1、XML基础教程(第2版),第3章 有效的XML文件,本章主要内容,第3章 有效的XML文件,规范的XML文件和有效的XML文件,XML的核心是使用标记组织数据之结构,以便让信息的交互更加方便。 规范性仅仅是XML语言的基本语法,没有对XML文件怎样组织数据进行具体的限制。在某些系统中,如果不对XML怎样组织数据进行合理的约束,那么对同一问题编写的XML文件,在数据组织结构上就可能有很大的不同 。,例子1,例子1 time1.xml,国贸大厦08:30至18:30华联商场07:30至22:30,国贸大厦08:3018:30华联商场07:3022:30,例子1 time2.xml,3.1 有效XM
2、L文件的定义,对XML组织数据进行约束的主要原因有两个,一是让XML的数据组织的更加合理,符合系统的要求,二是便于维护XML中的数据,从而提高整个系统的可维护性。 对XML的数据结构进行限制有两种方式:使用文档类型定义(Document Type Definition,DTD)和XML Schema模式。一个规范的XML文件如果和某个DTD文件相关联,并遵守该DTD文件规定的约束条件,就称之为有效的XML文件。,3.1.1 初识DTD,DTD文件也是有着特殊结构的文件,简单地说,DTD文件是由元素所构成的文本文件。在DTD文件中,用关键字ELEMENT来定义一个元素,格式如下:,需要一个刻画商
3、店营业时间的XML文件,但数据之结构必须符合下列要求。Page 28 根标记的名称是“商店营业时间”。 根标记可以有若干个名称为“商店”的子标记。 名称为“商店”标记顺序地包含有名称为“商店名称”、“开门时间”和“关门时间”的子标记。 名称为“商店名称”的标记包含的内容只能是文本数据,不能包含有子标记 名称为“开门时间”的标记包含的内容只能是文本数据,不能包含有子标记。 名称为“关门时间”的标记包含的内容只能是文本数据,不能包含有子标记。,DTD通过其中的元素来限制XML文件中的标记 ,3.1.2 DTD文件的保存,DTD文件需使用文本编辑器编写、保存。DTD文件的扩展名必须是“.dtd”,保
4、存时所选择的编码必须和其关联的XML文件一致,比如,DTD所要约束的XML文件的编码为UTF-8,那么DTD文件也必须按着UTF-8编码保存。,limitShop.dtd,limitShop.dtd,3.1.3 XML文件与DTD文件相关联,一个XML文件只有和某个DTD文件相关联,才会受到该DTD文件的约束。 在XML文件中使用“文档类型声明”与一个DTD文件相关联。有两种形式的关联:SYSTEM和PUBLIC。 1. SYSTEM格式 使用SYSTEM文档类型声明的格式:例 和名字是“limitShop.dtd”的DTD文件相关联 2. PUBLIC格式 使用PUBLIC文档类型声明的格式
5、:例和名字是“limitShop.dtd”的DTD文件相关联 3. DTD文件的位置 SYSTEM或PUBLIC格式的文档类型声明中提到的:“DTD文件的URI“必须是一个有效的资源, 如果URI是一个文件的名字,该DTD文件必须和当前XML文件在同一目录中 如果URI是一个URL,该URL必须是可以访问的。,例子2,example3_2.xml,西单商场06:3023:00海淀商厦07:3018:30,limitShop.dtd,3.2 如何检查有效性,当用浏览器打开一个有效的XML文件时,浏览器的XML解析器仅仅检查XML文件是否是规范的、检查XML所关联的DTD文件是否有语法错误,并不检
6、查XML文件是否遵守该DTD规定的约束条件 。我们可以使用DOM 解析器来检查一个XML文件是否是有效的。简要的说明如下: 首先获取一个DocumentBuilderFactory对象factory:DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); factory设置是否检查XML文件的有效性:factory.setValidating(true); factory对象调用方法newDocumentBuilder()返回DOM解析器:DocumentBuilder domParser= factory. n
7、ewDocumentBuilder(); 解析器domParser调用public Document parse(File f) throws SAXException,IOException 方法解析XML文件。,例子3,TestValidate.java,DTD文件使用元素(ELEMENT)来约束XML文件中的标记,在DTD文件中使用ELEMENT定义一个元素,格式为:例如: 特别需要强调以下两点:DTD文件中的元素的作用与其在DTD文件中的书写位置无关。DTD文件中不允许使用多个元素约束同一个标记。,3.3 DTD中的元素,3.3.1 约束标记只包含有文本数据,如果准备约束一个标记没有子
8、标记,也就是说只能有文本数据,那么“标记的约束条件”是用小括号括起的#PCDATA,格式如下:例如,对于 下列3个名称是“姓名”的标记都是符合约束条件的标记:张三 而李逵男 是不符合约束条件的标记,3.3.2 约束标记的子标记_1元素的格式,若要约束XML文件中某个标记可以有怎样的子标记,那么 DTD中元素 声明的“标记的约束条件”是用小括号括起的子标记列表,格式为注: “子标记列表”中用逗号分隔列出的若干个标记 是有先后顺序的,“开学时间”标记 是不符 合约束的标记 清华大学201009 01 ,“开学时间”标记是符合约束的标记 201009 01 ,“开学时间”标记是不符合约束的标记 09
9、 201001 ,3.3.2 约束标记的子标记_2模式限定符的使用,1 元素格式 中的“子标记列表”的每个标记的后面可以尾加模式限定符号来限定该子标记出现的次数。不尾加限定符号的子标记必须出现且只能出现一次。限定符号有:+:尾加该限定符号的子标记必须出现一次或多次。*:尾加该限定符号的子标记可出现零次或多次。?:尾加该限定符号的子标记可出现零次或一次。 例如: 2 “子标记列表”中的子标记也可以是几个标记的“或运算”,而且“或运算”必须用小括号扩起,例如,元素:,例子4,example3_4.xml,fourDTD.dtd,3.3.3 约束标记的混合内容,一个标记的内容可以有两部分构成文本数据
10、和标记,其中的标记称做该标记的子标记.上面我们已经知道怎样使用DTD约束标记的子标记,比如约束“开学时间”恰好包含有3个子标记year、month和day,不可以包含有能显示的文本数据 。如果允许标记的内容即可以有可显示的文本数据,也可以有子标记,那么在DTD文件中,元素的“标记的约束条件”是关键字“#PCDATA”和若干个子标记的“或运算”,而且该“或运算”必须用小括号括起并尾加一个“*”号,格式如下:,注:几种常见的错误写法,及错误的原因见page 37,例子5,example3_5.xml,张三1993-12-12 男 孙翠花1992-01-31 女 ,fiveDTD.dtd,3.3.4
11、 EMPTY和ANY,如果准备约束一个标记是空标记,或者是只含有空字符的非空标记,元素的“标记的约束条件”可以是关键字“EMPTY”;如果不准备对一个标记有任何约束,元素的“标记的约束条件”可以是关键字“ANY”。,对于元素:下列2个标记都是符合约束条件的标记:,对于元素:下列2标记是符合约束条件的标记: how are youhow are you你好 ,3.4 DTD的完整性,(1)不允许无穷嵌套如果一个DTD元素约束某个标记可以出现某个子标记,那么对该子标记进行约束的DTD元素就不能约束该标记的子标记是它的父标记。DTD文件中同时出现下列两个元素是不允许的。 (2)XML文件中的每个标记
12、都必须在DTD中有相应元素进行约束。,nocomplete.dtd是不完整的 ,3.5 DTD中的属性约束列表,XML文件中的标记可以附带属性,标记附带属性的目的是为该标记添加附加信息。标记的属性是一个“名-值”对,即属性必须由名字和值组成。属性必须在非空标记的开始标签或空标记中声明,用“=”为属性指定一个值。例如,下列名字为“长方体”的空标记有三个属性:,3.5.1 ATTLIST属性约束列表_1,DTD文件中可以使用元素约束XML文件中的标记。同样,可以通过在DTD文件中定义属性约束列表来约束XML文件中的标记的属性。 DTD使用关键字ATTLIST定义一个属性约束列表来约束XML文件中标
13、记的属性,在DTD中定义属性约束列表的格式为:,ATTLIST属性约束列表1 ,ATTLIST属性约束列表2 ,例子6,example3_6.xml,A101自习室A606语音室,sixDTD.dtd,图3.4 使用ATTLIST属性约束列表约束属性,3.5.1 ATTLIST属性约束列表_2,1属性名称属性名称可以由字母、数字、下划线(“_”)、点(“.”)或连字符(“-”)组成,但必须以字母或下划线开头,属性的名称区分大小写。 2属性类型属性值一定是一个字符串,那么属性类型就决定了属性可以用怎样的字符串作为它的值。 注:属性值中都不能含有含有左尖括号 “”、与符号“&” 、单引号“”和双引
14、号“”,如果想使用这些字符,可以使用实体引用。要特别注意的是,属性值区分大小写。 3默认值情况ATTLIST定义的属性约束列表是为了约束XML文件中标记的属性,ATTLIST属性约束列表:中的“默认值情况”是对标记的属性进行约束的细节条件。,3.5.2 属性的默认值,ATTLIST属性约束列表 其中的“默认值情况”含有约束的细节条件。“默认值情况”可以是下列三种情形: “默认值情况”是字符串,例如:“默认值情况”是字符串“red“。 “默认值情况”是#IMPLIED或#REQUIRE,例如:“默认值情况”是#REQUIRED。 “默认值情况”是#FIXED “字符串“。例如:“默认值情况”是#
15、FIXED “119“。 “默认值情况”对标记的属性给予约束的意义如表3.1。,表3.1 默认值情况的约束意义,3.5.2 属性的默认值_1 “默认值情况”是字符串,“默认值情况”是字符串,例如:“默认值情况”是字符串“red“。 在编写XML中时,可以显示地为被约束的标记附加该属性,并且可以重新指定该属性的值。 编写XML文件时,也允许被约束的标记不显示地附加该属性,在这种情况下,解析器认为该标记有这个属性,并且默认值为ATTLIST属性约束列表中“默认值情况”给定的字符串。,例子7,example3_7.xml,电视机 2678元/台东北大米 5.9元/千克,sevenDTD.dtd,3.
16、5.2 属性的默认值_2 默认值情况”是#IMPLIED,在ATTLIST属性约束列表中可以设置属性的“默认值情况”是#IMPLIED。例如:这时,该属性就没有默认值,而且被约束的标记可以不附加该属性。当认为一个属性对于标记可有可无、且没有默认值时,就可以将属性的“默认值情况”设置为#IMPLIED。,3.5.2 属性的默认值_3 #REQUIRED,在ATTLIST属性约束列表中可以设置属性的“默认值情况”是#REQUIRED,例如:这时,该属性没有默认值,被约束的标记必须要附加该属性并给出属性的值。当不想为某个属性设置默认值,但要求标记必须附加该属性时,就可以将属性的“默认值情况”设置为#
17、REQUIRED。,3.5.2 属性的默认值_4 #FIXED,ATTLIST属性约束列表中可以设置属性的“默认值情况”是: #FIXED “字符串“ 例如:这时,该属性的默认值就是关键字# FIXED后面指定的那个字符串。 在编写XML文件时,即使被约束的标记不显示地附加该属性,解析器也认为该标记有这个属性,而且属性值是# FIXED后面指定的那个字符串。但是,在编写XML文件时,如果被约束的标记显示地附加该属性,那么不可以改变属性的值,即该属性的值必须是# FIXED后面指定的那个字符串。当准备约束标记的某个属性的值是固定不变的一个值,就可以将属性的“默认值情况”设置为: #FIXED “
18、字符串“,例子8,example3_8.xml,物理系专用 英语系专用 老师课间休息专用 学生课间休息专用 ,eightDTD.dtd,图3.6 默认值情况为#REQUIRED和#IMPLIED,例子9,example3_9.xml,不要乱打报警电话。一旦发生火灾,请及时拨打火警电话。救死扶伤 ,nineDTD.dtd,图3.7 默认值情况为#FIXED 图3.8 使用解析器检查出的错误,3.5.3 属性类型,属性类型决定了属性可以用怎样的字符串作为属性的值。属性的常用类型有:CDATA、Enumerated、NMTOKEN、NMTOKENS、ID、IDREF、IDREFS。,3.5.3 属性
19、类型_1 CDATA类型,1CDATA类型对于CDATA(Character Data)类型的属性,该属性的值可以是任何一个字符串,但是,字符串中不能含有含有左尖括号、右尖括号、与符号、单引号和双引号,如果想使用这些字符,可以使用实体引用。 例题3-10 page 47,例子10,example3_10.xml,张飞 李逵 ,tenDTD.dtd,3.5.3 属性类型_2Enumerated 类型,2Enumerated 类型如果属性的类型是Enumerated 类型,那么该属性只可以是枚举值。在ATTLIST属性约束列表中使用Enumerated类型的格式如下:例题3-11 page 48,
20、例子11,example3_11.xml,10010 中山路 20011 长江路 ,elevenDTD.dtd,3.5.3 属性类型_3 NMTOKEN类型,3NMTOKEN类型 如果属性的类型是NMTOKEN类型的属性,属性值可以由字母、数字、下划线(“_”)、点(“.”)或连字符(“-”)组成,属性值中不能含有空格字符(属性值也可以用数字、点或连字符开头)。例题3-11 page 49,!ELEMENT 作家名单 (姓名*) ,例子12,example3_12.xml,张三 李陶 ,twelveDTD.dtd,3.5.3 属性类型_ 4NMTOKENS类型,4NMTOKENS类型 对于NM
21、TOKEN类型的属性,其属性值中不能含有空格。如果需要某个属性的属性值含有空格,而且被空格分隔开的子字符串符合NMTOKEN类型属性的属性值之规定,那么就可以将属性的类型取为NMTOKENS类型. 例题3-14 page 50,例子13,example3_13.xml,XM基础教程 清华大学出版社 Java程序设计 清华大学出版社 ,thirteenDTD.dtd,3.5.3 属性类型_ 5ID类型,5ID类型如果希望某个属性的属性值具有专用性,即不允许其它类型相同的属性再取这个属性值,那么就可以将属性的类型取为ID类型。注意ID类型的属性值可以由字母、数字、下划线(“_”)、点(“.”)或连
22、字符(“-”)组成,但必须以字母或下划线开头。需要特别注意的是ID类型属性的“默认值情况”只能是“#REQUIRED”和“IMPLIED” 例题3-14 page51,“默认值情况”是错误的,默认值情况”是正确的 ,例子14,example3_14.xml,101 无轨电车201 有轨电车801 快车631 普通,fourteenDTD.dtd,图3.11 使用解析器检查出的错误,3.5.3 属性类型_ 6 IDREF类型,6IDREF类型 如果准备通过标记的属性值来判断标记之间的联系,就可以在标记中使用IDREF(Identifier Reference)类型的属性。 IDREF类型属性的属
23、性值只能取某个标记中ID类型属性的属性值。 例题3-15 page52,例子15,example3_15.xml,张三 李四 赵五 孙六 ,fifteenDTD.dtd,3.5.3 属性类型_ 7 IDREFS类型,7IDREFS类型 我们希望约束某个属性的属性值是若干个其它ID属性的属性值的组合,IDREFDS类型属性的属性值能满足这一愿望。对于IDREFS类型的属性,它的值可以是用空格分隔的若干个其它ID属性的属性值。例题3-16 page53,例子16,example3_16.xml,张三 李四 ,sixteenDTD.dtd,3.6 内部 DTD,可以把DTD文件的内容直接写在XML文件的内部,相对外部DTD文件,这样的内容称做XML文件的内部DTD 在XML文件中,内部DTD用“”结束. 注:同时使用外部DTD和内部DTD的格式: 或一个XML文件如果遵守内部DTD规定的约束条件,也称作有效的XML文件。,例子17,example3_17.xml,张三 2010 李四 2012 ,例子18,example3_18.xml,木门 铝合金 铁门 铝合金 ,eighteenDTD.dtd,