views:

73

answers:

2

Javascript for Mozilla:

  while (result)
    {
    alert(result.childNodes[0].nodeValue);
    //txt=txt+result.childNodes[0].nodeValue+"<br/>";
    result=nodes.iterateNext();
    }

This is intended to return a series of strings from an xml file. When I use the alert line, it alerts as expected with the proper strings in a series. The "txt" variable on the commented line is supposed to go to an innerHTML further down in the function. But Firebug keeps telling me that the result.childNodes[0] is undefined. Why would it be defined in the alert but not the next line?

I hope that's enough code to determine the problem...if not I will post more.

Thanks for help

[edit]

this is the definition of result:

  var x=xmlDoc.responseXML;
  var nodes=x.evaluate(path, x, null, XPathResult.ANY_TYPE, null);
  var result=nodes.iterateNext();

I am retrieving XML

[edit]

okay I put the iterator in a for loop like this:

  for (var i=0; i<2; i++)
    {
    var res=(xmlNodes.childNodes[0].nodeValue);
    txt=txt+res+"<br/>";
    xmlNodes=xmlQuery.iterateNext();
    }

because I had a theory that once the iteration was null the loop would fail. So that's what happened--it worked until I set the loop one instance higher than the amount of nodes available. now I am trying to figure out how to get the "length" of the node-set. How do I do that?

A: 

now I am trying to figure out how to get the "length" of the node-set. How do I do that?

In XPath this is achieved using the standard XPath count() function.

count(someExpression)

evaluates to the number of nodes selected by someExpression.

Dimitre Novatchev
+1  A: 

I don't see any problems in the code you have shown so far. If childNodes[0] is undefined, then it has to be a text node or an empty node, and you should see an exception when trying to access a property such as nodeValue of childNodes[0] which is undefined. The exception will show up on alert or concatenation, or any other type of access.

This is the answer to your updated question.

now I am trying to figure out how to get the "length" of the node-set. How do I do that?

You can have the following types of node-sets returned from the evaluate function:

  • Iterators
  • Snapshots
  • First Nodes

I'll skip "first nodes" as that doesn't apply in this situation.

Iterators

With iterators, you only get an iterateNext() method for traversing nodes sequentially. Iterators refer to live nodes, meaning if the nodes in the document were to change while you are traversing the resultset, the iterator will become invalid.

Here's an example with using an iterator to go over each resulting node:

var results = doc.evaluate("expr", doc, null, ORDERED_SNAPSHOT, null);
var node;

while(node = results.iterateNext()) {
    console.log(node);
}

If you want to use iterators, and find the number of matching results, a wrapper function that iterates through all nodes and returns them in an array might be useful.

function evaluateXPath(document, expression) {
    var ANY_TYPE = XPathResult.ANY_TYPE;
    var nodes = document.evaluate(expression, document, null, ANY_TYPE, null);
    var results = [], node;

    while(node = nodes.iterateNext()) {
        results.push(node);
    }

    return results;
}

Get nodes as an array and loop the array:

var results = evaluateXPath(doc, "expr");

for(var i = 0; i < results.length; i++) {
    console.log(results[i]);
}

Snapshots

Snapshots provide a static result of the nodes at the time of querying. Changes to the document will not affect this snapshot. Useful interfaces here will be the snapshotLength property, and snapshotItem(index) function.

Here's an example using a snapshot result:

var ORDERED_SNAPSHOT = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
var results = doc.evaluate("expr", doc, null, ORDERED_SNAPSHOT, null);

for(var i = 0; i < results.snapshotLength; i++) {
    var node = results.snapshotItem(i);
    console.log(node);
}

See a working example.

It seems you are developing this for Firefox. Did you consider using E4X for this purpose? It provides a really easy interface for dealing with XML documents - for creating, manipulating, and querying.

Anurag
thanks that is very illuminating. Working on it last night, I ended up using snapshotLength of the query. I think I understand your examples pretty well, but I am not sure about one line (b/c I am pretty noob with javascript): var results=[], node; tell me if I am correct--it declares the variable results as an empty array, and also declares that the variable nodes is equal to results. Is that right?Well I will look into E4X, I guess I wanted to understand the basics of querying the XML DOM before moving to a library. I'm sure using the library would save time though...
Troy
@Troy - `var results = [], node;` will declare results to be an empty array, and node to be like `null`. We can declare multiple variables in one line as `var a, b, c, ...;`. and each variable can have a value as we did for results or nothing (which will initialize it with `undefined`). E4X is not a library. It's a specification that is only supported by Firefox amongst browsers but it makes XML processing a breeze. Checkout [this tutorial](https://developer.mozilla.org/en/e4x_tutorial) if you get time.
Anurag