Search code examples
xmlxsltxslt-2.0mode

Apply-templates with different modes


I want to process nodes with apply-templates but use different modes to match the right template-rules for all the nodes within the sequence.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<story>
    <p class="h1">
        <content>heading</content>
        <br/>
    </p>
    <p>
        <content>some text</content>
        <br/>
        <content>more text...</content>
    </p>
</story>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:element name="div">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="p">
        <xsl:choose>
            <xsl:when test="@class='h1'">
                <xsl:element name="h1">
                    <!--apply-tempaltes mode:#default, for br mode:ignore-->
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="p">
                    <!--apply-tempaltes mode:#default-->
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="content" mode="#default">
        <xsl:element name="span">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="br" mode="#default">
        <xsl:element name="br"/>
    </xsl:template>

    <xsl:template match="br" mode="ignore"/>

</xsl:stylesheet>

Wanted Output:

<?xml version="1.0" encoding="UTF-8"?>
<story>
    <h1 class="h1"><span>heading</span>    
    </h1>
    <p><span>some text</span> 
        <br/>
        <span>more text...</span> 
    </p>
</story>

XSLT-version is 2.0. I know, there are other ways to achieve the wanted output for this example, but i would like to use the mode-attributes.


Solution

  • AFAICT, you want to do:

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <!-- identity transform -->
    <xsl:template match="@*|node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="p[@class='h1']">
        <h1 class="h1">
            <xsl:apply-templates mode="h1"/>
        </h1>
    </xsl:template>
    
    <xsl:template match="content" mode="#all">
        <span>
            <xsl:apply-templates mode="#current"/>
        </span>
    </xsl:template>
    
    <xsl:template match="br" mode="h1"/>
    
    </xsl:stylesheet>