用java处理xml数据
XML是一种受支持的Internet标准,用于对结构化数据进行编码,这种方式几乎可以通过任何编程语言轻松解码,甚至可以由人类使用标准文本编辑器来读取或编写。 许多应用程序,尤其是符合现代标准的Web浏览器,都可以直接处理XML数据。
作为基于文本的标准,XML非常适合在客户端和服务器系统之间交换数据。 许多数据已经基于文本(文件路径,描述,地址,名称等),并且诸如整数,浮点数和日期之类的数据可以轻松地在字符串表示形式之间进行转换。
不幸的是,将某些数据(例如XHTML或XML标记)包含在XML文档中既麻烦又麻烦。 将标记放入XML元素的一种方法是将标记字符[小于(<),大于(>)和&符(&)]替换为其等效实体(&lt ;、>和&& ; 分别)。 这扩展了数据,并使人类极度难以阅读,更不用说如果您在文本编辑器中手动编写XML会带来翻译标记的烦恼。
更好的解决方案可能是将数据直接放入XML文档中。 这就是XML的CDATA部分起作用的地方。
什么是CDATA?
XML文档中的文本通常是解析的字符数据,或(用“文档类型定义”术语而言)是PCDATA。 XML的特殊字符(&,<和>)在PCDATA中可以识别,并用于解析元素名称和实体。 解析器将CDATA(字符数据)部分视为数据块,使您可以在数据流中包括任何字符。
如果您曾经尝试将一些HTML或XML放入XML文档中(可能作为文档),则在包含示例时就遇到了这个问题。 清单1显示了一个简单的段落示例,其中带有一些强调的文本。
清单1.示例元素中的一些示例XHTML
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
Paragraphs can include emphasized text.
</description>
<example>
<p>The pug snoring on the couch next to me is
<em>extremely</em> cute.</p>
</example>
</sample>
当您想显示标记时,这变成了一场噩梦(请参见清单2 )。
清单2.带有标记的示例XHTML
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
Paragraphs can include emphasized text.
</description>
<example>
<p>The pug snoring on the couch next to me is
<em>extremely<em> cute.</p>
</example>
</sample>
通过将示例标记包装在CDATA部分中,可以按原样编写示例标记,而无需XML解析器尝试将其解释为包含<em>元素的<p>元素。 如果您的XML是根据DTD或XML Schema进行验证的,则这是必需的(除非DTD或XSD中实际存在的元素并且可以在文档中包含该元素)。 参见清单3 。
清单3.使用CDATA保护示例
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
Paragraphs can include emphasized text.
</description>
<example>
<![CDATA[<p>The pug snoring on the couch next to me is
<em>extremely</em> cute</p>]]>
</example>
</sample>
使用CDATA
从清单3的简短示例可以看出,CDATA节以特殊序列<![CDATA[
并以]]>
序列开始。 这些标记位之间的任何内容都将原样通过XML解析器。 一些开发平台具有一个特殊的CDATA对象(例如在XML DOM中找到的CDATASection)来表示CDATA部分的内容,但是其他开发平台会将其提供为更通用的东西,通常是XML文本节点。 在任何一种情况下,CDATA部分的内容将可用而无需修改。
尽管XML通常对空格非常宽容,但]]>
节结尾不能包含空格或换行符。
XHTML中的CDATA
如果您查看了许多嵌入JavaScript的网页,则可能已经看到了CDATA的实际应用。 您会经常看到类似清单4的内容 。
清单4. XHTML的<script>元素中的CDATA
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type"
content="application/xhtml+xml;charset=utf-8"/>
<title>CDATA Section in Action</title>
<script type="text/javascript">
// <![CDATA[
function nowWeAreSafe( x, y, z ) {
// Without the CDATA section, these would cause
// parsing errors:
if( x < y && y > z ) {
return y--;
}
return 0;
}
// ]]>
</script>
</head>
<body>
...
</body>
</html>
<script>
元素中JavaScript以包含CDATA节开头的注释开头,以以CDATA节结尾的注释结尾。 直到您意识到没有CDATA部分,脚本将通过Web浏览器的XHTML解析器运行,这似乎是使XHTML和JavaScript嘈杂的一种毫无意义的方法。
除非您非常非常不幸,否则这通常不会造成麻烦,但是它肯定会导致解析器错误,从而导致令人困惑且难以调试的呈现错误。 为什么?
您可能已经猜到了,<,>和&字符可能被标记为元素或实体(或杂散标记字符)。 同样,连字符(-)可以看作是XHTML注释块的意外开始(或结束)。 实际上,这就是为什么您应该将嵌入式脚本包装在CDATA节中而不是XML注释的原因-注释太脆弱了。
CDATA有时也会在内联<style>
元素中显示,尽管这种用法并不常见(参见清单5 )。
清单5. CDATA防止解析<style>元素中的错误
<style type="text/css">
/* <![CDATA[ */
body {
background-image:
url("marble.png?width=300&height=300")
}
/* ]]> */
</style>
再次注意,CDATA标记如何隐藏在特定于语言的注释中,以免混淆客户端Web浏览器中CSS解析器。
CDATA的局限性
显然,CDATA部分很有用,但与所有其他优点一样,您需要牢记一些限制。
浏览器通常不是XML解析器
浏览器根本无法可靠地执行HTML或XHTML中的CDATA。 XHTML的任何地方都允许使用CDATA节(就像在任何XML应用程序中一样),但实际上它们被完全忽略了。 您将丢失其内容(CDATA部分已从常规DOM中消失),或者将内容呈现为带有一些杂散标记字符的文本。
要查看这种效果,请查看一个页面,该页面显示了示例段落,带有可见标记的示例段落(使用实体),并试图使用CDATA显示带有标记可见的示例段落。 XHTML页面源在清单6中 。
清单6.尝试在XHTML中使用CDATA
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8"/>
<title>CDATA Section in Action</title>
</head>
<body>
<h1>CDATA Section in Action</h1>
<p>
A sample paragraph:
</p>
<p>The pug snoring on the couch next to me is <em>extremely</em>
cute.</p>
<p>
Markup version:
</p>
<p id="no1">
<p>The pug snoring on the couch next to me is <em>extremely</em> cute.</p>
</p>
<p>
CDATA version:
</p>
<p id="no2">
Uh,
<![CDATA[<p>The pug snoring on the couch next to me is <em>extremely</em> cute.</p>]]>
where?
</p>
<p>
Wait, what?
</p>
</body>
</html>
Firefox 3使用CDATA部分的内容, 如图1所示 。 (查看图1的纯文本版本 。)
图1. Firefox忽略了CDATA部分
基于WebKit的浏览器(例如Safari和Chrome)使用虚假的标记字符对其进行渲染(请参见图2 )。 (查看图2的纯文本版本 。)
图2. Safari和Chrome渲染CDATA部分
InternetExplorer®还使用类似的虚假标记字符来呈现它(请参见图3 )。 (查看图3的纯文本版本 。)
图3. Internet Explorer 8还呈现了CDATA部分
尽管当XHTML文档中包含CDATA节时浏览器无法正常工作,但是它们必须在通过Ajax加载的XML文档中正确处理它们。 如果不这样做,浏览器的XML解析器将被视为“不符合”标准,人们会毫不留情地对其进行嘲笑,然后再将其标记为对Ajax来说是严重破坏。
节末还是很特别
即使您可以将任何内容放入CDATA节中,节结束标记]]>
的顺序也被认为是特殊的。 您绝对不能嵌套CDATA节。 如果XML解析器读取此序列,则这是CDATA部分的结尾,当它到达实际部分结尾时,您可能最终会收到解析器错误。
换句话说,XML(或XHTML)解析器看不到您在CDATA节中使用<![CDATA[
因为解析器忽略节结束标记]]>
之外的标记字符(请参见清单7 )。
清单7.这是无效的XML。 您不能嵌套CDATA部分
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
You can't nest CDATA sections.
</description>
<example>
<![CDATA[You want a <![CDATA[ ]]> inside your
example? No, this is wrong.]]>
</example>
</sample>
如果需要在CDATA节中放置节结束标记,该怎么办? 您需要将其分为两个CDATA部分(请参见清单8 )。
清单8.在CDATA节中放置节结束序列的正确方法
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
Split up the section end.
</description>
<example>
<![CDATA[You want a ]]]]><![CDATA[>
inside your example? Do it this way.]]>
</example>
</sample>
也就是说,用]]]]><![CDATA[>
]]>
替换数据中的任何[ ]]>
,这样序列中的最后一个>便不在括号内。 解析器正在寻找[ ]]>
作为三个字符的序列,并通过将其拆分来破坏序列。
是的, ]]]]><![CDATA[>
是令人恐惧的标记。 幸运的是,这种情况很少出现。
还是文字
即使CDATA部分的内容保持不变通过了解析器,它们仍然需要是有效的XML数据字符,如文档的字符编码所指定。 使用类似UTF-8的名称可以使数据使用很大范围的字符,但是它不是8位整洁的。
任何所谓的控制字符(十六进制值低于0x20的空格字符)都可能导致解析器因无效的令牌错误而停止。 您不能只获取任何数据并将其转储到CDATA节中,但仍然具有有效的文档。
大小事项
当使用CDATA节将数据块添加到XML时,要记住的最后一件事是大小。 如果通过Web服务提供XML文件,请确保客户端应用程序可以处理潜在的大型数据传输,而不会因3G连接上的数据滴入而超时或阻塞其用户界面。
反之亦然。 确保您的服务器可以接受来自发送XML数据的客户端的大型上游传输。 Web服务器(尤其是Windows®平台上的IIS)通常具有相当小的上传限制,以帮助防止拒绝服务攻击。 像这样从浏览器发送大量数据很容易出错(例如,如果用户因为认为传输已崩溃而取消了传输,该怎么办?)并且倾向于锁定服务器和客户端上的宝贵资源。
同样,根据您的操作,需要记住许多人正在使用移动平台,而其他人也可能会卡在拨号连接上(仍然!),前提是您的应用程序在LAN之外运行。
即使您未采用这种方式设计,也有人会尝试通过iPhone上的拨号VPN连接来使用它,他们会抱怨您应用程序的速度,而不是选择糟糕的生活!
以XML存储二进制数据
当确实需要在XML文档中包括一些二进制数据时,您需要确保它不会触发XML解析器。 如果数据恰好是文本,则可以将其转储到CDATA节中并进行处理,但是真正的二进制数据需要以安全且可恢复的方式进行编码。
幸运的是,MIME标准定义了一种受良好支持的安全编码方案base64。 base64编码使二进制数据的大小约为原始大小的137%,因此您需要权衡额外的存储空间(和少量处理吞吐量)才能将二进制数据嵌入XML文档中。
通常,您希望在XML中指定编码和原始文件名,如清单9所示 。
清单9. XML文档中一个base64编码文件的示例
<?xml version="1.0" encoding="UTF-8"?>
<sample>
<description>
An embedded image file.
</description>
<image name="stop.png" encoding="base64"
source="FamFamFam"
href="http://www.famfamfam.com/lab/icons/silk/">
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQ
CAYAAAAf8/9hAAAABGdBTUEAAK/INwWK
6QAAABl0RVh0U29mdHdhcmUAQWRvYmUg
SW1hZ2VSZWFkeXHJZTwAAAJOSURBVDjL
pZI9T1RBFIaf3buAoBgJ8rl6QVBJVNDC
ShMLOhBj6T+wNUaDjY0WmpBIgYpAjL/A
ShJ+gVYYYRPIony5IETkQxZ2770zc2fG
YpflQy2MJzk5J5M5z/vO5ESstfxPxA4e
rL4Zuh4pLnoaiUZdq7XAGKzRJVbIBZ3J
PLJaD9c/eCj/CFgZfNl5qK5q8EhTXdxx
LKgQjAFr0NK0ppOpt9n51D2gd2cmsvOE
lVcvOoprKvuPtriNzsY8rH+H0ECoQEg4
WklY1czP8akZby51p6G3b6QAWBl43llS
VTlUfuZE3NmYh9Vl0HkHSuVq4ENFNWFd
C+uJ5JI/9/V2Y//rkShA1HF6yk/VxJ0f
07CcgkCB7+fSC8Dzcy7mp4l9/khlUzwe
caI9hT+wRrsOISylcsphCFLl1RXIvBMp
YDZJrKYRjHELACNEgC/KCQQofWBQ5nuV
64UAP8AEfrDrQEiLlJD18+p7BguwfAoB
UmKEsLsAGZSiFWxtgWWP4gGAkuB5YDRW
ylKAKIDJZBa1H8Kx47C1Cdls7qLnQTZf
fQ+20lB7EiU1ent7sQBQ6+vdq2PJ5dC9
ABW1sJnOQbL5Qc/HpNOYehf/4lW+jY4v
h2tr3fsWafrWzRtlDW5f9aVzjUVj72Fm
CqzBypBQCKzbjLp8jZUPo7OZyYm7bYkv
w/sAAFMd7V3lp5sGqs+fjRcZhVYKY0xu
pwysfpogk0jcb5ucffbbKu9Esv1Kl1N2
+Ekk5rg2DIXRmog1Jdr3F/Tm5mO0edc6
MSP/CvjX+AV0DoH1Z+D54gAAAABJRU5E
rkJggg==
</image>
</sample>
在机器生成的XML文档中,您可以保留空白,并一起运行整个base64编码的文件,而无需换行符。
避免问题
处理XML中的二进制数据的最佳方法是完全避免使用二进制数据。 正如您在HTML中所看到的那样,以标准化的方式引用外部文件非常有效。 当您可以通过某种方式让客户端应用程序获取外部文件时,这是一个不错的选择。 对于HTML',浏览器仅发出另一个HTTP请求,以获取通过<img>之类的元素包含的数据。
通过不将二进制数据直接包含在XML中,可以避免潜在的浪费文本编码,并可以实现其他增强功能,例如大多数人在其Web浏览器中喜欢的图像缓存。
摘要
您可以使用XML的CDATA部分(以<![CDATA
开头并以]]>
结尾]]>
来使文档的一部分远离解析器。 尽管您需要通过停止并重新启动CDATA节来保护任何]]>
序列,但内部的数据将以与输入的文本完全相同的方式从解析器中出来。
即使您不能利用XHTML文档中的CDATA部分,浏览器和常规编程平台也都很好地支持XML。 使用CDATA将标记的数据直接嵌入到XML文档中使您不必对数据进行编码,但是您需要格外小心,并考虑(可能)大量数据传输对客户端和服务器应用程序的影响。
当您需要在XML文档中存储二进制数据时,可以使用诸如标准MIME base64编码之类的文本编码,尽管引用外部文件可能是一个更好的主意。
翻译自: https://www.ibm.com/developerworks/xml/library/x-cdata/index.html
用java处理xml数据