Nitin
Nitin

Reputation: 3

Need XSLT to wrap XML in the CDATA tags without hampering Root node with namespace

Requirement is basically wrapping the whole XML content into a XML Tag with CDATA, Input XML below

<?xml version="1.0" encoding="UTF-8"?>
<ns1:outSystemWS xmlns:ns1="http://abcd.co.za">
    <ns1:in0>
        <PQR>
            <STU>
                <TEST1>123</TEST1>
                <TEST2>XYZ</TEST2>
            </STU>
            <req>
                <TEST3>DEF</TEST3>
                <TEST4>GHI</TEST4>
            </req>
        </PQR>
    </ns1:in0>
</ns1:outSystemWS>

Expected Output:

<?xml version="1.0" encoding="UTF-8"?>
<ns1:outSystemWS xmlns:ns1="http://abcd.co.za">
    <ns1:in0><![CDATA[<PQR>
            <STU>
                <TEST1>123</TEST1>
                <TEST2>XYZ</TEST2>
            </STU>
            <req>
                <TEST3>DEF</TEST3>
                <TEST4>GHI</TEST4>
            </req>
        </PQR>]]>
    </ns1:in0>
</ns1:outSystemWS>

I have tried below XSLT but no luck!! Please help

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="ns:outSystemWS[*]" xmlns:ns="http://abcd.co.za">
        <xsl:copy>
            <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
            <xsl:copy-of select="." />
            <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 0

Views: 547

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116982

I agree with Martin Honnen that the best solution is to serialize properly the content of the CDATA section, and not to resort to the hack of inserting the CDATA markup as escaped text.

Still, in a pinch you could do:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ns1="http://abcd.co.za">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="ns1:in0" >
    <xsl:copy>
        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
        <xsl:apply-templates/>
        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167516

XSLT 3 with the help of the XPath 3 serialize function can do that:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output cdata-section-elements="ns1:in0" xmlns:ns1="http://abcd.co.za"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="PQR">
      <xsl:value-of select="serialize(.)"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/gVhDDz9

In earlier versions of XSLT you will need to check whether there is a processor specific extension function or way or you need to use an XSLT based serialization like https://lenzconsulting.com/xml-to-string/

Upvotes: 1

Related Questions