LorneCash
LorneCash

Reputation: 1614

XSLT Run Template inside Template that adds Root element

XML File:

<Item isNew="1">
    <project_number>00123</project_number>
    <name>Copy Stuff</name>
    <owned_by_id>D9CB2DAFA027466490E50FBEF05E17E9</owned_by_id>
</Item>

Expected output:

<NEW>
    <Item isNew="1">
        <project_number>00123</project_number>
        <name>Copy of PDP Template</name>
        <owned_by_id>D9CB2DAFA027466490E50FBEF05E17E9</owned_by_id>
        <new_classification>Test</new_classification>
        <new_sales_id>9876</new_sales_id>
        <new_sales_type>OEM</new_sales_type>
        <new_product_line />
    </Item>
</NEW>

XSL Stylesheet (producing incorrect output):

<?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"
        xmlns:cs="urn:cs"
        exclude-result-prefixes="msxsl cs">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*"/>

    <xsl:template match="node() | @*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <xsl:element name="NEW">
            <xsl:call-template name="InnerTemplate" />
        </xsl:element>
    </xsl:template>

    <xsl:template name="InnerTemplate">
        <xsl:param name="DocumentToAdd">
            <new_classification>Test</new_classification>
            <new_sales_id>9876</new_sales_id>
            <new_sales_type>OEM</new_sales_type>
            <new_product_line />
        </xsl:param>

        <xsl:copy-of select="."/>
        <xsl:copy-of select="$DocumentToAdd"/>
    </xsl:template>
</xsl:stylesheet>

Incorrect Output:

<NEW>
  <Item isNew="1">
    <project_number>00123</project_number>
    <name>Copy Stuff</name>
    <owned_by_id>D9CB2DAFA027466490E50FBEF05E17E9</owned_by_id>
  </Item>
  <new_classification>Test</new_classification>
  <new_sales_id>9876</new_sales_id>
  <new_sales_type>OEM</new_sales_type>
  <new_product_line />
</NEW>

I'm limited to XSLT 1.0 ONLY

I know how to use a template to put the new nodes inside the Item if I'm NOT also adding a root element with another template but I can't seem to figure out how to do this if it needs to run inside the other template.

I also know I could do this with 2 sequential transforms but that's not an option in my case.

Upvotes: 0

Views: 436

Answers (1)

Joel M. Lamsen
Joel M. Lamsen

Reputation: 7173

If you want to change the Item node, have a template matching it. Try having it this way.

<?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"
    xmlns:cs="urn:cs"
    exclude-result-prefixes="msxsl cs">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*"/>

    <xsl:param name="DocumentToAdd">
        <new_classification>Test</new_classification>
        <new_sales_id>9876</new_sales_id>
        <new_sales_type>OEM</new_sales_type>
        <new_product_line />
    </xsl:param>

    <xsl:template match="node() | @*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <NEW>
            <xsl:apply-templates/>
        </NEW>
    </xsl:template>

    <!-- template match for Item -->
    <xsl:template match="Item">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <!-- add elements inside this node  -->
            <xsl:copy-of select="$DocumentToAdd"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

See it in action: http://xsltransform.net/6qjwabD.

Upvotes: 1

Related Questions