Output current node depth in hierarchy

Using XSLT / XPATH 1.0, I want to create HTML where the class attribute of the span element indicates the depth in the original XML hierarchy.

For example, with this XML fragment:

 <text> <div type="Book" n="3"> <div type="Chapter" n="6"> <div type="Verse" n="12"> </div> </div> </div> </text> 

I want this HTML:

 <span class="level1">Book 3</span> <span class="level2">Chapter 6</span> <span class="level3">Verse 12</span> 

How deep these div elements may be unknown a priori. div can be "Book → Chapter". They can be Volume -> Book -> Chapter -> Paragraph -> Line.

I cannot rely on @type values. Some or all may be NULL.

+7
source share
3 answers

This has a very simple and short solution - no recursion, no parameters, no xsl:element , no xsl:attribute :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="div"> <span class="level{count(ancestor::*)}"> <xsl:value-of select="concat(@type, ' ', @n)"/> </span> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet> 

when this conversion is applied to the provided XML document :

 <text> <div type="Book" n="3"> <div type="Chapter" n="6"> <div type="Verse" n="12"></div></div></div> </text> 

required, the correct result is obtained :

 <span class="level1">Book 3</span> <span class="level2">Chapter 6</span> <span class="level3">Verse 12</span> 

The explanation . Proper use of templates, AVT and count() .

+16
source

Or without using recursion - but Dimitre's answer is better than mine

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/text"> <html> <body> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="//div"> <xsl:variable name="depth" select="count(ancestor::*)"/> <xsl:if test="$depth > 0"> <xsl:element name="span"> <xsl:attribute name="class"> <xsl:value-of select="concat('level',$depth)"/> </xsl:attribute> <xsl:value-of select="concat(@type, ' ' , @n)"/> </xsl:element> </xsl:if> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet> 
+5
source

As usual with XSL, use recursion.

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/text"> <html> <xsl:apply-templates> <xsl:with-param name="level" select="1"/> </xsl:apply-templates> </html> </xsl:template> <xsl:template match="div"> <xsl:param name="level"/> <span class="{concat('level',$level)}"><xsl:value-of select="@type"/> <xsl:value-of select="@n"/></span> <xsl:apply-templates> <xsl:with-param name="level" select="$level+1"/> </xsl:apply-templates> </xsl:template> </xsl:stylesheet> 
0
source

All Articles