XPath Context – Where am I in the DOM?
So I was helping a colleague with a code review when I stumbled on something that has been bugging me for a while. I’ve always chalked it up to dom4j – the popular java XML library. It turns out, that it is not dom4j at all – it is XPath. The problem is that when you select a node with an XPath expression, there is context that applies.
I used to think that each node is a self-contained XML document – this is definitely not true.
Considering this quick java app, in a maven project with a POM:
@SuppressWarnings( "all" ) public class DomXpathTest { public static void main( final String[] args ) throws Exception { Document document = DocumentHelper.parseText( FileUtils.readFileToString( new File( "pom.xml" ) ).replaceFirst( "<project.*>", "<project>" ) ); List< Node > nodes = document.selectNodes( "//dependency" ); for( Node node : nodes ) { // Node artifact = node.selectSingleNode( "//artifactId" ); Node artifact = node.selectSingleNode( "./artifactId" ); System.out.println( artifact.asXML() ); System.out.println( "---------------------------------------------" ); } } }
Something like this (which is commented out):
node.selectSingleNode( "//artifactId" );
Will in fact select the first artifactId node encountered from the whole document. Which is why, instead, we need to instead use “./” to essentially say “select the first artifactId that is a direct descendant from my current position”. You can also use “.//” or any other variant.
Leave a comment