XPath - abbreviation for the position () function

Can anyone explain what is the difference between

/root/a[position()=1 or position()=2 

and

 /root/a[1 or 2] 

? I would suggest that the second would be an abbreviated form of the first, but the Java XPath processor (Sun JDK 1.6.0) thinks differently. The following is my test application.

The libxml2 library and the XPath db2 processor consider these paths different. So this is not like a JDK error.

 import java.io.*; import javax.xml.xpath.*; import org.w3c.dom.*; import org.xml.sax.InputSource; public class XPathTest { public static void main(String[] args) throws Exception { //String xpathStr = "/root/a[position()=1 or position()=2]"; String xpathStr = "/root/a[1 or 2]"; XPathFactory xpf = XPathFactory.newInstance(); XPath xp = xpf.newXPath(); Reader irdr = new StringReader( "<root><a name=\"first\"/><a name=\"second\"/><a name=\"third\"/></root>"); InputSource isrc = new InputSource(irdr); XPathExpression expr = xp.compile(xpathStr); Object result = expr.evaluate(isrc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); Element element = (Element) node; System.out.print(element.getNodeName() + " " + element.getAttributeNode("name")); System.out.println(); } } } 
+4
source share
4 answers

I do not think that [1 or 2] evaluates what you think it evaluates. or works with two boolean values. I suspect that both 1 and 2 are evaluated as true. Therefore, this expression is evaluated as true and does practically nothing and returns all elements.

In the general case, position() can be used in expressions like [position() <= 5] , while the index address can only select one element, for example [5] .

+4
source

If the value in square brackets is the number [N] , it is interpreted as [position()=N] . But [1 or 2] not a number, so this rule does not apply.

+1
source

[1 or 2] also evaluates the "always true" predicate in .Net, so this behavior seems consistent:

Here is the output from XPath.NET 3.5 XmlDocument

  // Returns first, second var ndl = dom.SelectNodes(@"/root/a[position()=1 or position()=2]"); // Returns first, second and third ndl = dom.SelectNodes(@"/root/a[1 or 2]"); // Returns first, second ndl = dom.SelectNodes(@"/root/a[1] | /root/a[2]"); 

Edit

In XPath 2, you can use the index-of and exists sequence functions to determine if a given position is contained in a sequence of values:

 /root/a[exists(index-of((1,2), position()))] 
0
source

The numerical value in [] considered as an index. OR does not work for indexes in your path ( [1 or 2] ). The correct way to use position() .

0
source

All Articles