人们都很喜欢 XML 以及它所提供的灵活性和互操作性,但是,通过使用一些技巧,可以使与 XML 的互操作和与 XML 一起使用的工具更加简单。在处理 XML 时养成一些良好的习惯可以保证最高效地利用您的 XML 文档和应用程序。
使用 10 种良好的习惯
以下是 10 种最良好的 XML 习惯:
- 定义 XML 和编码
- 使用 DTD 或 XSD
- 记得进行验证
- 验证并不总是能够解决问题
- XML 结构和属性
- 使用 XPath 查找信息
- 并不总是需要使用解析器提取信息
- 何时使用 SAX 而非 DOM 解析
- 何时使用 DOM 而非 SAX 解析
- 使用良好的 XML 编辑器
![]() |
|
在快速创建 XML 文档时,一般都会倾向于创建基本的结构并避开一些普通 XML 文档需求,包括指定 XML 文档声明和 XML 文档包含的数据的编码类型。
考虑清单 1 所示的 XML 文档。
清单 1. 未包含 XML 声明和数据编码类型的 XML 文档
<phrases> <phrase lang="en">Hello</phrase> <phrase lang="it">Buongiorno</phrase> <phrase lang="fr">Salut!</phrase> </phrases> |
对于普通人来说,可以查看该文档并将其识别为 XML,但是对于计算机来说,则很难作出这样的判断。在文件顶部添加 XML 声明,可以使它更加明确、更容易识别。一行简单的代码就可以说明文档是 XML,并且指出版本号和 XML 数据使用的字符编码类型。例如:
<?xml version="1.0" encoding="us-ascii"?> |
编码说明中的内容也应该确保正确性。XML 解析器使用编码确保 XML 文档的单个字符被正确载入。例如,继续 清单 1 中基于短语的示例,如果向文档添加一个俄语条目,则会出现问题,因为目前指定的编码不支持扩展的字符集(使用俄语短语表示 hello 时要求使用扩展字符集)。
指定错误的编码意味着解析器不能正确处理文档;例如,如果将一个多字节扩展字符读取为一个单字节组成的序列,那么会导致数据的损坏和不良输出
添加了 XML 声明后,应该确保使用 DTD 或 XSD 定义有效的 XML 文件的结构。这两种方法都允许 XML 解析器检查并确定 XML 文件的内容与建模数据对应的结构相匹配。
例如,给出一个针对联系(contact)数据库的简单 XML 结构,您希望定义一种结构来指定联系人的姓名、地址和电话号码。使用 DTD 方法可以使您映射这种结构并确保结构中的每一个联系人与布局相匹配。
例如,清单 2 中显示了针对联系数据库的 DTD。
<!ELEMENT phone (#PCDATA)> <!ATTLIST phone type (home | work | mobile) #REQUIRED> <!ELEMENT contact (#PCDATA | name | phone | address)*> <!ELEMENT contacts (#PCDATA | contact)*> <!ELEMENT country (#PCDATA)> <!ELEMENT road (#PCDATA)> <!ELEMENT address (#PCDATA | road | city | state | postcode | country)*> <!ATTLIST address type (home | work) #REQUIRED> <!ELEMENT state (#PCDATA)> <!ELEMENT name (#PCDATA)> <!ELEMENT postcode (#PCDATA)> <!ELEMENT city (#PCDATA)> |
DTD 定义了描述联系人所需要的元素、属性(以及这些属性所支持的值)。例如,在 清单 2 可以看到,phone 元素有一个 type 属性,而 address 和其中的 component 元素也有属性。
使用 DTD 可以帮助确保属性的有效性,并且,和验证过程一起使用时可以识别任何问题。当和支持 XML 的编辑器一起使用时,DTD 可以帮助编辑和自动完成内容。
XSDs,即模式,可以执行很多与 DTD 相同的功能,但有其独特的用途。例如,一些 XML 编辑器需要使用 DTD 自动完成内容,然而模式在设计文档实际层次结构方面更加灵活。您可以根据具体环境选择工具。
查看清单 3,能否找出其中的问题?
<contacts>
<contact>
<name>Martin</name>
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
<address type="home">
<road>Home road</road>
<city>Home city</city>
<state>Home state</state>
<zipcode>12434</zipcode>
<country>USA</country>
</address>
</contact>
<contact>
<name>Sharon</name>
<phone type="work">234 567 8901</phone>
<phone>234 567 8901</phone>
<address type="home">
<road>Other home road</road>
<city>Other city</city>
<state>Other state</state>
<zipcode>39487</zipcode>
<country>USA</country>
</address>
<address type="work>
<road>Work building, work road</road>
<city>Work city</city>
<state>Work state</state>
<zipcode>12347</zipcode>
<country>USA</country>
</address>
</contact>
</contacts>
|
手动查找问题非常麻烦。但是可以通过 xmllint(一款可以检验 XML 文件的内容和结构的免费工具)运行文件,您可以查看运行该文件的输出,如清单 4 所示。
$ xmllint contacts.xml
contacts.xml:27: parser error : Unescaped '<' not allowed in attributes values
<road>Work building, work road</road>
^
contacts.xml:27: parser error : attributes construct error
<road>Work building, work road</road>
^
contacts.xml:27: parser error : Couldn't find end of Start Tag address line 26
<road>Work building, work road</road>
^
contacts.xml:32: parser error : Opening and ending tag mismatch: contact line 15
and address
</address>
^
contacts.xml:33: parser error : Opening and ending tag mismatch: contacts line 1
and contact
</contact>
^
contacts.xml:34: parser error : Extra content at the end of the document
</contacts>
|
尽管与最初的问题(其中的一个属性没有结束)相比似乎复杂了很多,但却为您查找问题提供了一个起点。
xmllint 还支持各种各样的命令行选项,帮助选择诊断方法和结果。其中最有用的一个选项是 --noout,它阻止 xmllint 在解析文件时回传内容。对于较短的文件来说没有什么影响,但对于大型文件来说则是一个问题。
如果正在使用 DTD,那么使用 --postvalid 选项告诉 xmllint 针对 DTD 验证内容,确保内容不仅是有效的 XML,而且还与 DTD 的结构相匹配。如果将 使用 DTD 或 XSD 为 contact 文件生成的 DTD 添加到文件,那么属性定义错误将被纠正,但随后将生成一个不同的错误,如清单 5 所示。
$ xmllint --noout --postvalid contacts.xml
contacts.xml:9: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:21: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:28: element address: validity error : Element zipcode is not declared
in address list of possible children
Document contacts.xml does not validate
|
这样使用 xmllint 可以方便快捷地确定文档的结构是否有效。xmllint 是 libxml2 工具箱的一部分,该工具箱已绑定到 Linux、UNIX® 和 Mac OS X,但 Windows® 需要独立下载。有关 xmllint 和 libxml2 的更多信息,请参见 参考资料。
验证并不总是能够解决问题
使用 xmllint 和类似工具验证 XML 文件(特别是如果使用了 DTD),是验证 XML 文件内容的很好方法。然而,这种方法也有其局限性。例如,如何处理 XML 文件的内容?
使用 DTD 或 XSD,您可以为属性指定明确的内容。您只是创建了带有一个字符串或 ID 的属性(可以是受限制的可用选项列表的一部分),但是不能使用这种方式控制或限制元素的内容。
例如,在联系人示例中,telephone numbers 元素包含数字和空格。但是没办法阻止用户向该元素添加字母字符。这样做在使用 xmllint 进行验证时不会检查出错误,并且编辑器和其他支持 XML 的解决方案也无法解决或识别这个问题。应用程序出现的故障可能和您预料的一样,因为它识别出一个非标准数据类型。
简而言之,XML 验证只能保证结构正确,而无法保证数据的有效性。
解决此问题的最简单方法是编写一个解析器,它可以读取 XML 文件并实际验证数据内容。但是不要过度地验证内容,只需确保数据符合应用程序的要求。
RSS订阅







收 藏
推 荐