Cross-Browser JavaScript Xml Parsing

Cross-Browser Javascript XML Parsing

The following will work in all major browsers, including IE 6:

var parseXml;

if (typeof window.DOMParser != "undefined") {
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
} else if (typeof window.ActiveXObject != "undefined" &&
new window.ActiveXObject("Microsoft.XMLDOM")) {
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
} else {
throw new Error("No XML parser found");
}

Example usage:

var xml = parseXml("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);

Live demo:

var parseXml;

if (typeof window.DOMParser != "undefined") {

parseXml = function(xmlStr) {

return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");

};

} else if (typeof window.ActiveXObject != "undefined" &&

new window.ActiveXObject("Microsoft.XMLDOM")) {

parseXml = function(xmlStr) {

var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");

xmlDoc.async = "false";

xmlDoc.loadXML(xmlStr);

return xmlDoc;

};

} else {

throw new Error("No XML parser found");

}

var xml = parseXml("<foo>Stuff</foo>");

document.body.innerHTML = "Root element: " + xml.documentElement.nodeName;

Cross-Browser Javascript Parser for XML with Namespace

You could try another approach, by converting the XML to JSON server side, using a generic XSLT like http://code.google.com/p/xml2json-xslt/, and deliver to the browser only JSON.

It will add up a small overhead on the server response, but nothing compared to the amount of code and time spent on the browser to render XML.

With the exception of IE, with its impressive msxml, I think reading XML in common browsers is a real pain compared to JSON.

Parse XML using JavaScript

I'm guessing from your last question, asked 20 minutes before this one, that you are trying to parse (read and convert) the XML found through using GeoNames' FindNearestAddress.

If your XML is in a string variable called txt and looks like this:

<address>
<street>Roble Ave</street>
<mtfcc>S1400</mtfcc>
<streetNumber>649</streetNumber>
<lat>37.45127</lat>
<lng>-122.18032</lng>
<distance>0.04</distance>
<postalcode>94025</postalcode>
<placename>Menlo Park</placename>
<adminCode2>081</adminCode2>
<adminName2>San Mateo</adminName2>
<adminCode1>CA</adminCode1>
<adminName1>California</adminName1>
<countryCode>US</countryCode>
</address>

Then you can parse the XML with Javascript DOM like this:

if (window.DOMParser)
{
parser = new DOMParser();
xmlDoc = parser.parseFromString(txt, "text/xml");
}
else // Internet Explorer
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(txt);
}

And get specific values from the nodes like this:

//Gets house address number
xmlDoc.getElementsByTagName("streetNumber")[0].childNodes[0].nodeValue;

//Gets Street name
xmlDoc.getElementsByTagName("street")[0].childNodes[0].nodeValue;

//Gets Postal Code
xmlDoc.getElementsByTagName("postalcode")[0].childNodes[0].nodeValue;

JSFiddle


Feb. 2019 edit:

In response to @gaugeinvariante's concerns about xml with Namespace prefixes.
Should you have a need to parse xml with Namespace prefixes, everything should work almost identically:

NOTE: this will only work in browsers that support xml namespace prefixes such as Microsoft Edge

// XML with namespace prefixes 's', 'sn', and 'p' in a variable called txt

txt = `

<address xmlns:p='example.com/postal' xmlns:s='example.com/street' xmlns:sn='example.com/streetNum'>

<s:street>Roble Ave</s:street>

<sn:streetNumber>649</sn:streetNumber>

<p:postalcode>94025</p:postalcode>

</address>`;

//Everything else the same

if (window.DOMParser)

{

parser = new DOMParser();

xmlDoc = parser.parseFromString(txt, "text/xml");

}

else // Internet Explorer

{

xmlDoc = new ActiveXObject("Microsoft.XMLDOM");

xmlDoc.async = false;

xmlDoc.loadXML(txt);

}

//The prefix should not be included when you request the xml namespace

//Gets "streetNumber" (note there is no prefix of "sn"

console.log(xmlDoc.getElementsByTagName("streetNumber")[0].childNodes[0].nodeValue);

//Gets Street name

console.log(xmlDoc.getElementsByTagName("street")[0].childNodes[0].nodeValue);

//Gets Postal Code

console.log(xmlDoc.getElementsByTagName("postalcode")[0].childNodes[0].nodeValue);

Crossbrowser XML manipulation and parse with XSL (Chrome, Firefoz and IE 8/11)

See https://msdn.microsoft.com/en-us/library/dn423948(v=vs.85).aspx, in IE 11 you need to use new ActiveXObject('program.id') inside of a try/catch, the check for the window property does not work.

Furthermore, the native IE DOM documents you create with DOMParser in IE do not support transformNode, so if you know you need an XML DOM document in IE to do XSLT transformation then you need to make sure you create an MSXML DOM document with new ActiveXObject and you need to do try to do that first in your code with try/catch, before you try to instantiate DOMParser.

So for the XML parsing from a string I would use

  function getXmlDom(content) {
var xmlDom;
try {
xmlDom = new ActiveXObject('Msxml2.DOMDocument.6.0');
xmlDom.loadXML(content);
}
catch (e) {
try {
xmlDom = new ActiveXObject('Msxml2.DOMDocument.3.0');
xmlDom.loadXML(content);
}
catch (e2) {
xmlDom = (new DOMParser()).parseFromString(content, 'application/xml');
}
}

return xmlDom;
}

as done in http://home.arcor.de/martin.honnen/javascript/2016/test2016022301.html.

How do I detect XML parsing errors when using Javascript's DOMParser in a cross-browser way?

This is the best solution I've come up with.

I attempt to parse a string that is intentionally invalid XML and observe the namespace of the resulting <parsererror> element. Then, when parsing actual XML, I can use getElementsByTagNameNS to detect the same kind of <parsererror> element and throw a Javascript Error.

// My function that parses a string into an XML DOM, throwing an Error if XML parsing fails
function parseXml(xmlString) {
var parser = new DOMParser();
// attempt to parse the passed-in xml
var dom = parser.parseFromString(xmlString, 'application/xml');
if(isParseError(dom)) {
throw new Error('Error parsing XML');
}
return dom;
}

function isParseError(parsedDocument) {
// parser and parsererrorNS could be cached on startup for efficiency
var parser = new DOMParser(),
errorneousParse = parser.parseFromString('<', 'application/xml'),
parsererrorNS = errorneousParse.getElementsByTagName("parsererror")[0].namespaceURI;

if (parsererrorNS === 'http://www.w3.org/1999/xhtml') {
// In PhantomJS the parseerror element doesn't seem to have a special namespace, so we are just guessing here :(
return parsedDocument.getElementsByTagName("parsererror").length > 0;
}

return parsedDocument.getElementsByTagNameNS(parsererrorNS, 'parsererror').length > 0;
};

Note that this solution doesn't include the special-casing needed for Internet Explorer. However, things are much more straightforward in IE. XML is parsed with a loadXML method which returns true or false if parsing succeeded or failed, respectively. See http://www.w3schools.com/xml/xml_parser.asp for an example.

Parsing an xml tag with JavaScript

Your xml is not well formed. An xml element can have either text or child elements as content. Instead, try this

<system os="Xp">
<version>1.9</version>
<version>2.0</version>
</system>

or that

<system>
<os>Xp</os>
<version>1.9</version>
<version>2.0</version>
</system>


Related Topics



Leave a reply



Submit