Beginning XSLT
Thursday 29 May 2003
I'm currently learning XSLT and I've come across a problem which I can solve but only in what seems like an inelegant way. Given this example source document:
<p>
<r>
<t>Some </t>
</r>
<r>
<rPr>
<b />
<i />
</rPr>
<t>formatted</t>
</r>
<r>
<rPr>
<b />
</rPr>
<t> text.</t>
</r>
</p>
I want to transform it into something like this:
<p>Some <b><i>formatted</i></b><b> text.</b></p>
The problem is how to achieve the nesting of the text within the <b> and <i> tags. The following stylesheet seems to work but I don't like the use of the text elements with the disable-output-escaping attribute set. There is sure to be a right way of doing this but it has eluded me so far.
<xsl:stylesheet version = '1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:template match="p">
<p>
<xsl:apply-templates select="r"/>
</p>
</xsl:template>
<xsl:template match="r">
<xsl:if test="rPr/b">
<xsl:text disable-output-escaping="yes" ><b></xsl:text>
</xsl:if>
<xsl:if test="rPr/i">
<xsl:text disable-output-escaping="yes" ><i></xsl:text>
</xsl:if>
<xsl:apply-templates select="t"/>
<xsl:if test="rPr/b">
<xsl:text disable-output-escaping="yes" ></i></xsl:text>
</xsl:if>
<xsl:if test="rPr/i">
<xsl:text disable-output-escaping="yes" ></b></xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I've hugely simplified the source document and removed namespaces - for the purpose of illustrating the problem - but you may be able to guess what I'm trying to do from the element names.
UPDATE: I made the classic mistake of pasting a change into a sample without testing it. I've now corrected the final <r> element.