208
votes

I have a variable string that contains well-formed and valid XML. I need to use JavaScript code to parse this feed.

How can I accomplish this using (browser-compatible) JavaScript code?

10

10 Answers

91
votes

Update: For a more correct answer see Tim Down's answer.

Internet Explorer and, for example, Mozilla-based browsers expose different objects for XML parsing, so it's wise to use a JavaScript framework like jQuery to handle the cross-browsers differences.

A really basic example is:

var xml = "<music><album>Beethoven</album></music>";

var result = $(xml).find("album").text();

Note: As pointed out in comments; jQuery does not really do any XML parsing whatsoever, it relies on the DOM innerHTML method and will parse it like it would any HTML so be careful when using HTML element names in your XML. But I think it works fairly good for simple XML 'parsing', but it's probably not suggested for intensive or 'dynamic' XML parsing where you do not upfront what XML will come down and this tests if everything parses as expected.

327
votes

Updated answer for 2017

The following will parse an XML string into an XML document in all major browsers. Unless you need support for IE <= 8 or some obscure browser, you could use the following function:

function parseXml(xmlStr) {
   return new window.DOMParser().parseFromString(xmlStr, "text/xml");
}

If you need to support IE <= 8, the following will do the job:

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");
}

Once you have a Document obtained via parseXml, you can use the usual DOM traversal methods/properties such as childNodes and getElementsByTagName() to get the nodes you want.

Example usage:

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

If you're using jQuery, from version 1.5 you can use its built-in parseXML() method, which is functionally identical to the function above.

var xml = $.parseXML("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);
19
votes

Most examples on the web (and some presented above) show how to load an XML from a file in a browser compatible manner. This proves easy, except in the case of Google Chrome which does not support the document.implementation.createDocument() method. When using Chrome, in order to load an XML file into a XmlDocument object, you need to use the inbuilt XmlHttp object and then load the file by passing it's URI.

In your case, the scenario is different, because you want to load the XML from a string variable, not a URL. For this requirement however, Chrome supposedly works just like Mozilla (or so I've heard) and supports the parseFromString() method.

Here is a function I use (it's part of the Browser compatibility library I'm currently building):

function LoadXMLString(xmlString)
{
  // ObjectExists checks if the passed parameter is not null.
  // isString (as the name suggests) checks if the type is a valid string.
  if (ObjectExists(xmlString) && isString(xmlString))
  {
    var xDoc;
    // The GetBrowserType function returns a 2-letter code representing
    // ...the type of browser.
    var bType = GetBrowserType();

    switch(bType)
    {
      case "ie":
        // This actually calls into a function that returns a DOMDocument 
        // on the basis of the MSXML version installed.
        // Simplified here for illustration.
        xDoc = new ActiveXObject("MSXML2.DOMDocument")
        xDoc.async = false;
        xDoc.loadXML(xmlString);
        break;
      default:
        var dp = new DOMParser();
        xDoc = dp.parseFromString(xmlString, "text/xml");
        break;
    }
    return xDoc;
  }
  else
    return null;
}
13
votes

Marknote is a nice lightweight cross-browser JavaScript XML parser. It's object-oriented and it's got plenty of examples, plus the API is documented. It's fairly new, but it has worked nicely in one of my projects so far. One thing I like about it is that it will read XML directly from strings or URLs and you can also use it to convert the XML into JSON.

Here's an example of what you can do with Marknote:

var str = '<books>' +
          '  <book title="A Tale of Two Cities"/>' +
          '  <book title="1984"/>' +
          '</books>';

var parser = new marknote.Parser();
var doc = parser.parse(str);

var bookEls = doc.getRootElement().getChildElements();

for (var i=0; i<bookEls.length; i++) {
    var bookEl = bookEls[i];
    // alerts "Element name is 'book' and book title is '...'"
    alert("Element name is '" + bookEl.getName() + 
        "' and book title is '" + 
        bookEl.getAttributeValue("title") + "'"
    );
}
8
votes

I've always used the approach below which works in IE and Firefox.

Example XML:

<fruits>
  <fruit name="Apple" colour="Green" />
  <fruit name="Banana" colour="Yellow" />
</fruits>

JavaScript:

function getFruits(xml) {
  var fruits = xml.getElementsByTagName("fruits")[0];
  if (fruits) {
    var fruitsNodes = fruits.childNodes;
    if (fruitsNodes) {
      for (var i = 0; i < fruitsNodes.length; i++) {
        var name = fruitsNodes[i].getAttribute("name");
        var colour = fruitsNodes[i].getAttribute("colour");
        alert("Fruit " + name + " is coloured " + colour);
      }
    }
  }
}
8
votes

Apparently jQuery now provides jQuery.parseXML http://api.jquery.com/jQuery.parseXML/ as of version 1.5

jQuery.parseXML( data ) Returns: XMLDocument

2
votes

Please take a look at XML DOM Parser (W3Schools). It's a tutorial on XML DOM parsing. The actual DOM parser differs from browser to browser but the DOM API is standardised and remains the same (more or less).

Alternatively use E4X if you can restrict yourself to Firefox. It's relatively easier to use and it's part of JavaScript since version 1.6. Here is a small sample usage...

//Using E4X
var xmlDoc=new XML();
xmlDoc.load("note.xml");
document.write(xmlDoc.body); //Note: 'body' is actually a tag in note.xml,
//but it can be accessed as if it were a regular property of xmlDoc.
1
votes

Disclaimer : I've created fast-xml-parser

I have created fast-xml-parser to parse a XML string into JS/JSON object or intermediate traversal object. It is expected to be compatible in all the browsers (however tested on Chrome, Firefox, and IE only).

Usage

var options = { //default
    attrPrefix : "@_",
    attrNodeName: false,
    textNodeName : "#text",
    ignoreNonTextNodeAttr : true,
    ignoreTextNodeAttr : true,
    ignoreNameSpace : true,
    ignoreRootElement : false,
    textNodeConversion : true,
    textAttrConversion : false,
    arrayMode : false
};

if(parser.validate(xmlData)){//optional
    var jsonObj = parser.parse(xmlData, options);
}

//Intermediate obj
var tObj = parser.getTraversalObj(xmlData,options);
:
var jsonObj = parser.convertToJson(tObj);

Note: It doesn't use DOM parser but parse the string using RE and convert it into JS/JSON object.

Try it online, CDN

0
votes
<script language="JavaScript">
function importXML()
{
    if (document.implementation && document.implementation.createDocument)
    {
            xmlDoc = document.implementation.createDocument("", "", null);
            xmlDoc.onload = createTable;
    }
    else if (window.ActiveXObject)
    {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.onreadystatechange = function () {
                    if (xmlDoc.readyState == 4) createTable()
            };
    }
    else
    {
            alert('Your browser can\'t handle this script');
            return;
    }
    xmlDoc.load("emperors.xml");
}

function createTable()
{
    var theData="";
    var x = xmlDoc.getElementsByTagName('emperor');
    var newEl = document.createElement('TABLE');
    newEl.setAttribute('cellPadding',3);
    newEl.setAttribute('cellSpacing',0);
    newEl.setAttribute('border',1);
    var tmp = document.createElement('TBODY');
    newEl.appendChild(tmp);
    var row = document.createElement('TR');
    for (j=0;j<x[0].childNodes.length;j++)
    {
            if (x[0].childNodes[j].nodeType != 1) continue;
            var container = document.createElement('TH');
            theData = document.createTextNode(x[0].childNodes[j].nodeName);
            container.appendChild(theData);
            row.appendChild(container);
    }
    tmp.appendChild(row);
    for (i=0;i<x.length;i++)
    {
            var row = document.createElement('TR');
            for (j=0;j<x[i].childNodes.length;j++)
            {
                    if (x[i].childNodes[j].nodeType != 1) continue;
                    var container = document.createElement('TD');
                    var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);
                    container.appendChild(theData);
                    row.appendChild(container);
            }
            tmp.appendChild(row);
    }
    document.getElementById('writeroot').appendChild(newEl);
}
</script>
</HEAD>

<BODY onLoad="javascript:importXML();">
<p id=writeroot> </p>
</BODY>

For more info refer this http://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/

-1
votes

You can also through the jquery function($.parseXML) to manipulate xml string

example javascript:

var xmlString = '<languages><language name="c"></language><language name="php"></language></languages>';
var xmlDoc = $.parseXML(xmlString);
$(xmlDoc).find('name').each(function(){
    console.log('name:'+$(this).attr('name'))
})