Search code examples
templatesgenericsselectxsltnodes

How to create a generic XSLT to add nodes


I have an multiple XML files in various formats, all of which need to have a specific tag before it is passed through, hence I want to write a generic XSLT that will take any XML input and simply add the additional tags before and after the payload. For example:

Input XML (example1)

<?xml version="1.0" encoding="UTF-8"?>

<Order>
    <data1>
        <test>1</test>
        <test2>2</test2>
        <test3>3</test3>
    </data1>
</Order>

It can also be another XML with <Invoice> or anything else.

Required Output

<?xml version="1.0" encoding="UTF-8"?>
<soap:envelope>
<soap:body>
<Order>
    <data1>
        <test>1</test>
        <test2>2</test2>
        <test3>3</test3>
    </data1>
</Order>
</soap:body>
</soap:envelope>

With the following XSLT, I need to know which node is coming in (Order or invoice) in order to match the pattern - but can this be a generic one?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
<!-- I do not want to specify the node here -->
    <xsl:template match="Order">
        <soap:envelope>
        <soap:body>
            <xsl:copy-of select="*"/>              
        </soap:body>
        </soap:envelope>
    </xsl:template>
  </xsl:stylesheet>

Solution

  • The output you show is not a well-formed XML document: you cannot use a prefix without binding it to a namespace. Your XSLT has the same flaw and cannot be used without producing an error (at least not with a conforming processor).

    I am guessing you want to use:

    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="/">
        <soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
            <soap:body>
                <xsl:copy-of select="."/>              
            </soap:body>
        </soap:envelope>
    </xsl:template>
    
    </xsl:stylesheet>
    

    to produce a valid SOAP message:

    <?xml version="1.0" encoding="UTF-8"?>
    <soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
       <soap:body>
          <Order>
             <data1>
                <test>1</test>
                <test2>2</test2>
                <test3>3</test3>
             </data1>
          </Order>
       </soap:body>
    </soap:envelope>