tags:

views:

34

answers:

2

Summary: I'm using xslt to convert data, and need to produce some tags with CDATA inside and some tags without. Is escaping the CDATA sections my only option?

I'm attempting to convert data I already have in xml to Moodle Xml for importing. The final product needs to include some Html, which the Moodle Xml doc specifically says needs to be contained in CDATA.

Desired Output:

<question>
  <name>
    <text>FooName</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<img src="1.png">]]></text>
  </questiontext>
</question>

I gave this a try using the following code (trimmed down, but will include the data from my input xml file):

Method 1, nothing special

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <question>
      <name>
        <text>FooName</text>
      </name>
      <questiontext format="html">
        <text><![CDATA[<img src="1.png">]]></text>
      </questiontext>
   </xsl:template>

</xsl:stylesheet>

And got...

Bad Output from Method 1

<question>
  <name>
    <text>FooName</text>
  </name>
  <questiontext format="html">
    <text>&lt;img src="1.png"&gt;</text>
  </questiontext>
</question>

So I look up the xslt documentation and some SO questions, which seem to say I have 2 options:

  1. Do nothing, CDATA gets escaped.
  2. use cdata-section-elements ="text" to auto-generate cdata sections inside tags
  3. Generate CDATA sections by hand, using disable-output-escaping="yes"

Ok, autogeneration sounds good. Lets try that:

Method 2 adding cdata-section-elements="text"

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" cdata-section-elements="text"/>

Bad Output from cdata-section-elements ="text":

<question>
  <name>
    <text><![CDATA[FooName]]></text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<img src="1.png">]]></text>
  </questiontext>
</question>

So 2 isn't an option because there are other elements I do NOT want containing CDATA, in a schema I don't control.

This leaves me with option 3, escaping it by hand. My question then is: Is option 3 my only option? Is there anything else I can do to get my desired output using XSLT? not using XSLT?

A: 

As you have noticed, your Method 1 and Method 2 do not produced the result you want.

Because of the extremely strange and rare requirement for the output lexical appearance, you are left with only the 3rd method.

Dimitre Novatchev
A: 

As Dimitre has answer, your requirement is strange because in XML elements names have schema meaning. If text elements schema allows CDATA, this is so for all text elements.

One way to do what you want with extra element:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"&gt;
<xsl:output cdata-section-elements="xhtml:div"/>
    <xsl:template match="/">
        <question>
            <name>
                <text>FooName</text>
            </name>
            <questiontext format="html">
                <text>
                     <xhtml:div><![CDATA[<img src="1.png">]]></xhtml:div>
                </text>
            </questiontext>
        </question>
    </xsl:template>
</xsl:stylesheet>

Output (with any input):

<question xmlns:xhtml="http://www.w3.org/1999/xhtml"&gt;
    <name>
        <text>FooName</text>
    </name>
    <questiontext format="html">
        <text>
            <xhtml:div><![CDATA[<img src="1.png">]]></xhtml:div>
        </text>
    </questiontext>
</question>
Alejandro