Domanda

Using the example below, I would like to use xPath to find the first occurence of two different elements. For example, I want to figure out if b or d appears first. We can obviously tell that b appears before d (looking top-down, and not at the tree level). But, how can I solve this using xpath?

<a>
   <b>
   </b>
</a>
<c>
</c>
<d>
</d>

Right now, I find the node (b and d in this case) by getting the first element in the nodeset, which I find using the following code:

String xPathExpression = "//*[local-name()='b']";
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(xPathExpression);

and

String xPathExpression = "//*[local-name()='d']";
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(xPathExpression);

Now using xpath, I just can't figure out which comes first, b or d.

È stato utile?

Soluzione

You want to scan the tree in document order (the order the elements occur). As though by chance this is the default search order, and all you've got to do is select the first element which is a <b/> or <d/> node:

//*[local-name() = 'b' or local-name() = 'd'][1]

If you want the name, add another local-name(...) call:

local-name(//*[local-name() = 'b' or local-name() = 'd'][1])

Altri suggerimenti

If you wanted to use LINQ to XML to solve the same solution you can try the following:

XDocument xmlDoc = new XDocument(filepath);
XElement first = (from x in xmlDoc.Descendants()
            where x.Name == "b" || x.Name == "d"
            select x).FirstOrDefault();

Now you can run a simple if statement to determine if "b" or "d" was the first element found that matches our criteria.

 if(first.Name.Equals("b")
    //code for b being first
 else if(first.Name.Equals("d")
    //code for d being first

Per a commentator's suggestion your code would is cleaner to use a lambda expression instead of a full LINQ query, but this can sometimes be confusing if you are new to LINQ. The following is the exact same query for my XElement assignment above:

XElement first = xmlDoc.Descendants().FirstOrDefault(x => x.Name == "b" || x.Name == "d");

I hope that's what you're looking for if you were open to not using xpath.

This XPath expressions would work:

//*[local-name()='b' or local-name()='d'][1]

Or for a shorter solution, you could try this:

(//b|//d)[1]

Both expressions will select either b elements or d elements, in the order in which they appear, and only select the first element from the result set.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top