Search code examples
xmlxsltxpathstylesheet

Listing or counting paths from current node to each leaf node that have some property


Is here some way using XSLT to list or count paths from current node to each one leaf node based on some criteria. for e.g. in specific case here suppose current node is "t" and paths from current node to each leaf node that do not have "trg" attribute. In below e.g.

<root>
  <t>
    <a1>
     <b1 trg="rr">
       <c1></c1>
     </b1>
     <b2>
       <c2></c2>
     </b2>
    </a1>
    <a2>
      <b3>
        <c3></c3>
      </b3>
    </a2>
  </t>
</root>

here is only path with this property t/a1/b2/c2 and t/a2/b3/c3

but not t/a1/b1/c1


Solution

  • The easiest approach would be:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="text()"/>
        <xsl:template match="text()" mode="search"/>
        <xsl:template match="t">
            <xsl:apply-templates mode="search">
                <xsl:with-param name="pPath" select="name()"/>
            </xsl:apply-templates>
        </xsl:template>
        <xsl:template match="*" mode="search">
            <xsl:param name="pPath"/>
            <xsl:apply-templates mode="search">
                <xsl:with-param name="pPath" select="concat($pPath,'/',name())"/>
            </xsl:apply-templates>
        </xsl:template>
        <xsl:template match="*[not(*)]" mode="search">
            <xsl:param name="pPath"/>
            <xsl:value-of select="concat($pPath,'/',name(),'&#xA;')"/>
        </xsl:template>
        <xsl:template match="*[@trg]" mode="search" priority="1"/>
    </xsl:stylesheet>
    

    Output:

    t/a1/b2/c2
    t/a2/b3/c3
    

    Note: Complete pull style. A rule for path search beginning (t patttern). A rule for tunneling parameter (* pattern). A rule for outputing leafs' path (*[not(*)] pattern). A rule for recursion breaking condition (*[@trg] pattern).