0

I have what should be an extremely simple xml question, which has me completely lost. I have the following XML file:

<items>
    <item percentFinished="0.0">
        <details>
            <name>Objective 1</name>
            <description>Test objective</description>
        </details>
    </item>
    <item percentFinished="0.0">
        <details>
            <name>Objective 2</name>
            <description>Another objective</description>
        </details>
        <subitems>
            <item percentFinished="0.0">
                <details>
                    <name>Sub Objective 1</name>
                    <description>A Sub Objective</description>
                </details>
            </item>
        </subitems>
    </item>
</items>

The javascript file is eventually going to be creating dynamic html from the xml file, but for now I am just trying to get the parsing down properly. Here is my current javascript file:

if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
} else {// code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","defaultData.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
// HTML Div
var outer = document.createElement('div');
var div = document.createElement('div');

// Gets the item list from the XML
var itemList = selectValue(xmlDoc,"items/item");
var item = itemList.iterateNext();
while (item!=null) {
    parseItemNode(item,div);
    item = itemList.iterateNext();
}
outer.appendChild(div);
document.write(outer.innerHTML);

function parseItemNode(itemNode, parentNode) {
    var details = selectValue(itemNode,"item/details").iterateNext();
    var name = selectValue(details,"name").stringValue;
}
function selectValue(context,xpath) {
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        var nsResolver = document.createNSResolver( context.ownerDocument == null ? context.documentElement : context.ownerDocument.documentElement );
        return document.evaluate(xpath, context, nsResolver, XPathResult.ANY_TYPE,null); 
    } else {
        return context.selectNodes(xpath);
    }
}

So the issue I am having is: the details variable in the parseItemNode() function is null. I had a look at the selectValue(itemNode,"item/details") call in the debugger, and the result is this:

XPathResult {invalidIteratorState: false, resultType: 4, iterateNext: function, snapshotItem: function, ANY_TYPE: 0…}
  booleanValue: [Exception: TypeError: Failed to read the 'booleanValue' property from 'XPathResult': The result type is not a boolean.]
  invalidIteratorState: false
  numberValue: [Exception: TypeError: Failed to read the 'numberValue' property from 'XPathResult': The result type is not a number.]
  resultType: 4
  singleNodeValue: [Exception: TypeError: Failed to read the 'singleNodeValue' property from 'XPathResult': The result type is not a single node.]
  snapshotLength: [Exception: TypeError: Failed to read the 'snapshotLength' property from 'XPathResult': The result type is not a snapshot.]
  stringValue: [Exception: TypeError: Failed to read the 'stringValue' property from 'XPathResult': The result type is not a string.]
  __proto__: XPathResult

At this point, I have no idea what is going on or how to fix it, and I haven't been able to dig up anything on Google. Can someone explain to me what is happening, and how I should make it work correctly?

6
  • 1
    Any reason you don't want to use jQuery? The jquery get() function auto-parses xml for you, along with handling the XHR request: api.jquery.com/jQuery.get Commented Nov 12, 2014 at 21:29
  • A simple example of using the jQuery get function to parse XML: stackoverflow.com/questions/226663/parse-rss-with-jquery/… Commented Nov 12, 2014 at 21:34
  • jQuery selectors do not support namespaces and are much slower and need a lot more memory. Problem is current IEs do not support Xpath at all, you need to use a JS implementation. Commented Nov 12, 2014 at 21:47
  • David, the issue with the example you showed is why I am using XPath: the subitems section makes it such that calling: $(data).find("item") returns a list of 4, since it includes the subitems, which I don't want parsed at this moment (they will be parsed later). ADASein, the weird thing is that iterateNext() isn't throwing an exception, I just get hit with the null pointer when I try to use the result of iterateNext(). Commented Nov 12, 2014 at 21:54
  • Very simple. Just use $(data).find(">item") to get just the immediate children. I'm pretty sure CSS selectors can do everything XPath does, or at least everything you need to do in this example. Commented Nov 12, 2014 at 21:56

1 Answer 1

3

The details variable in the parseItemNode() function is null because the itemNode variable is the <item/> node itself. Therefore, applying Xpath item/details on this <item/> will return the <details/> that are child of <item/> that are child of <item/>, hence, no node.

Switch the XPath expression to 'details' only since you're applying it on <item/> node.

Btw, XSLT is designed to build (X)HTML upon any XML source.

Sign up to request clarification or add additional context in comments.

1 Comment

Wow. I don't know how I missed that, especially considering I didn't make the mistake on the line immediately below it... I'll have to chalk that one up as tunnel-vision. Thanks for the help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.