除经特别注明外,本站文章版权归JScud Develop团队或其原作者所有.
转载请注明作者和来源. scud(飞云小侠) 欢迎访问 JScud Develop
根据XML中CDATA类型的规范可以知道:"&"和"<"不需要也不能被转换. ">" 如果出现在"]]>" 的内容而不是表示结束时,必须被转义为>
但是这样就存在一个问题,如果我需要输入"]]>",正确的处理是保存为"]]>",但是如果我想输入"]]>",那么应该如何保存哪? 我想了很久,除非加空格或者采用特殊的办法,否则是没有办法解决的.
1.如果我们不考虑输入"]]>"的问题,来考虑一下"]]>"的处理,看看各种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 ]]> ]]></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=]]>"); //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的结果也没有把字串"]]>"翻译为"]]>".
接着再来测试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]]>"); 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[ <hr> ]]> ]]></description> </item> </channel> </rss> |
结果:
1.POTU没有做任何处理
2.FeedDemon做了处理,不过同时也把其他的> <等等都翻译了,这就更不对了..
本来我是打算在RSS里使用CDATA类型的description字段的,经过几番试验和测试,最后决定还是使用普通的description字段了,不在使用CDATA了.
CDATA? 鸡肋乎? 呵呵