Search code examples
xsltmode

XSLT apply-template with mode - Incorrect result with no matching mode


Here's a simple case.

Here's my XML:

<?xml version="1.0" encoding="utf-8" ?>
<dogs>
    <dog type="Labrador">
        <Name>Doggy</Name>
    </dog>
    <dog type="Batard">
        <Name>Unknown</Name>
    </dog>
</dogs>

This XML is used with two Xslt. This is the common one:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="text"/>

    <xsl:template match="dogs">
        <xsl:text>First template&#13;&#10;</xsl:text>
        <xsl:apply-templates select="." mode="othertemplate" />
    </xsl:template>
</xsl:stylesheet>

This is the child one:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:include href="transform.xslt"/>

    <xsl:template match="dogs" mode="othertemplate">
        <xsl:text>&#9;&#9;Other template</xsl:text>
    </xsl:template>
</xsl:stylesheet>

The child includes the common one (called transform.xslt).

When I execute the child, I get the expected result:

First template
        Other template

When I execute the common one, I get this strange results:

First template


        Doggy


        Unknown

The common one applies a template with the mode "othertemplate". This mode is only included, some times, in the child xslt.

I want that, if there's no template with mode "othertemplate", then nothing should be outputted.

I don't want to include a template with mode "othertemplate" with empty body for all xslt files that does not have to use this template mode...

What should I do?

Thanks


Solution

  • The built-in XSLT templates are defined and selected for every mode. So, the built-in template for text nodes is selected and (by definition) it outputs the text node.

    To suppress this, you need to override thie built-in template for text nodes (also possibly for elements) in your desired mode with an empty template:

    <xsl:template match="text()" mode="othertemplate"/>
    

    Include the above in your imported stylesheet.