As you now know, you cannot nest CDATA sections (a limitation that stems from the syntax all the way back to SGML in the 80's).
It looks like this is an issue of double-escaping your content. What you need is to escape the content once and then surround it with a CDATA section.
There are potentially ways to do this, but it would help if you explained a little more the full context of where this is happening.
Sara, technical writer/jackbe
Hi Sara,
Thanks for your reply. I haven't made much progress on this, although I'm exploring the use of a Groovy script to generate an unescaped xml fragment, but that's not working out so far (I'm not sure which version of Groovy is running under the Presto server and whether the MarkupBuilder helper classes have been included) but that's another issue.
I'm trying to generate a kml file for use with Google maps using a mashup. It's looking really cool so far, BUT, I've run in to this problem with an embedded CDATA section. In the kml file I need to add html surrounded by a CDATA escape so that when the kml file is parsed by Google Maps the content is not processed. Using an emml script I need to generate the kml document so that it includes a CDATA section something like this:
<kml xmlns="http://www.opengis.net/kml/2.2">
<document>
<Style id="medSporeCountBalloon">
<BalloonStyle>
<bgColor>#EBFFEB</bgColor>
<text><![CDATA[<h1>some html content etc</h1>]]></text>
</BalloonStyle>
</Style>
</document>
</kml>
I've tried all manner of ways to create the text node CDATA string but it always ends up in some form of escaped output when the final result is output from the emml script. Here's one approached I tried:
<text>{concat('<',$cdataOpen)}<h1 style="margin-top:0px;">Anexa Animal Health</h1>
$[sporeCount/displayName]:
<font color="orange">$[sporeCount]</font>
<br />$[dateSampled/displayName]: $[dateSampled]
<br /><small>Source: $[dataSource]</small>{$cdataClose}></text>
where cdataOpen = "![CDATA[" and cdataClose = "]]" but the output result is:
<text><![CDATA[<h1 style="margin-top:0px;">Anexa Animal Health</h1>
$[sporeCount/displayName]:
<font color="orange">$[sporeCount]</font>
<br/>$[dateSampled/displayName]: $[dateSampled]
<br/>
<small>Source: $[dataSource]</small>]]></text>
Any suggestions.
Thanks as always ...
Cheers, Innes
Hi Sara,
I've had a bit of a breakthrough today. It's not a perfect solution and probably a bit fragile at the moment, but it does actually produce what I want for this particular case. Here's the emml solution to this particular problem.
<mashup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jackbe.com/2008-03-01/EMMLSchema/ ../src/schemas/EMMLSpec.xsd"
xmlns="http://www.jackbe.com/2008-03-01/EMMLSchema" xmlns:macro="http://www.jackbe.com/2008-03-01/EMMLMacro"
name="testCDATA">
<operation name="genCDATAXml">
<output name="testResult" type="string" />
<!--
*********************************************************************
* wrapCDATA_WriteToFile Macro
*********************************************************************
-->
<macro name="wrapCDATA_WriteToFile">
<!--
wrapCDATA_WriteToFile: Version 1.0 - Innes Fisher (Feb 2010) This
macro is used to wrap a specially marked section of an input
document in a CDATA section so that it can be used in a subsequent
process where the CDATA section will be ignored when the XML is
parsed. The specially marked up XML is also written to the specified
file. The macro outputs a string rather than a document. The nodes
in the input document that must be surrounded by a CDATA section are
marked with ##CDATAbegin# at the start and ##CDATAend# at the end
-->
<output name="CDATAOutput" type="string" /> <!-- CDATA wrapped output -->
<input name="CDATAInput" type="document" /> <!-- specially marked input document -->
<input name="path" type="string" /> <!-- path for the output file -->
<input name="fileName" type="string" /> <!-- name of the output file -->
<variables>
<variable name="CDATAInputString" type="string" /> <!-- string version of the input document -->
<variable name="xmlString" type="string" /> <!-- Groovy script variable declaration -->
</variables>
<!-- convert the input document to a String form -->
<assign fromvariable="$CDATAInput" outputvariable="CDATAInputString" />
<!-- Process the XML string and replace the CDATA tags -->
<!--
*********************************************************************
* Groovy script
*********************************************************************
-->
<script type="groovy" inputvariables="CDATAInputString,xmlString"
outputvariable="xmlString">
<![CDATA[
def cdataBeginString = "##CDATAbegin#" // Marks the CDATA opening point marker
def cdataEndString = "##CDATAend#" // marks the CDATA closing point marker
// Build strings to use in wrapping the marked content in a CDATA section since we
// cant specify it normally as they would mark real CDATA start/end points
def cdataBegin = "<"+"![CDATA[" // constructed CDATA markup string opener
def cdataEnd = "]]"+">" // constructed CDATA makrup string closer
// Using a regex to replace all the occurences of the CDATA opening and closing points
// in the passed in variable CDATAInput
String resultTemp = CDATAInputString.replaceAll(/$cdataBeginString/){it - cdataBeginString + cdataBegin}
resultTemp = resultTemp.replaceAll(/$cdataEndString/) {it - cdataEndString + cdataEnd}
// Write out the new UTF8 encoded Xml string with the wrapped CDATA section(s)
byte[] xmlBytes = resultTemp.getBytes("UTF8")
xmlString = new String(xmlBytes,"UTF8")
]]>
</script>
<!-- tidy up the string a bit and remove excess whitespace etc -->
<assign fromexpr="normalize-space($xmlString)" outputvariable="$CDATAOutput" />
<!-- write the reformed XML string to the specified output file -->
<!--
*********************************************************************
* Groovy script
*********************************************************************
-->
<script type="groovy" inputvariables="path,fileName,CDATAOutput">
<![CDATA[
def outFile = new File(path + fileName)
outFile.write(CDATAOutput)
]]>
</script>
</macro>
<!--
************************** End of macro *****************************
-->
<!-- test it out -->
<constructor outputvariable="testin">
<text>
##CDATAbegin#
<someMarkup>wrap this markup in a CDATA section</someMarkup>
##CDATAend#
<normalMarkup>should be untouched</normalMarkup>
<childNode>
##CDATAbegin#<moreCDATA>wrap this too</moreCDATA>##CDATAend#
</childNode>
</text>
</constructor>
<macro:wrapCDATA_WriteToFile CDATAInput="$testin"
path="c:/scratch/" fileName="test.kml" outputvariable="testResult" />
<display message="finished ..." />
</operation>
</mashup>
It should produce the following string and place it in a file called test.kml in the directory c:\scratch
if you have one.
<text> <![CDATA[ <someMarkup>wrap this markup in a CDATA section</someMarkup> ]]> <normalMarkup>should be untouched</normalMarkup> <childNode> <![CDATA[<moreCDATA>wrap this too</moreCDATA>]]> </childNode> </text>
Any suggestions on improvements are more than welcome. I'm sure my coding, especially the Groovy scripts is a bit primitive.
Cheers, Innes



Hi Mashers,
I'm workin on building an emml output document that needs to include a CDATA section, but I'm having problems getting the output rendered properly because the CDATA section is evaluated as the script is parsed and a nested CDATA causes problems..
Essentially I need to do something like:
<![CDATA[<!CDATA[... the actual cdata content to be output ...]]]]
but this doesn't work.
Does anyone have any suggestions. I'll try a few more approaches over the weekend but it might save me some time if this problem has been solved before.
Thanks everyone,
Innes (NZ)