This question already has an answer here:
-
Generate/get xpath from XML node java
8 answers
I have NodeList of elements with specific name and I would like to have XPath of all of theese nodes.
I cannot find a way how to do that.
NodeList nList = doc.getElementsByTagName("definition");
for (int i = 0; i < nList.getLength(); i++) {
Node node = nList.item(i);
System.out.println(node.GET_XPATH());
}
I'm looking for a method like GET_XPATH()
Do someone know how to do that? Or is it even possible?
If it is possible with XSLT can use it as well, but prefer if someone know about this possibility in Java.
REASON:
I need a set of pointers to XML library. Pointers to definition elements.
EXAMPLE
Input:
<odML>
<section>
<type>experiment</type>
<name>Experiment</name>
<definition></definition>
<property>
<definition></definition>
</property>
<property>
<definition></definition>
<value>
<definition></definition>
</value>
</property>
</section>
<definition></definition>
</odML>
Output:
/odML/section/definition
/odML/section/property[1]/definition
/odML/section/property[2]/definition
/odML/section/property[2]/value/definition
/odML/definition
The following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="//definition">
<xsl:for-each select="ancestor::*">
<xsl:text>/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:if test="(preceding-sibling::*|following-sibling::*)[name()=name(current())]">
<xsl:text>[</xsl:text>
<xsl:value-of select="count(preceding-sibling::*[name()=name(current())]) + 1"/>
<xsl:text>]</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>/definition</xsl:text>
<xsl:if test="position()!=last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied to your example input, will return:
/odML/section/definition
/odML/section/property[1]/definition
/odML/section/property[2]/definition
/odML/section/property[2]/value/definition
/odML/definition
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="definition">
<xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="*" mode="path">
<xsl:value-of select="concat('/',name())"/>
<xsl:if test="../*[name()=name(current())][2]">
<xsl:value-of select=
"concat('[',count(preceding-sibling::*[name()=name(current())])+1,']')"/>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
When applied on the provided source XML document:
<odML>
<section>
<type>experiment</type>
<name>Experiment</name>
<definition></definition>
<property>
<definition></definition>
</property>
<property>
<definition></definition>
<value>
<definition></definition>
</value>
</property>
</section>
<definition></definition>
</odML>
produces the wanted, correct result:
/odML/section/definition
/odML/section/property[1]/definition
/odML/section/property[2]/definition
/odML/section/property[2]/value/definition
/odML/definition