Can anyone explain what's the difference between
/root/a[position()=1 or position()=2
and
/root/a[1 or 2]
? I'd assume the 2nd to be abbreviated form of the 1st, but Java XPath (Sun JDK 1.6.0) processor thinks otherwise. Following is my test application.
libxml2 library and also db2 XPath processor consider these paths different too. So it doesn't look like JDK bug.
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();
}
}
}
Single Slash “/” – Single slash is used to create Xpath with absolute path i.e. the xpath would be created to start selection from the document node/start node.
An expression is evaluated to yield an object, which has one of the following four basic types: node-set (an unordered collection of nodes without duplicates) boolean (true or false) number (a floating-point number)
A context node is the node the XPath processor is currently looking at. The context node changes as the XPath processor evaluates a query. If you pass a document to the XPath processor, the root node is the initial context node.
I don't think [1 or 2]
is evaluating how you think it is evaluating. or
works on two boolean values. I suspect both 1
and 2
are evaluating as true. Therefore this expression is evaluating as true and essentially doing nothing, and will return all elements.
In general, position()
can be used in expressions like [position() <= 5]
whereas the index address can only ever select one element like [5]
.
If the value in square brackets is a number [N]
, it is interpreted as [position()=N]
. But [1 or 2]
is not a number, so this rule does not apply.
[1 or 2]
evaluates to an "always true" predicate in .Net as well, so this behaviour appears consistent:
Here's the output from a the XPath of a .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 sequence functions index-of
and exists
to determine whether the given position is contained in a sequence of values:
/root/a[exists(index-of((1,2), position()))]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With