74

Are there any cross-browser / cross-platform ways to parse XML files in Javascript?

John Slegers
  • 45,213
  • 22
  • 199
  • 169
sazr
  • 24,984
  • 66
  • 194
  • 362
  • 3
    look at http://stackoverflow.com/questions/649614/xml-parsing-in-javascript – Milan Jaric Oct 31 '11 at 03:35
  • Isnt' this a duplicate of https://stackoverflow.com/questions/649614/xml-parsing-of-a-variable-string-in-javascript/8412989#8412989 ? – lucascaro Nov 13 '18 at 16:59
  • [This question](https://stackoverflow.com/questions/83405/xml-parser-for-javascript/83584#83584) was the earliest request for a cross-platform XML parser, but it was closed for being off-topic as it asked for an off-site resource (just as this question was). – Graham Nov 13 '18 at 23:09

3 Answers3

72

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;
Liam
  • 27,717
  • 28
  • 128
  • 190
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • 2
    This works, except in IE9 in standards mode. In IE9 standards mode to correct the issue, you just need to reform your initial if statement to be something like: if (window.DOMParser && typeof XMLDocument !== "undefined") – GotDibbs Aug 21 '12 at 16:09
  • @GotDibbs: Really? The above example works fine for me in IE 9 standards. – Tim Down Sep 07 '12 at 14:50
  • Yep. Not sure if there's some other setting getting in the way here, but the moment I go into the dev toolbar and switch the browser mode to IE9 and document mode to IE9 standards it bombs without that additional check. – GotDibbs Sep 07 '12 at 15:06
  • 1
    @GotDibbs: I know it's been a while, but here's a jsFiddle that works fine for me in IE 9 standards mode: http://jsfiddle.net/3s7Ly/1/ – Tim Down May 14 '13 at 09:53
  • @TimDown: If it is a working version, would you mind editing that into your answer? – nhahtdh Jul 15 '15 at 07:45
  • @nhahtdh: The code in the jsfiddle is exactly the same as in the answer. I haven't found the additional check to be necessary. – Tim Down Jul 15 '15 at 08:11
  • @TimDown Is this code still reliable for all browsers (namely Chrome, Firefox, IE)? Or better still, is there a version of this code snippet that doesn't rely on ActiveX objects? – Bradley Jan 27 '16 at 10:39
  • @Bradley: `DOMParser` has now been [standardized](https://w3c.github.io/DOM-Parsing/#the-domparser-interface) so this code shouldn't get any less reliable. It works in current versions of all major browsers. It only falls back to the ActiveX stuff in old versions of IE; if you don't care about those then you can remove the ActiveX code branch, but it won't do any harm if left in. – Tim Down Jan 27 '16 at 11:57
7

Consider using jQuery.parseXML.

Note that old JQuery's code (pre 2.x) is essentially identical to one proposed in the accepted answer and can be found at http://code.jquery.com/jquery-1.9.1.js, partial version below:

// Cross-browser xml parsing
parseXML: function( data ) {
    ...
    try {
        if ( window.DOMParser ) { // Standard
            tmp = new DOMParser();
            xml = tmp.parseFromString( data , "text/xml" );
        } else { // IE
            xml = new ActiveXObject( "Microsoft.XMLDOM" );
            xml.async = "false";
            xml.loadXML( data );
        }
    } catch( e ) {
        xml = undefined;
    }
    ...
}

Starting JQuery 2.x code changed to skip ActiveX branch, if you still need it - use older version of JQuery or inline ActiveX parsing. Partial code from http://code.jquery.com/jquery-2.0.0.js:

// Cross-browser xml parsing
parseXML: function( data ) {
    var xml, tmp;
    .....
    // Support: IE9
    try {
        tmp = new DOMParser();
        xml = tmp.parseFromString( data , "text/xml" );
    } catch ( e ) {
        xml = undefined;
    }
    .....
},
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 2
    jQuery.parseXml can be pretty slow. I would suggest looking at the post from @TimDown – GotDibbs Aug 21 '12 at 16:08
  • 8
    Maybe it was a year ago, but looking at the source code of jQuery (http://code.jquery.com/jquery-1.9.1.js), I fail to see the difference from the TimDown's answer (omitting some error-handling logic). – zbstof Feb 09 '13 at 08:15
  • @Zotov I've inlined your comment (post was rightfully downvoted as link-only, and your comment looked worth inlining rather than deleting the post). – Alexei Levenkov Dec 03 '17 at 18:02
4

If you need to parse large XML documents that you may not be able to completely hold in memory, consider using a SAX style parser like this one: https://github.com/isaacs/sax-js/

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196