分析XML中的CDATA类型在RSS中的使用

除经特别注明外,本站文章版权归JScud Develop团队或其原作者所有.
转载请注明作者和来源.  scud(飞云小侠)    欢迎访问 JScud Develop



根据XML中CDATA类型的规范可以知道:"&"和"<"不需要也不能被转换. ">" 如果出现在"]]>" 的内容而不是表示结束时,必须被转义为&gt;

但是这样就存在一个问题,如果我需要输入"]]>",正确的处理是保存为"]]&gt;",但是如果我想输入"]]&gt;",那么应该如何保存哪? 我想了很久,除非加空格或者采用特殊的办法,否则是没有办法解决的.

1.如果我们不考虑输入"]]&gt;"的问题,来考虑一下"]]>"的处理,看看各种XML解析器是如何处理的?

xml解析器的测试包含2个部分:设置cdata类型的数据和读出cdata类型的数据.

首先我们写一个测试的例子,计划使用JDom 1.0和Dom4j来测试一下:

 package com.jscud.test;
 
 public class XmlTestBase
 { 
     public static String xmlpart =
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
         "<xml>" +
         "<test>"+
         "<hello><![CDATA[ hello ]]&gt; ]]></hello>" +
         "</test>" +
         "</xml>";       
    
     public static void print(String str)
     {
         System.out.println(str);
     }    
 } 


JDom测试的例子如下:

package com.jscud.test;
 
 import java.io.*;
 import org.jdom.*;
 import org.jdom.input.SAXBuilder;
 import org.jdom.output.*;
 
 //@author scud http://www.jscud.com
 
 public class JDomXmlFileTest extends XmlTestBase
 {
 
     public static void main(String[] args) throws Exception
     {
         readDocument();
         print("===========================");
         createDocument();
     }
    
     public static void readDocument() throws Exception
     {
         Reader reader = new StringReader(xmlpart);
         SAXBuilder builder = new SAXBuilder();
        
         Document doc = builder.build(reader);
 
         Element aRoot = doc.getRootElement();
        
         Element anode = aRoot.getChild("test").getChild("hello");
        
         print(anode.getText());       
     }
 
     public static void createDocument() throws Exception
     {       
         Document doc = new Document();
        
         doc.setRootElement(new Element("root"));
        
         CDATA node = new CDATA("hello alt=]]&gt;");
        
         //throw Exception
         //node.setText("hello]]>");
        
         Element ele = new Element("hello");
        
         ele.setContent(node);
        
         Element root = doc.getRootElement();
        
         root.getChildren().add(ele);
        
         XMLOutputter outputter = new XMLOutputter();
         Format aFormat = Format.getCompactFormat();
         aFormat.setEncoding("GB2312");
        
         String sResult = outputter.outputString(doc.getRootElement().getChildren());
        
        print(sResult);
        
     }
 } 

 编译并运行上面的代码结果,我们可以看到JDom无法设置Cdata的值为"]]>",会报异常.从xml字符串读出cdata的结果也没有把字串"]]&gt;"翻译为"]]>".

接着再来测试Dom4J:

package com.xml.test;
 
 import java.io.StringReader;
 
 import org.dom4j.*;
 import org.dom4j.io.SAXReader;
 import org.dom4j.tree.DefaultCDATA;
 
 /**
  * 测试XML的CData数据类型.
  *
  * @author scud http://www.jscud.com
  *
  */
 
 public class Dom4jXmlTest extends XmlTestBase
 {   
 
     public static void main(String[] args) throws Exception
     {
         readDocument();
         print("===========================");
         createDocument();       
     }
    
     public static void createDocument()
     {
         Document document = DocumentHelper.createDocument();
         Element root = document.addElement( "root" );
        
         DefaultCDATA cdata = new DefaultCDATA("sample]]>");
         DefaultCDATA cdata2 = new DefaultCDATA("sample]]&gt;");
        
         Element anode = root.addElement("cdata");
         anode.add(cdata);
        
         print(anode.getText());       
         print(anode.asXML());
        
         Element anode2 = root.addElement("cdata2");
         anode2.add(cdata2);
        
         print(anode2.getText());       
         print(anode2.asXML());
     }
    
     public static void readDocument() throws Exception
     {
         StringReader strreader = new StringReader(xmlpart);
        
         SAXReader reader = new SAXReader();
         Document document = reader.read(strreader);
        
         Node node = document.selectSingleNode( "//test/hello" );
        
         print(node.getText());
        
         print(node.getStringValue());
     }
    
 } 

 
 我们可以看到Dom4j也是没有做任何处理,输入的时候不作任何转换,原样输出,这样必然导致xml错误.读出的时候也没有做转换.

根据上面的测试我们可以得出结论:很多xml解析器没有正确解析cdata的数据,(jdom和dom4j用的人比较多),不要太相信这些解析器.

 

2.我们再来看看阅读RSS的RSS阅读器吧,例如FeedDemon和POTU,我们准备了一个CData类型的description字段,来进行测试.

内容:

<?xml version="1.0" encoding="GB2312" ?>
 <rss version="2.0">
 <channel>
  <title>Some Where</title>
  <link>http://www.jscud.com/</link>
  <description />
 <item>
  <title>Test</title>
  <link>http://www.jscud.com</link>
  <author>scud</author>
  <pubDate>Mon, 22 Aug 2005 10:22:22 GMT</pubDate>
  <description><![CDATA[
  &lt;hr&gt;
  ]]&gt;
  ]]></description>
  </item>
  </channel>
  </rss>


结果
 1.POTU没有做任何处理
 2.FeedDemon做了处理,不过同时也把其他的&gt; &lt;等等都翻译了,这就更不对了..
 

本来我是打算在RSS里使用CDATA类型的description字段的,经过几番试验和测试,最后决定还是使用普通的description字段了,不在使用CDATA了.

CDATA? 鸡肋乎? 呵呵

 

posted on 2005-08-22 18:49 Scud(飞云小侠) 阅读(2585) 评论(0)  编辑  收藏 所属分类: Java


只有注册用户登录后才能发表评论。


网站导航:
 
<2005年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

公告

文章发布许可
创造共用协议:署名,非商业,保持一致

我的邮件
cnscud # gmail


常用链接

留言簿(15)

随笔分类(113)

随笔档案(103)

相册

友情链接

技术网站

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜