Blog

Get XPath of an XML node

There are lots of XSL templates out there that get a human readable path to a node. But none of them cover the case when there are more than one node of the same element at the same level.

Please find below the code that get XPath of an XML node:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes">
    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:tagibute name="position">
          <xsl:call-template name="xpath.position">
            <xsl:apply-templates select="@*|node()"></xsl:apply-templates>
          </xsl:call-template>
        </xsl:tagibute>
      </xsl:copy>
    </xsl:template>

    <xsl:template name="xpath.position">
     <xsl:param name="node" select="."></xsl:param>
     <xsl:param name="path" select="''"></xsl:param>
     <xsl:variable name="next.path">
      <xsl:text>*[position()=</xsl:text>
      <xsl:value-of select="$node/count(preceding-sibling::*)+1">
       <xsl:text>]</xsl:text>
       <xsl:if test="$path != ''">/</xsl:if>
       <xsl:value-of select="$path"></xsl:value-of>
      </xsl:value-of>
     </xsl:variable>

   <xsl:choose>
    <xsl:when test="$node/parent::*">
      <xsl:call-template name="xpath.position">
        <xsl:with-param name="node" select="$node/parent::*"></xsl:with-param>
          <xsl:with-param name="path" select="$next.path"></xsl:with-param>
      </xsl:call-template>
    </xsl:when>
 
    <xsl:otherwise>
      <xsl:text>/</xsl:text>
        <xsl:value-of select="$next.path"></xsl:value-of>
      </xsl:otherwise>
    </xsl:choose>
   </xsl:template>
  </xsl:output>
</xsl:stylesheet>

Share this post



Leave a comment


Previous Post

Next Post


\