0

I'm trying to parse some XML results in javascript to use with phonegap. As it stands my xml layout is:

<Results>
     <Result>
          <FirstName>John</FirstName>
          <Surname>Beech</Surname>
          <Company>CompanyName</Company>
          <Job_Title>Property Department</Job_Title>
          <UserID>184</UserID>
          <CompanyID>CompanyID</CompanyID>
          </Result>
     <Result>
          <FirstName>Rosie</FirstName>
          <Surname>Beech</Surname>
          <Company>CompanyName</Company>
          <Job_Title>Job Title</Job_Title>
          <UserID>10494</UserID>
          <CompanyID>17322</CompanyID>
     </Result>
</Results>

And I'm using the following javascript to at the moment just alert out the responses, but eventually I want to create a table of the responses.

<script language="javascript" type="text/javascript">
    window.onload = function () {
        $.ajax({
            type: 'GET',
            url: 'Lookupbysurname.aspx?surname=beech',
            dataType: 'html',
            success: function (data) {


                try {
                    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                    xmlDoc.async = "false";
                    xmlDoc.loadXML(data);
                }
                catch (e) {
                    try {
                        parser = new DOMParser();
                        xmlDoc = parser.parseFromString(data, "text/xml");
                    }
                    catch (e) {
                        alert(e.message);
                        return;
                    }
                }

                for (var i = 0; i < xmlDoc.getElementsByTagName("CompanyID")[0].childNodes[0].length; i++) {
                    alert(xmlDoc.getElementsByTagName("CompanyID")[0].childNodes[0].nodeValue);
                }
            }
        });
    }
</script>

However at the moment it's only alerting the same response out over and over. Have I put the loop together wrong? Loops in JS arent my forte! Any help will be appreciated.

MissCoder87
  • 2,669
  • 10
  • 47
  • 82
  • FWIW, since you're already using jQuery, you can simplify your XML parsing logic and just use [$.parseXML](http://api.jquery.com/jQuery.parseXML/). – T.J. Crowder May 05 '12 at 13:52

2 Answers2

2

However at the moment it's only alerting the same response out over and over.

Of course it is, you're using the same index (0) each time.

But the TL;DR version of this is: Since you're already using jQuery, just use jQuery. You can not only use it to replace your complex parser creation logic by using $.parseXML instead, but you can also use jQuery to do the loop. Here I assume you're trying to loop over CompanyID elements:

var xmlDoc = $.parseXML(data);
var $xml = $(xmlDoc);
$xml.find("CompanyID").each(function() {
    alert($(this).text());
});

Live example | source


Building up to that, your code is using 0 rather than i:

for (var i = 0; i < xmlDoc.getElementsByTagName("CompanyID")[0].childNodes[0].length; i++) {
    // This is always 0 -----------------------------------------v 
    alert(xmlDoc.getElementsByTagName("CompanyID")[0].childNodes[0].nodeValue);
}

You want to use i, not 0, if you want to loop over the child nodes.


But that loop is hugely inefficient, because you're going back and repeating the lookup each time. Instead:

var nodes = xmlDoc.getElementsByTagName("CompanyID")[0].childNodes;
for (var i = 0; i < nodes.length; i++) {
    alert(nodes[i].nodeValue);
}

Or alternately, of course, use firstChild and nextSibling:

var node;
for (node = xmlDoc.getElementsByTagName("CompanyID")[0].firstChild;
     node;
     node = node.nextSibling) {
    alert(node.nodeValue);
}

But looking at your XML, I suspect you want to loop over CompanyID nodes, rather than the child nodes of them:

var node;
for (node = xmlDoc.getElementsByTagName("CompanyID");
     node;
     node = node.nextSibling) {
    alert(node.firstChild.nodeValue);
}

But again, you can do this with dramatically less code by making more use of the library you're already using. :-)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • You should also use `nodes[i]` instead of `nodes[0]` (second last box) – Ulrich Dangel May 05 '12 at 13:53
  • Thanks a lot for this! Will it work cross domain? Js will be local to the phone and XML on remote server – MissCoder87 May 05 '12 at 14:16
  • @TomBeech: The XML part is unrelated to domains; we've picked up at the point where you have the XML text in `data`. (And actually, you may not even need the `parseXML` call; if the server returns the correct MIME type, jQuery will parse it for you before giving it to the callback.) It's the `ajax` calls you need to worry about. My impression, based on [this question](http://stackoverflow.com/questions/7154988) and some Googling, is that normally you're fine, but I haven't used PhoneGap myself. – T.J. Crowder May 05 '12 at 14:26
2

You can avoid using parseXML() by using XMLHttpRequest's responseXML property, which is wrapped in jQuery as follows:

$.ajax({
    type: 'GET',
    url: 'Lookupbysurname.aspx?surname=beech',
    dataType: 'xml',
    success: function(xmlDoc) {
        alert(xmlDoc.getElementsByTagName("CompanyID")[0].nodeValue);
    }
});

Since you're already using jQuery, you could use jQuery to traverse the XML:

var $xml = $(xmlDoc);
$xml.find("CompanyID").each(function() {
    alert( $(this).text() );
});

Full code:

$.ajax({
    type: 'GET',
    url: 'Lookupbysurname.aspx?surname=beech',
    dataType: 'xml',
    success: function(xmlDoc) {
        var $xml = $(xmlDoc);
        $xml.find('CompanyID').each(function() {
            alert( $(this).text() );
        });
    }
});
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thanks for this, where is xmlDoc defined in this? i'm getting an error that xmlDoc is not defined and that xmlDoc.getElementsByTagName is not a function - Tom – MissCoder87 May 05 '12 at 15:31
  • Sorry - Was being special, fixed the xmlDoc not defined, but still getElementsByTagName isnt working - http://paste.tiag.me/22 Tom – MissCoder87 May 05 '12 at 15:38
  • @TomBeech: Sorry, I meant that you need to put the second block of code in the `success` method. I'll update my answer. – Tim Down May 05 '12 at 17:05