1
votes

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.

1
You haven't told us what the wanted output is. Shall we read your mind? I have no idea what this means: "apply-tempaltes mode:#default, for br mode:#ignore". You need to tell us what you are trying to accomplish. - JLRishe
I want to know, if i can use different modes for all the items in a sequence. #default will will not work, as soon as i use mode ignore. i could go with mode="#all" for template match="content". I'm sure, there is a better solution. - FelHa
Still unclear, please tell us about the goal instead of asking about modes. Do you want to ignore (that is: not copy to the result document) br elements if they are inside a p[@class = 'h1'] element? - Mathias Müller
ok maybe i chose a bad example. the goal is to process the items of <xsl:apply-templates/> with different modes, depending on their names. Yes, i want to ignore brelements but without using predicates in the match-pattern. - FelHa
You can write two xsl:apply-templates, e.g. <xsl:apply-templates select="node() except br"/>, <xsl:apply-templates select="br" mode="mode-name"/>, only as you want to ignore the element you don't need the second apply-templates at all, applying only to node() except br suffices. - Martin Honnen

1 Answers

3
votes

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>