I have some HTML containing styled spans like these:
<p><span class="foo">unstyled span</span></p>
<p><span style="font-style: italic;">italic</span></p>
<p><span style="font-weight: bold; font-style: italic;">bold italic</span></p>
<p><span style="text-decoration: underline; font-style: italic; font-weight: bold;">underline italic bold</span></p>
Spans are also used there to set font and background color and few more things. Basically I have to replace span
tags with em
, strong
, etc. where possible, keep some styles and remove everything else (unneeded styles and classes). For the above input, the desired output is:
<p>unstyled span</p>
<p><em>italic</em></p>
<p><em><strong>bold italic</strong></em></p>
<p><em><strong><span style="text-decoration: underline;">underline italic bold</span></strong></em></p>
With my very limited XSLT skills I was able to write the following transformation that does the job but looks ugly:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="span">
<xsl:call-template name="startStyleTests" select="." />
</xsl:template>
<xsl:template name="startStyleTests">
<xsl:call-template name="testItalic" select="." />
</xsl:template>
<xsl:template name="testItalic">
<xsl:choose>
<xsl:when test="contains(./@style, 'italic')">
<xsl:element name="em"><xsl:call-template name="testBold" select="." /></xsl:element>
</xsl:when>
<xsl:otherwise><xsl:call-template name="testBold" select="." /></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="testBold">
<xsl:choose>
<xsl:when test="contains(./@style, 'bold')">
<xsl:element name="strong"><xsl:call-template name="testUnderline" select="." /></xsl:element>
</xsl:when>
<xsl:otherwise><xsl:call-template name="testUnderline" select="." /></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="testUnderline">
<xsl:choose>
<xsl:when test="contains(./@style, 'underline')">
<xsl:element name="span">
<xsl:attribute name="style">text-decoration: underline;</xsl:attribute>
<xsl:call-template name="endStyleTests" select="." />
</xsl:element>
</xsl:when>
<xsl:otherwise><xsl:call-template name="endStyleTests" select="." /></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="endStyleTests">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
(a few "testSomething" templates removed for readability)
How should it really be done with XSLT 1.0?