![Java核心技术·卷Ⅱ:高级特性(原书第10版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/937/34339937/b_34339937.jpg)
3.3.2 XML Schema
因为XML Schema比起DTD语法要复杂许多,所以我们只涉及其基本知识。更多信息请参考http://www.w3.org/TR/xmlschema-0上的指南。
如果要在文档中引用Schema文件,需要在根元素中添加属性,例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/139-i.jpg?sign=1739510847-1O6iwstCsbQw4hHWY7PLlDYBiHFClor8-0-3a11947eaa0912541c2a36a05130bf1a)
这个声明说明Schema文件config.xsd会被用来验证该文档。如果使用命名空间,语法就更加复杂了。详情请参见XML Schema指南(前缀xsi是一个命名空间别名(namespace alias),请查看第3.5节以了解更多信息)。
Schema为每个元素都定义了类型。类型可以是简单类型,即有格式限制的字符串,或者是复杂类型。一些简单类型已经被内建到了XML Schema内,包括:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-i.jpg?sign=1739510847-0lJ0MXLFYReraiNnwBGXC9S7zKCQrmcE-0-52fd94d6b811bc67196fc5b87250e403)
注意:我们用前缀xsd:来表示XSL Schema定义的命名空间。一些作者代之以xs:。
可以定义自己的简单类型。例如,下面是一个枚举类型:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-2-i.jpg?sign=1739510847-yKAK19fbgC3sHkXET4CeYQ7gNSBTplzY-0-7d5013b4a393a1366dd229c4f30f202d)
当定义元素时,要指定它的类型:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-3-i.jpg?sign=1739510847-BkGRyCrZMWqK4ZPP8Om0j9CAmXxAJofR-0-a08e03eee16bb9026aa8d0527555c8a9)
类型约束了元素的内容。例如,下面的元素将被验证为具有正确格式:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-4-i.jpg?sign=1739510847-cueeHyWjKMoCdPVuYlQr93ptGZ4PluVv-0-c634b7a128938deac1b981ee7535d9ee)
但是,下面的元素会被解析器拒绝:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-5-i.jpg?sign=1739510847-MnvbUIHel9Kc9UL6uE7EZNLLdD1XaKx1-0-b917de8e05b8f74bfc14738b51c2acd1)
FontType是name、size和style元素的序列。在这个类型定义中,我们使用了ref属性来引用在Schema中位于别处的定义。也可以嵌套定义,像这样:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/140-6-i.jpg?sign=1739510847-jI12SIGoOKde7SsFWvUNut8GYr3Qqj0o-0-459be366266b27c7f926cbf26b16b47e)
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-i.jpg?sign=1739510847-sr3uHjYtO5mx1TXIAjpngF1QoXezBvzW-0-8e06e08f95599051fbc027afe986d8ca)
请注意style元素的匿名类型定义。
xsd:sequence结构和DTD中的连接符号等价,而xsd:choice结构和|操作符等价,例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-2-i.jpg?sign=1739510847-UNdTsDSctg9cjoB0tqiJvCtMJKUC5LML-0-652184ff93c05c32ca4c7bbec9834c0b)
这和DTD中的类型email|phone类型是等价的。
如果要允许重复元素,可以使用minoccurs和maxoccurs属性,例如,与DTD类型item*等价的形式如下:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-3-i.jpg?sign=1739510847-tGinfuTUMZXUmzDLhXpeBchKu0Vt23UQ-0-e294d5c06d56cc37b870dab1cc9d0b1d)
如果要指定属性,可以把xsd:attribute元素添加到complexType定义中去:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-4-i.jpg?sign=1739510847-RSoI82cmh7d29sIVEcshVnQDpRv3BHn2-0-5a09ef604bbca488023d357fa4c2b5c6)
这与下面的DTD语句等价:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-5-i.jpg?sign=1739510847-9gKZvUuOx2sPiVyCUl57QkyhG8cAZtxN-0-87fcc062c64eb7d0af4b3b17eaee792d)
可以把Schema的元素和类型定义封装在xsd:schema元素中:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-6-i.jpg?sign=1739510847-0W5hGq3iISp1OOQtDY3kOetPPssH37ZK-0-2dac7230bab01d833a430263e7a59b8e)
解析带有Schema的XML文件和解析带有DTD的文件相似,但有3点差别:
1)必须打开对命名空间的支持,即使在XML文件里你可能不会用到它。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-7-i.jpg?sign=1739510847-Qbc0QSAIaQicIFkQO5viC34PC5IkQoHi-0-70f9498265e198aec89c2d1fa58407c1)
2)必须通过如下的“魔咒”来准备好处理Schema的工厂。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/141-8-i.jpg?sign=1739510847-x0nvzgUnlLK9NZiCtmKswQkeFqYYRJpD-0-309fa1267886f4f1a220d5cc651ae8d4)
3)解析器不会丢弃元素中的空白字符,这确实很令人恼火,关于这是否是一个bug,人们看法不一。有一种变通方法,请参看程序清单3-4中的代码。