Search code examples
xmlxslt-2.0saxon

How to Apply the Same XSLT Template to Both XML Elements and Dynamically Created Elements?


I am working with XSLT 2.0 and trying to apply the same transformation process to both elements from the input XML and elements dynamically created within the XSLT.

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <h2>General Introduction</h2>
    <h3>Project Overview</h3>
    <h3>Goals and Challenges</h3>
    <h2>Installation</h2>
    <h3>Initial Configuration</h3>
    <h4>Configuration File</h4>
    <h3>Deployment</h3>
    <h4>On a Local Server</h4>
    <h4>On a Remote Server</h4>
    <h2>Usage</h2>
    <h3>Basic Commands</h3>
    <h3>Advanced Options</h3>
</document>

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="/document">
        <html>
            <body>
                <xsl:apply-templates/>
                <h3>Dynamic title (was not in the XML)</h3>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="h2 | h3 | h4">
        <xsl:element name="{name()}">
            ¶<xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Issue

The transformation correctly applies to <h2>, <h3>, and <h4> elements from the original XML. However, the dynamically created element:

<h3>Dynamic title (was not in the XML)</h3>

is not processed by the template that matches h2 | h3 | h4.

The question

How can I ensure that both XML elements and dynamically created elements undergo the same transformation process? Is there a way to reapply templates to generated elements within XSLT?


Solution

  • As an alternative to Martin's solution, which does two processing passes over the entire document, you could locally process the dynamic element like this:

         <xsl:template match="/document">
            <html>
                <body>
                    <xsl:apply-templates/>
                    <xsl:variable name="temp">
                       <h3>Dynamic title (was not in the XML)</h3>
                    </xsl:variable>
                    <xsl:apply-templates select="$temp"/>
                </body>
            </html>
        </xsl:template>