Search code examples
xslt-3.0

problem specifying CDATA element in xsl:output instruction


consider this....

<xsl:output method="xml" cdata-section-elements="urn:data"/>

that works nicely BUT, what if I have some urn:data elements that I do want CDATA, and some I dont.

the obvious thing to do is specify a path!

<xsl:output method="xml" cdata-section-elements="urn:OperatorSpecificData/urn:data"/>

that would work (in theory)...but it doesnt, because paths arent allowed.

hmmmm.

any ideas?

(ok, maybe I could create my own custom element and then "copy" the document with the custom element out, replacing the custom element with the actual requirement element....though i have suspicion the 'cdata' nature of the data would be lost and it would become standard escaped string data)


Solution

  • One option might be to use serialize() in a template specific to the element you want to have CDATA.

    Not sure if there's a way to do it without resorting to xsl:value-of w/DOE (disable-output-escaping) though.

    Example...

    XML Input

    <doc>
        <yes>
            <foo>test</foo>
        </yes>
        <no>
            <foo>test</foo>
        </no>
    </doc>
    

    XSLT 3.0

    <xsl:stylesheet version="3.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        exclude-result-prefixes="xs">
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
            
        <xsl:mode on-no-match="shallow-copy"/>
        
        <xsl:template match="yes/foo">
            <xsl:value-of 
                select="serialize(., map{'cdata-section-elements':(xs:QName('foo'))})" 
                disable-output-escaping="yes"/>
        </xsl:template>
        
    </xsl:stylesheet>
    

    XML Output

    <doc>
       <yes><foo><![CDATA[test]]></foo></yes>
       <no>
          <foo>test</foo>
       </no>
    </doc>