(I have researched this question extensively but not found an adequate solution yet.)
I am using XSLT to convert a series of XML files to a ‘tree’-like HTML document, where the parent-child relationships between elements is reflected with indenting.
The solution below works fine but it’s too verbose, and we also need to accommodate adding a few new
elements to the schema in the future.
What’s a good general-purpose solution that will do what we need? I’ve seen recursive solutions online where a “depth” variable is used and is incremented and passed in as a parameter, and used to drive the indenting level; this seems to be a common pattern however I could not get it to work for me.
Thanks.
So my data files look like this:
<document>
<metadata>
<version>1.0</version>
<date>1/1/12</date>
etc...
</metadata>
<trackdata>
<tracks>
<track>123</track>
<track>456</track>
etc...
</trackdata>
</document>
And the XSLT (Note the different values for the text-indent at the different levels):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="no"/>
<xsl:template match="@*|node()">
<xsl:apply-templates select="@*|node()" />
</xsl:template>
<xsl:template match="metadata">
Metadata: <xsl:apply-templates/>
</xsl:template>
<xsl:template match="version">
<div style="text-indent:3em">Version: <xsl:value-of select="text()"/></div>
</xsl:template>
<xsl:template match="date">
<div style="text-indent:3em">Date: <xsl:value-of select="text()"/></div>
</xsl:template>
<xsl:template match="trackdata">
Track Data: <xsl:value-of select="text()"/></div>
</xsl:template>
<xsl:template match="tracks">
<div style="text-indent:3em">Tracks: <xsl:apply-templates/>
</xsl:template>
<xsl:template match="track">
<div style="text-indent:6em">Track: <xsl:value-of select="text()"/></div>
</xsl:template>
etc…
Try creating a variable to hold the
text-indentvalue. Something like this:Here’s another full example of usage…
XML Input (well-formed)
XSLT 1.0
Raw HTML Output
If you wanted the first div to not have an indent, you could change the variable to this: