1

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
Ondrej Havlicek
  • 170
  • 5
  • 12
  • I'm sorry what? xPath is query language used to execute queries against a document or node...I'm not sure what you're hoping to achieve – MadProgrammer May 07 '15 at 23:56
  • I need a reverse process. I have a set of XML and I need for every of this XML have a list of XPaths to definition elements... Definition elements are supposed to be almost everywhere in the document. And I need to know that in XML XYZ have this element on /odML/section/property[1]/definition for example... – Ondrej Havlicek May 08 '15 at 00:04
  • In some editors you are able to right click on any element you can get a XPath for this element. Lets say that I need to do similiar function if the first comment is unclear. – Ondrej Havlicek May 08 '15 at 00:08
  • Yeah, I'm pretty sure you're going to need to build this yourself (or there might be a library which can help), but I'm pretty sure it's not in the default libraries – MadProgrammer May 08 '15 at 00:14
  • 1
    This is *probably* possible in XSLT. We'll know for sure when you post an example of the input XML and the expected output. – michael.hor257k May 08 '15 at 00:21
  • Added example with simplified XML – Ondrej Havlicek May 08 '15 at 00:28
  • Is the name "definition" supposed to be hard-coded into this? – michael.hor257k May 08 '15 at 00:33
  • Yes. This is stable element name and I need list only of theese elements. – Ondrej Havlicek May 08 '15 at 00:36
  • Ondrej, As you can see, the XSLT solution is much shorter (just 18 lines) and simpler than a solution in Java. XSLT is the language especially designed for processing XML, and it shows. – Dimitre Novatchev May 08 '15 at 03:59

2 Answers2

1

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>&#10;</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
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
1

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>&#xA;</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
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431