Question

I'm using xslt to transform an xml doc.

Under certain conditions, I need to supply a snippet of xml (that is not contained in the xml doc) to a template in the xslt doc.

Without introducing a second xml doc, how would I go about achieving this? Specifically, how would I embed this snippet in the xslt doc? And how would I reference it within the xslt doc, such that I could pass it to a template?

I've been unable to find examples of this use-case after doing multiple web searches.

Here's the use-case in simplified form:

xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <snippet>
        <el att1="c"/>
    </snippet>

    <xsl:template match="root">
        <xsl:apply-templates select="el"/>
        <xsl:apply-templates select="snippet/el"/>
    </xsl:template>

    <xsl:template match="el">
        <xsl:value-of select="@att1"/>
    </xsl:template>

</xsl:stylesheet>

xml

<root>
    <el att1="a"/>
    <el att1="b"/>
</root>

Expected output:

abc

Thanks much!

Was it helpful?

Solution

In XSLT 2.0 you can simply create a variable with the required content and then apply templates to that directly, e.g.

<xsl:variable name="snippet">
    <el att1="c"/>
</xsl:variable>

and then

<xsl:apply-templates select="$snippet/el" />

This doesn't work in 1.0, but you can use a trick with the document function with an empty string argument to refer to the XSLT stylesheet itself as an XML tree.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:variable name="snippet">
        <el att1="c"/>
    </xsl:variable>

    <xsl:template match="root">
        <xsl:apply-templates select="el"/>
        <xsl:apply-templates
            select="document('')/*/xsl:variable[@name='snippet']/el"/>
    </xsl:template>

    <xsl:template match="el">
        <xsl:value-of select="@att1"/>
    </xsl:template>

</xsl:stylesheet>

In both cases though you need to be aware that because the node(s) you're processing are not in the main input XML tree, then / may not mean what you think it does. A / refers to the root node of the tree that contains the current context node, so for the XSLT 2.0 example that would be the root node of a temporary tree, which has the el as a direct child, and in the XSLT 1.0 version it would be the root of the stylesheet tree, with the xsl:stylesheet as its child.

OTHER TIPS

I don't understand your example that well. Here's a simple one:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates select="el"/>
        <el att1="c"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="el">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

When this is applied to your input:

<root>
    <el att1="a"/>
    <el att1="b"/>
</root>

the result is:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <el att1="a"/>
  <el att1="b"/>
  <el att1="c"/>
</root>

Edit:

Using your example:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="root">
    <xsl:apply-templates select="el"/>
    <xsl:text>c</xsl:text>
</xsl:template>

<xsl:template match="el">
    <xsl:value-of select="@att1"/>
</xsl:template>

</xsl:stylesheet>

produces:

abc
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top