Reputation: 16641
I'm trying to do a basic thing in Saxon HE 9.7 with xquery. I have an xquery that returns a set of elements. Then I want to query each element separately. But I can't seem to figure out how to do a query on just that element. I thought setContextItem()
would do the trick, but that doesn't work.
I've created a simple example that illustrates my problem. I am looping over <element>
and then I want to retrieve the <name>
for each element. But my query returns nothing, because it is actually querying the complete xml, not just the element. If I change the inner query to //name
it returns all name tags in the document.
File data/example.xml:
<root>
<element>
<name>1</name>
</element>
<element>
<name>2</name>
</element>
</root>
Java code:
public static void main(String[] args) throws SaxonApiException
{
Processor proc = new Processor(false);
XPathCompiler xpath = proc.newXPathCompiler();
DocumentBuilder builder = proc.newDocumentBuilder();
XdmNode rootNode = builder.build(new File("data/example.xml"));
String xquery = "/root/element";
XPathSelector selector = xpath.compile(xquery).load();
selector.setContextItem(rootNode);
for (XdmItem item : selector)
{
xquery = "/element/name";
XPathSelector selector2 = xpath.compile(xquery).load();
selector2.setContextItem(item);
System.out.println("item=" + item);
if (selector2.iterator().hasNext())
System.out.println("name=" + selector2.iterator().next());
else
System.out.println("Not found");
}
}
My Maven dependency:
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.7.0-4</version>
</dependency>
Result:
item=<element>
<name>1</name>
</element>
Not found
item=<element>
<name>2</name>
</element>
Not found
Upvotes: 1
Views: 373
Reputation: 89285
In XPath, /
at the beginning always references the document node. If you want your XPath (the one inside the loop) to respect context element, try to make it starts with a full-stop (.
) :
xquery = "./name";
Or just remove the /
completely * :
xquery = "name";
*) this will work for your case because child::
is the default axis which will be used if none is explicitly mentioned
Upvotes: 3