Search code examples
xmlxsltxml-parsingxslt-2.0xslt-grouping

Combine multiple XSLT templates with similar matches


I have this XSLT below

<xsl:template match="word[@italic = 'y']">
        <p>
                <xsl:attribute name="i">yes</xsl:attribute>
                <xsl:apply-templates/>
        </p>
</xsl:template>

<xsl:template match="word[@bold = 'y']">
        <p>
                <xsl:attribute name="b">yes</xsl:attribute>
                <xsl:apply-templates/>
        </p>
</xsl:template>

<xsl:template match="word[@underline = 'y']">
        <p>
                <xsl:attribute name="u">yes</xsl:attribute>
                <xsl:apply-templates/>
        </p>
</xsl:template>

Is there a way to combine these templates in a single nested block, using a variable that looks something like "italic | bold | underline", while also reflecting the changes in <xsl:attribute name="XXX">? Thanks.


Solution

  • The usual approach to combine match patterns is

    <xsl:template match="word[@italic = 'y'] | word[@bold = 'y'] | word[@underline = 'y']">
    

    As for transforming the attributes, can't you just use

    <xsl:template match="word">
      <p>
        <xsl:apply-templates select="@* | node()"/>
      </p>
    </xsl:template>
    

    plus templates for the attributes e.g.

    <xsl:template match="word/@italic[. = 'y']">
      <xsl:attribute name="i">yes</xsl:attribute>
    </xsl:template>
    

    and so on?

    Or perhaps

    <xsl:template match="word/@italic[. = 'y'] | word/@bold[. = 'y'] | word/@underline[. = 'y']">
      <xsl:attribute name="{substring(local-name(), 1, 1)}">yes</xsl:attribute>
    </xsl:template>