4.6.4 XML文档的定义和验证
XML是为数据共享交互设计的,而作为一种元标记语言,不同的开发团队可能采用不同的数据格式、标签格式,导致数据交流不畅、阻碍设备/程序间的文档交换。如【例4-33】和【例4-34】所示,图书出版行业的不同书商采用不同的标签描述具有相同含义的图书信息,将导致交流障碍。
【例4-33】书商A用于描述图书信息的文档。
【例4-34】书商B用于描述图书信息的文档。
从例子中可以看到,同样是描述图书信息,两个文档的数据结构和元素标签名、属性都有所差异。如果由程序来解析处理将导致数据难以交流共享。为解决这一问题,需要不同领域的从业者针对各自领域的特点制定共通的模式信息,用于规范和约束XML文档,保证数据交流和共享的顺利进行。
XML模式信息是描述数据及其结构的模型,用于定义文档的数据结构、词汇表和语法规则。模式信息对文档的逻辑结构进行了约束,这种约束可以比较宽松,也可以十分严格。它不仅可以规定XML文档中应包含哪些元素、属性,还可以规定元素之间的内在联系,比如元素之间如何嵌套、它们出现的顺序、元素可以包含的属性,等等。模式信息相当于XML文档的模板,各行业或组织应根据自己行业的特点建立适应性良好的规范的模板,方便行业内、组织内统一文档格式,以便数据更好地交互分享。
制定XML模式信息即是文档的定义。文档的定义使用户能够不依赖具体的数据就知道文档的逻辑结构。在没有XML文档的时候,也可以根据文档定义为XML文档编写处理程序,这样可以有效地提高工作效率。
将创建的XML文档与模式信息进行比较,即文档的验证。若该文档与模式信息列出的规则相匹配,则称为一个有效的文档。一个完整意义的XML文档不仅应是符合语法规范的“格式良好”的文档,还应该是一个有效的文档。
目前常用的撰写XML模式信息、实现文档定义和验证的语言是由W3C推荐的DTD(Document Type Definition)和XML Schema。
1.DTD
DTD中描述的基本部件是元素和属性,它们负责确定XML文档的逻辑结构。元素表示一个信息对象,而属性表示这个对象的性质。DTD的语法与XML有所不同,基本结构包括XML文档元素的声明、元素的相互关系、属性列表声明,等等。
以下面的例子来看DTD是怎么定义XML的文档结构的。
【例4-35】DTD使用示例。
在上例中可以看出,!DOCTYPE表示DTD声明的开始,其后的book表示XML文档的根元素名。后续由!和括起来的内容均是DTD定义的内容,]标明了声明结束。其中规定了:
·根元素book包含子元素booktitle、author、isbn、publisher、publishtime、price。
·元素booktitle、author、isbn、publisher、publishtime、price的文本内容是可解析的文本#PCDATA(Parsed Character Data),也就是说,这些元素的文本中不能再含有其他子元素。因此这种写法author Alice sex female/sex/author就是错误的,因为Alice sex female/sex中含有标签sex。
(1)DTD中元素的定义
在DTD中,元素的定义方式如下:
!ELEMENT元素名元素定义)
元素定义可以有几种方式。
·当包含多个子元素时,可以将子元素的名称列出,如前面的例子!ELEMENT book(booktitle,author,isbn,publisher,publishtime,price)。
·当要在多个互斥的子元素中选择一个时,用|将子元素隔开,如!ELEMENT publish(publisher|ISBN|pubdate),表示子元素publisher、ISBN、pubdate都是可选的。
·当没有下一级子元素时,元素定义写成(#PCDATA),表示字符类型数据,如!ELEMENT author(#PCDATA)。
·当不确定是否有元素时,使用ANY关键词,如!ELEMENT description ANY。
·当需要对子元素出现的次数进行控制时,使用?*+控制。其中?表示可能出现一次或者不出现;*表示可能不出现或者出现多次;+表示出现一次或者多次,但至少出现一次。例如,
!ELEMENT book(booktit le,author,isbn,publ isher,publ ishtime,price)+
(2)DTD中属性的定义
在DTD中,还必须对属性进行定义。属性的定义格式如下:
!ATTLIST元素名属性名属性类型属性附加声明
属性的类型最常见的有两种,一种是CDATA型,一种是Enumerated型。
·CDATA型
表明属性值不包含和”等保留字符,如果属性值中需要包含这些字符,需要使用转义字符。
·Enumerated型
如果属性值不是任意的字符串,而是在几个可能的值中进行选择,如书籍的类别属性,可以为“历史”“地理”“文学”等,不能为其他情况时,可以将类别属性设定为Enumerated型。这种类型不需要在定义中显式地指出。例如,
!ATTLIST bookinfo category(“历史“|“地理“|“文学“)
属性的类型除了最常见的CDATA和Enumerated外,还可能有其他几种类型:ID、IDREF和IDREFS型、ENTITY和ENTITIES型、NMTOKEN和NMTOKENS型、NOTATION型。具体说明请参考相关文档。
属性附加声明用于描述属性额外的相关信息。常用的属性附加声明包括#REQUIRED、#IMPLIED、#FIXED“固定值”以及“默认值”。具体说明请参考相关文档。
例如,!ATTLIST memory unit CDATA“MB”,这里定义了memory元素中的unit属性,类型是CDATA,表示字符类型数据,引号括起来的表示默认值是“MB”。
当某元素有多个属性时,应对每个属性都加以声明,对属性的先后顺序没有要求。
【例4-36】声明属性示例。
上述代码则将属性的声明放在其相关的元素声明之前。
(3)DTD的使用
DTD有两种使用方式:内部DTD和外部DTD。所谓内部DTD是指DTD的定义和XML文档写在同一个文档中,外部DTD是指XML文档引用一个扩展名为DTD的独立文件。
【例4-37】是一个引用内部DTD的文档。
【例4-37】引用内部DTD的文档示例。
例子中DTD的定义写在了XML文档中。
引用外部DTD也分为两种情况,一种是引用私有的外部DTD,即自定义的DTD,如公司开发小组定义的DTD;另一种是引用国际标准组织发布的技术建议或者某一领域公开的标准DTD。
【例4-38】引用私有的外部DTD的文档示例。
…
其中book是该XML文档的根元素,它引用了自定义的mydef.DTD文档。
【例4-39】为一个引用公开外部DTD的文档。
【例4-39】引用公开外部DTD的文档示例。
2.XML Schema
使用DTD虽然带来较大的方便,但DTD也有一些不足:一是它用不同于XML的语言编写,需要不同的分析器技术,这对于工具开发商和开发人员都是一种负担;二是DTD不支持名称空间;三是DTD在支持继承和子类方面的局限性;最后,DTD没有数据类型的概念。
为解决这些问题,W3C在2001年5月正式发布了XML Schema的推荐标准,经过数年的大规模讨论,成为XML环境下首选的数据建模工具。XML Schema是继DTD之后第2代用来定义和验证XML文件的标准。它拥有许多类似DTD的准则,但又要比DTD强大一些。XML Schema本身是一个有效的XML文档,文件扩展名为.xsd。通过该文档可以更直观地了解所定义的XML文档结构。
【例4-40】是一个XML Schema的使用示例。
【例4-40】XML Schema的使用示例。
这个例子第1句为XML文档声明语句,根元素为xsd:schema,其属性xmlns:xsd=“http://www.w3.org/2001/XMLSchema”表明在XML Schema中定义了命名空间。xsd:element name=“book”是元素声明语句,为XML文档定义了一个根元素book,该元素是一个复杂类型xsd:complex Type,它包含了子元素booktitle、author…,等等。这些子元素是顺序排列的,因此使用了sequence标签,将这个顺序排列的子元素包含起来。每个子元素都有自己的类型,类型可以是简单类型也可以是复杂类型。在这个例子中的子元素都是简单类型,如元素booktitle是string型的,元素price是integer型的。
以这个例子和DTD定义做一个对比,发现它们有以下的不同。
·XML Schema的语法和XML文档的语法相同,而DTD的语法与XML文档的语法不同。
·XML Schema的元素有“类型”的概念。例如,根元素book是复杂类型,元素booktitle是string型,元素price是integer型。在DTD中是没有这种概念的。
·在XML Schema中有命名空间的概念,如xsd等,在DTD中则没有。