Re: [xsl] Creating Nested Structure Based on Attributes

Subject: Re: [xsl] Creating Nested Structure Based on Attributes
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Mon, 19 Mar 2007 12:11:56 +0100
Jeff Sese wrote:

<inline font-style="italic" font-variant="small-caps" font-weight="bold" vertical-alignment="superscript">text</inline>



Hi Jeff,


David Carlisle already showed you how to do it in XSLT 1.0 with mode switching. I don't know if you have the possibility to use XSLT 2.0, but here's a solution that does the same in XSLT 2.0, with the help of a little function that turns any range of attributes into a hierarchical node list, making it easier to use with matching templates. It's perhaps a bit non-conventional, but it keeps your code pretty tight.

Output from your source is equal to the requested output.

Happy coding!

-- Abel Braaksma
  http://abelleba.metacarpus.com


<xsl:stylesheet xmlns:f="http://function"; xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">

<xsl:output indent="yes" />

<xsl:template match="inline">
<xsl:copy>
<xsl:apply-templates select="f:attr-to-nodes-hier(attribute::*, text())" />
</xsl:copy>
</xsl:template>


<!-- result from f:attr-to-nodes-hier -->
<xsl:template match="attr">
<emphasis format="{@value}">
<xsl:apply-templates select="node()" />
</emphasis>
</xsl:template>
<!-- result from f:attr-to-nodes-hier -->
<xsl:template match="attr[@name = 'vertical-alignment']">
<superscript>
<xsl:apply-templates select="node()" />
</superscript>
</xsl:template>
<xsl:function name="f:attr-to-nodes-hier" as="node()*">
<xsl:param name="attributes" as="attribute()*" />
<xsl:param name="text" as="text()" />
<xsl:if test="$attributes">
<attr name="{$attributes[1]/name()}" value="{$attributes[1]}">
<xsl:copy-of select="f:attr-to-nodes-hier($attributes[position() > 1], $text)" />
</attr>
</xsl:if>
<xsl:if test="empty($attributes)">
<xsl:sequence select="$text" />
</xsl:if> </xsl:function>
</xsl:stylesheet>


Current Thread