-2

I have an XML file and I want to create xpath for each attribute in XML file using Java or XSLT.

Sample XML -

<host> 
 <node> 
   <type>fruit1</type>
   <value>10</value>
 </node>
 <node>
   <type>fruit2</type>
   <value>20</value>
 </node>
 <node>
   <type>fruit3</type>
   <value xsi:type="valueList">
    <listValues>
      <value>
        <value>30</value>
        <code>abc</code>
      </value>
    </listValues>
   </value>
 </node>
 <node>
   <type>fruit4</type>
   <value>40</value>
 </node>  
 <node>
   <type>fruit5</type>
   <value>50</value>
 </node>
</host>

The expected output is -

host/node[1]/type[text()]
host/node[1]/value[text()]
host/node[2]/type[text()]
host/node[2]/value[text()]
host/node[3]/type[text()]
host/node[3]/value[@type = "valueList"]/listValues/value/value[text()]
host/node[3]/value[@type = "valueList"]/listValues/value/code[text()]
host/node[4]/type[text()]
host/node[4]/value[text()]
host/node[5]/type[text()]
host/node[5]/value[text()]

Any help would be a great plus

QA Testing
  • 57
  • 7
  • What kind of "XPath" do you have in mind where indexing seems to start with `0`? In the W3C standard the first child node has position `1`. And what is `type(text)`, also doesn't look like XPath to me. – Martin Honnen Mar 21 '19 at 09:11
  • HI, I have modified the expected output. Sorry for typo issues – QA Testing Mar 21 '19 at 09:47
  • One of many possible duplicate of [How to get xpaths for all leaf elements from XML?](https://stackoverflow.com/questions/9064951/how-to-get-xpaths-for-all-leaf-elements-from-xml) – Alejandro Mar 21 '19 at 15:29

1 Answers1

0

you can check this

 <xsl:template match="text()[normalize-space() ne '']">
    <xsl:text>&#xa;</xsl:text>
    <xsl:for-each select="ancestor::*">
        <xsl:value-of select="local-name()"/>
        <xsl:if test="following-sibling::*[local-name() = current()/local-name()] or preceding-sibling::*[local-name() = current()/local-name()]"><xsl:value-of select="concat('[', count(preceding-sibling::*[local-name() = current()/local-name()]) + 1 ,']')"></xsl:value-of></xsl:if>
        <xsl:for-each select="@*">
            <xsl:text>[@</xsl:text><xsl:value-of select="local-name(.)"/><xsl:text> = "</xsl:text><xsl:value-of select="."></xsl:value-of><xsl:text>"]</xsl:text>
        </xsl:for-each>
        <xsl:if test="position() ne last()">/</xsl:if>
        <xsl:if test="position() eq last()"><xsl:text>[text()]</xsl:text></xsl:if>
    </xsl:for-each>
</xsl:template>

check output at https://xsltfiddle.liberty-development.net/94rmq6a

Rupesh_Kr
  • 3,395
  • 2
  • 17
  • 32
  • 1
    I think you can simplify your check on siblings to just ``, and you could probably replace the `xsl:value-of` that gets the index number with just ``. See https://xsltfiddle.liberty-development.net/94rmq6a/1 – Tim C Mar 21 '19 at 10:37
  • I see an error more often 'The entity name must immediately follow the '&' in the entity reference.' when I use the above XSLT script. Do you know why is it ? – QA Testing Mar 21 '19 at 11:49
  • @QATesting Can you share your input for that where you found above issue. – Rupesh_Kr Mar 21 '19 at 12:42
  • This is XSLT 2.0 as per the use of `ne` and `eq` operators. But there are one-liners in XPath 2.0... I think there is one even in the Specification. – Alejandro Mar 21 '19 at 15:25