I'm processing an XML document (an InstallAnywhere .iap_xml installer) before handing it off to another tool (InstallAnywhere itself) to update some values. However, it appears that the XSLT transform I am using is stripping CDATA sections (which appear to be significant to InstallAnywhere) from the document.
I'm using Ant 1.7.0, JDK 1.6.0_16, and a stylesheet based on the identity:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" cdata-section-elements="string" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Basically, "string" nodes that look like:
<string><![CDATA[]]></string>
are being processed into:
<string/>
From reading XSLT FAQs, I can see that what is happening is legal as far as the XSLT spec is concerned. Is there any way I can prevent this from happening and convince the XSLT processor to emit the CDATA section?
To do this, you'll need to add a special case for empty string
elements and use disable-output-escaping
. I don't have a copy of Ant to test with, but the following template worked for me with libxml
's xsltproc
, which exhibits the same behavior you describe:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" cdata-section-elements="string"/>
<xsl:template match="string">
<xsl:choose>
<xsl:when test=". = ''">
<string>
<xsl:text disable-output-escaping="yes"><![CDATA[]]></xsl:text>
</string>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input:
<input>
<string><![CDATA[foo]]></string>
<string><![CDATA[]]></string>
</input>
Output:
<input>
<string><![CDATA[foo]]></string>
<string><![CDATA[]]></string>
</input>