1

I am trying to wrap CDATA for the elements in an xml file.

Another point i missed was, there are some elements with same names those need to be escaped from adding CDATA.

This is the source xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<books>
    <jndi:binding name="books/cat/action/configs">
        <jndi:value type="java.lang.String">
            <urlConfig>
              <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>
              <urlKey name="logo" altURL="def.com">
                <address>abc.com</address>
              </urlKey>
              <urlKey name="logo1" altURL="def.com">
                <address>abc.com</address>
              </urlKey>
            </urlConfig>
        </jndi:value>
    </jndi:binding>
    <jndi:binding name="books/cat/romance/configs">
        <jndi:value type="java.lang.String">
            <urlConfig>
              <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>          
              <urlKey name="logo" altURL="def.com">
                <address>abc.com</address>
              </urlKey>          
              <urlKey name="logo1" altURL="def.com">
                <address>abc.com</address>
              </urlKey>  
            </urlConfig>
        </jndi:value>
    </jndi:binding>
<jndi:binding name="books/cat/thriller/configs">
    <jndi:value type="java.lang.String">
        abc.com
    </jndi:value>
</jndi:binding> 
<jndi:binding name="books/cat/classic/configs">
    <jndi:value type="java.lang.String">
        abc.com
    </jndi:value>
</jndi:binding>
</books>

I have tried to use the same trick that @Dimitre Novatchev has mentioned here at How to insert CDATA into XML text markup exported from Access 2003?. But some how that's not working for me.

This is the xsl file that i tried:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:jndi="urn:jboss:jndi-binding-service:1.0"  >
 <xsl:strip-space elements="*"/>
 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Can some one suggest me how to add CDATA to an element and also need to add an additional line <?xml version="1.0" encoding="ISO-8859-1"?> at the beginning of CDATA.

Here is the expected out:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<books>
    <jndi:binding name="books/cat/action/configs">
        <jndi:value type="java.lang.String">
        <![CDATA[
            <?xml version="1.0" encoding="ISO-8859-1"?>
            <urlConfig>
              <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>
              <urlKey name="logo" altURL="def.com">
                <address>abc.com</address>
              </urlKey>
              <urlKey name="logo1" altURL="def.com">
                <address>abc.com</address>
              </urlKey>
            </urlConfig>
        ]]> 
        </jndi:value>
    </jndi:binding>
    <jndi:binding name="books/cat/romance/configs">
        <jndi:value type="java.lang.String">
        <![CDATA[
            <?xml version="1.0" encoding="ISO-8859-1"?>
            <urlConfig>
              <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>          
              <urlKey name="logo" altURL="def.com">
                <address>abc.com</address>
              </urlKey>          
              <urlKey name="logo1" altURL="def.com">
                <address>abc.com</address>
              </urlKey>  
            </urlConfig>
        ]]> 
        </jndi:value>
    </jndi:binding>
<jndi:binding name="books/cat/thriller/configs">
    <jndi:value type="java.lang.String">
        abc.com
    </jndi:value>
</jndi:binding> 
<jndi:binding name="books/cat/classic/configs">
    <jndi:value type="java.lang.String">
        abc.com
    </jndi:value>
</jndi:binding>
</books>
Community
  • 1
  • 1
kumar
  • 389
  • 1
  • 9
  • 28

1 Answers1

1

The problem is that you need to convert the XML that goes inside the CDATA sections into text. This XSLT should do the job:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:jndi="urn:jboss:jndi-binding-service:1.0">

  <xsl:output method="xml" indent="yes" cdata-section-elements="jndi:value"/>

  <xsl:template match="jndi:value">
    <xsl:copy>
      <!-- Copy the attributes -->
      <xsl:apply-templates select="@*"/>
      <!-- Convert the contained nodes (elements and text) into text -->
      <xsl:variable name="subElementsText">
        <xsl:apply-templates select="node()" mode="asText"/>
      </xsl:variable>
      <!-- Output the XML directive and the converted nodes -->
      <xsl:value-of select="concat('&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;',$subElementsText)"/>
    </xsl:copy>
  </xsl:template>

  <!-- Copy text nodes as text -->
  <xsl:template match="text()" mode="asText">
    <xsl:copy/>
  </xsl:template>

  <!-- Copy elements as text -->
  <xsl:template match="*" mode="asText">
    <xsl:value-of select="concat('&lt;',name())"/>
    <xsl:for-each select="@*">
      <xsl:value-of select="concat(' ',name(),'=&quot;',.,'&quot;')"/>
    </xsl:for-each>
    <xsl:value-of select="'&gt;'"/>
    <xsl:apply-templates select="node()" mode="asText"/>
    <xsl:value-of select="concat('&lt;/',name(),'&gt;')"/>
  </xsl:template>

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

</xsl:stylesheet>

Basically it uses a couple of templates to match the XML elements that need to be converted to text and convert them 'manually'. The cdata-sections-elements directive does the rest.

When applied to

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<books xmlns:jndi="urn:jboss:jndi-binding-service:1.0">
  <jndi:binding name="books/cat/action/configs">
    <jndi:value type="java.lang.String">
      <urlConfig>
        <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>
        <urlKey name="logo" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
        <urlKey name="logo1" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
      </urlConfig>
    </jndi:value>
  </jndi:binding>
  <jndi:binding name="books/cat/romance/configs">
    <jndi:value type="java.lang.String">
      <urlConfig>
        <defaults catID="1983" subcatID="1987" method="get" onError="keep"/>
        <urlKey name="logo" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
        <urlKey name="logo1" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
      </urlConfig>
    </jndi:value>
  </jndi:binding>
</books>

produces the expected result:

<?xml version="1.0" encoding="utf-8"?>
<books xmlns:jndi="urn:jboss:jndi-binding-service:1.0">
  <jndi:binding name="books/cat/action/configs">
    <jndi:value type="java.lang.String"><![CDATA[<?xml version="1.0" encoding="utf-8"?>
      <urlConfig>
        <defaults catID="1983" subcatID="1987" method="get" onError="keep"></defaults>
        <urlKey name="logo" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
        <urlKey name="logo1" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
      </urlConfig>
    ]]></jndi:value>
  </jndi:binding>
  <jndi:binding name="books/cat/romance/configs">
    <jndi:value type="java.lang.String"><![CDATA[<?xml version="1.0" encoding="utf-8"?>
      <urlConfig>
        <defaults catID="1983" subcatID="1987" method="get" onError="keep"></defaults>
        <urlKey name="logo" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
        <urlKey name="logo1" altURL="def.com">
          <address>abc.com</address>
        </urlKey>
      </urlConfig>
    ]]></jndi:value>
  </jndi:binding>
</book
MiMo
  • 11,793
  • 1
  • 33
  • 48
  • Hi @Mimo, Thanks for the code, I dont see the expected output , wondering how should i include `<![CDATA[ ` in the element. – kumar Sep 09 '13 at 15:35
  • I get the correct output - see above. The XSLT already adds the XML directive. – MiMo Sep 09 '13 at 17:32
  • thanks for the detailed information, I forgot to mention this morning that i also need to skip some elements that are having same template match "jndi:value" from adding CDATA. Please check the updated source file and output. – kumar Sep 09 '13 at 18:04
  • To the best of my knowledge you cannot generate with a XSLT the same element sometimes with CDATA content and sometimes not. Having those elements with or without CDATA content should not make any difference though: in the end CDATA is just a way to simplify the coding, but the text a XML parser would load is exactly the same. – MiMo Sep 09 '13 at 18:54
  • Is it possible to group the elements that need CDATA and that don't need CDATA. Example: If a name of the parent element is `` add a CDATA to that element else don't do any CDATA for that element. – kumar Sep 09 '13 at 19:01
  • how to add newline before CDATA section starts and ends, Example: `new line<![CDATA[ ...... new line ]]>` – kumar Sep 09 '13 at 19:47
  • 'Is it possible to group the elements..': to the best of my knowledge no. – MiMo Sep 09 '13 at 20:55
  • any idea how to add new line before CDATA and after end of CDATA. – kumar Sep 10 '13 at 02:07
  • No idea - but why would you want to do that..? – MiMo Sep 10 '13 at 12:55
  • If i can put the CDATA in new line, I planning to put `...` for all the one's that i want to have CDATA sections, so once they are converted to CDATA, i can remove the unwanted nodes(in our case that would be `` from an xml file. This way we can group CDATA elements and non CDATA elements. – kumar Sep 10 '13 at 12:59
  • ...why do you want only some CDATA? Having all CDATA (or none) does not make any difference in the actual content of the XML – MiMo Sep 10 '13 at 13:00
  • because i have some jndi:bindings whose jndi:values are need to be in CDATA sections and some need to be in non cdata sections, So in order to accomplish this i am trying to add a new nodes for the elements that need a CDATA so that i can match all nodes and wrap CDATA section to them. – kumar Sep 10 '13 at 13:19
  • ...why some need to be in a CDATA section and other not? It should make no difference – MiMo Sep 10 '13 at 13:22