#我們寫文件來約束一個XML文件的書寫規範,這稱之為XML約束。
常用的約束技術有:
XML DTD
XML Schema
DTD的基本概念:
document type definition 文件類型定義
DTD檔案一般和XML檔案搭配使用,主要是為了約束XML檔。
XML文件引入DTD文件,這樣XML可以自訂標籤,但又受到DTD文件的約束。例如上一節使用XML描述一個班級的訊息,如果我們給每個學生定義一個標籤,語法上也是沒有錯誤的,但是不符合語義,學生怎麼能夠用面積來描述呢?這時候我們就需要用到DTD檔來約束這個XML。
<?xml version="1.0" encoding="gb2312"?><class> <stu id="001"> <name>杨过</name> <sex>男</sex> <age>20</age> <面积>100</面积> </stu></class>
基本語法:
<!ELEMENT 元素名 类型>
我們也以班級為例,寫如下DTD文件,myClass.dtd :
<!ELEMENT 班级 (学生+)><!ELEMENT 学生 (名字,年龄,介绍)><!ELEMENT 名字 (#PCDATA)><!ELEMENT 年龄 (#PCDATA)><!ELEMENT 介绍 (#PCDATA)>
第一行表示根元素為班級,並且有學生這個子元素,子元素為1或多個。
第二行表示學生的子元素為名字,年齡,介紹
名字下面沒有子元素了,那麼#PCDATA表示名字裡面可以放任意文字。
年齡和介紹也是類似。
編寫myClass.xml檔案並引入DTD檔案如下:
<?xml version="1.0" encoding="utf-8"?><!--引入dtd文件,约束这个xml--><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
引入中寫的:SYSTEM,表示目前的DTD檔案是本地的
如果寫的是PUBLIC,則表示引入的DTD檔案是來自於網路的.
這時候引入的DTD檔案是沒有產生作用的,如果我們在學生元素中加入子元素,打開這個XML文件,瀏覽器依然不會報錯。
<?xml version="1.0" encoding="utf-8"?><!--引入dtd文件,约束这个xml--><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> <面积>100平米</面积> </学生> <学生> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
我們需要程式設計校驗XML文件的正確性。
IE5以上的瀏覽器內建了XML解析工具:Microsoft.XMLDOM,開發人員可以編寫JavaScript程式碼,利用這個解析工具來裝載XML文件,並對XML文件進行DTD驗證。
我們寫myXmlTools.html來對這個XML進行校驗,如下:
<html> <head> <!--自己编写一个简单的解析工具,去解析XML DTD是否配套--> <script language="javascript"> // 创建xml文档解析器对象 var xmldoc = new ActiveXObject("Microsoft.XMLDOM"); // 开启xml校验 xmldoc.validateOnParse = "true"; // 装载xml文档,即指定校验哪个XML文件 xmldoc.load("myClass.xml"); document.writeln("错误信息:"+xmldoc.parseError.reason+"<br>"); document.writeln("错误行号:"+xmldoc.parseError.line); </script> </head> <body> </body></html>
用IE瀏覽器開啟這個html文件,可以看到執行結果:
#可以看到第9行正是我們加上的這一行。
1.內部DTD文件
<!DOCTYPE 根元素 [定义内容]>
2.外部DTD文檔
引入外部的DTD文檔分為兩種:
(1)當引用的DTD文件是本地文件的時候,用SYSTEM標識,並寫上“DTD的文件路徑”,如下:
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
(2)如果引用的DTD文件是一個公共的文件時,採用PUBLIC標識,如下方式:
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL">
例如下例:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<!ELEMENT NAME CONTENT>
其中:
- ELEMENT是關鍵字,是不能修改的
- NAME表示元素名稱
- CONTENT是元素類型,必須要大寫! CONTENT的內容有三種寫法:
(1)EMPTY-表示該元素不能包含子元素和文本,但可以有屬性。
(2)ANY-表示該元素可以包含在該DTD中定義的任何元素內容
(3)#PCDATA-可以包含任何字元數據,但不能包含任何子元素
DTD中這樣規定:
<!ELEMENT 家庭(人+,家电*)>
這個DTD規定了家庭元素中可以有1到多個」人」這個子元素,也可以有0到多個」家電」這個子元素。其中的加號”+”和星號”*”的意思與正規表示式中的意思一致。
XML這樣寫:
<家庭> <人 名字="张晓明" 性别="男" 年龄="25"/> <人 名字="李小钢" 性别="男" 年龄="36" 爱好="作个教育家和伟人"/> <家电 名称="彩电" 数量="3"/></家庭>
關於組合類型,有下述的的修飾符可以使用:
符號 | 用途 | 範例 | 範例說明 |
---|---|---|---|
#() | 用來將元素分組 | (古龍|金庸),(王朔|餘傑) | 分成兩組 |
#| | 在列出的對象中選擇一個 | (男人|女人) | 表示男人或女人必須出現,兩者至少選其一 |
#該物件必須出現一次或多次 | (成員+) | 表示成員必須出現,而卻可以出現多個成員 | |
該物件允許出現0次或多次 | (嗜好*) | #嗜好可以出現兩次到多次 | |
? | |||
(菜鳥?) | 菜鳥可以出現,也可以不出現,如果出現的話,最多只能出現一次 | , |
DTD中属性的定义是这样的:
<!ATTLIST 元素名称 属性名称 类型 属性特点 属性名称 类型 属性特点...... >
其中,属性的类型有下面5种:
(1) CDATA
(2) ID
(3) IDREF/IDREFS
(4) Enumerated
(5) ENTITY/ENTITIES
属性的特点有如下4种:
(1) #REQUIRED,表示这个属性必须给,不给就报错
(2) #IMPLIED,表示这个属性可以给也可以不给
(3) #FIXED value,表示这个属性必须给一个固定的value值
(4) Default value,表示这个属性如果没有值,就分配一个默认的value值
比如,我们想在学生这个子元素上加上地址这个属性,而且这个属性是必须的,示例如下:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生 地址="香港"> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生 地址="澳门"> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
这个时候相应的DTD文件也要更新,不然就会报错,如下:
<!ELEMENT 班级 (学生+)><!ELEMENT 学生 (名字,年龄,介绍)><!ATTLIST 学生 地址 CDATA #REQUIRED><!ELEMENT 名字 (#PCDATA)><!ELEMENT 年龄 (#PCDATA)><!ELEMENT 介绍 (#PCDATA)>
(1)属性类型-CDATA,表示属性值可以是任何字符(包括中文和数字)
<!ATTLIST 木偶 姓名 CDATA #REQUIRED>
<木偶 姓名="匹诺曹"/><木偶 姓名="PiNuocao"/><木偶 姓名="123"/>
(2)属性类型-ID,表明该属性的取值必须是唯一的,但是属性的值不能是以数字开头!
<!ELEMENT 公司职员 ANY><!ATTLIST 公司职员 编号 ID #REQUIRED 姓名 CDATA #REQUIRED>
<公司职员 编号="Z001" 姓名="张三"/><公司职员 编号="Z002" 姓名="李思"/>
(3)属性类型-IDREF/IDREFS
- IDREF属性的值指向文档中其它地方声明的ID类型的值
- IDREFS同IDREF,但是可以具有由空格分开的多个引用。
<!ELEMENT 家庭(人+)><!ELEMENT 人 EMPTY><!ATTLIST 人 relID ID #REQUIRED paraentID IDREFS #IMPLIED name CDATA #REQUIRED>
<家庭> <人 relID="P_1" name="爸爸"/> <人 relID="P_2" name="妈妈"/> <人 relID="P_3" parentID="P_1 P_2" name="儿子"/></家庭>
(4)属性类型-Enumerated,事先定义好一些值,属性的值必须在所列出的值的范围内。
<!ATTLIST person 婚姻状态 (single|married|porced|widowed) #IMPLIED><!ATTLIST person 性别 (男|女) #REQUIRED>
(5)属性类型-ENTITY,实体
实体定义:
- 实体用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了。
- 在DTD定义中,一条!ENTITY语句用于定义一个实体。
- 实体可分为两种类型:引用实体和参数实体。引用实体是被XML文档应用的,而参数实体是被DTD文件本身应用的。
①引用实体:
引用实体主要在XML文档中被应用
语法格式如下,引用实体的定义内容最好放在DTD文件的最后。
<!ENTITY 实体名称 "实体内容">
引用方式:&实体名称; 末尾要带上分号,这个引用将直接转变成实体内容
举例如下:
<!ENTITY copyright "I am a programmer">.... ©right;
②参数实体:
参数实体被DTD文件自身使用
语法格式为:
<!ENTITY % 实体名称 "实体内容">
引用方式为:%实体名称
举例:
<!ENTITY % TAG_NAME "姓名|EMAIL|电话|地址"><!ELEMENT 个人信息 (%TAG_NAME;|生日)><!ELEMENT 客户信息 (%TAG_NAME;|公司名)>
学习DTD的目标在于:
(1)要求我们能够看得懂DTD文件,
(2)我们可以根据给出的DTD写出对应的XML文件
下面我们看一个案例,下述的DTD文件是从W3School在线教程中的DTD案例中拿过来的,细看每一行,我们都应该能够看得懂。
<!ENTITY AUTHOR "John Doe"><!ENTITY COMPANY "JD Power Tools, Inc."><!ENTITY EMAIL "jd@jd-tools.com"><!ELEMENT CATALOG (PRODUCT+)> <!ELEMENT PRODUCT(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)><!ATTLIST PRODUCTNAME CDATA #IMPLIEDCATEGORY (HandTool|Table|Shop-Professional) "HandTool"PARTNUM CDATA #IMPLIEDPLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"INVENTORY (InStock|Backordered|Discontinued) "InStock"> <!ELEMENT SPECIFICATIONS (#PCDATA)><!ATTLIST SPECIFICATIONSWEIGHT CDATA #IMPLIEDPOWER CDATA #IMPLIED><!ELEMENT OPTIONS (#PCDATA)> <!ATTLIST OPTIONSFINISH (Metal|Polished|Matte) "Matte" ADAPTER (Included|Optional|NotApplicable) "Included"CASE (HardShell|Soft|NotApplicable) "HardShell"><!ELEMENT PRICE (#PCDATA)> <!ATTLIST PRICEMSRP CDATA #IMPLIEDWHOLESALE CDATA #IMPLIEDSTREET CDATA #IMPLIEDSHIPPING CDATA #IMPLIED><!ELEMENT NOTES (#PCDATA)>
然后我们可以根据该DTD编写如下最简单的XML文件:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE CATALOG SYSTEM "product.dtd"><CATALOG> <PRODUCT NAME="康帅傅矿泉水" CATEGORY="Table" PARTNUM="12" PLANT="Chicago"> <SPECIFICATIONS WEIGHT="20" POWER="18">这里是细节</SPECIFICATIONS> <PRICE>25</PRICE> <PRICE>28</PRICE> </PRODUCT></CATALOG>
然后我们用Microsoft.XMLDOM校验该XML,会发现没有任何错误。但是要注意编码。
我们编写文档来约束一个XML文档的书写规范,这称之为XML约束。
常用的约束技术有:
XML DTD
XML Schema
DTD的基本概念:
document type definition 文档类型定义
DTD文件一般和XML文件配合使用,主要是为了约束XML文件。
XML文件引入DTD文件,这样XML可以自定义标签,但又受到DTD文件的约束。比如上一节使用XML描述一个班级的信息,如果我们给每一个学生定义一个标签,语法上也是没有错误的,但是不符合语义,学生怎么能够用面积来描述呢?这时候我们就需要用到DTD文件来约束这个XML。
<?xml version="1.0" encoding="gb2312"?><class> <stu id="001"> <name>杨过</name> <sex>男</sex> <age>20</age> <面积>100</面积> </stu></class>
基本语法:
<!ELEMENT 元素名 类型>
我们还以班级为例,编写如下DTD文件,myClass.dtd:
<!ELEMENT 班级 (学生+)><!ELEMENT 学生 (名字,年龄,介绍)><!ELEMENT 名字 (#PCDATA)><!ELEMENT 年龄 (#PCDATA)><!ELEMENT 介绍 (#PCDATA)>
第一行表示根元素为班级,并且有学生这个子元素,子元素为1或者多个。
第二行表示学生的子元素为名字,年龄,介绍
名字下面没有子元素了,那么#PCDATA表示名字里面可以放任意文本。
年龄和介绍也是类似。
编写myClass.xml文件并引入DTD文件如下:
<?xml version="1.0" encoding="utf-8"?><!--引入dtd文件,约束这个xml--><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
引入中写的:SYSTEM,表示当前的DTD文件是本地的
如果写的是PUBLIC,则表示引入的DTD文件是来自于网络的.
这时候引入的DTD文件是没有产生作用的,如果我们在学生元素中添加子元素,打开这个XML文件,浏览器依然不会报错。
<?xml version="1.0" encoding="utf-8"?><!--引入dtd文件,约束这个xml--><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> <面积>100平米</面积> </学生> <学生> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
我们需要编程校验XML文档的正确性。
IE5以上的浏览器内置了XML解析工具:Microsoft.XMLDOM,开发人员可以编写JavaScript代码,利用这个解析工具装载XML文件,并对XML文件进行DTD验证。
我们编写myXmlTools.html来对这个XML进行校验,如下:
<html> <head> <!--自己编写一个简单的解析工具,去解析XML DTD是否配套--> <script language="javascript"> // 创建xml文档解析器对象 var xmldoc = new ActiveXObject("Microsoft.XMLDOM"); // 开启xml校验 xmldoc.validateOnParse = "true"; // 装载xml文档,即指定校验哪个XML文件 xmldoc.load("myClass.xml"); document.writeln("错误信息:"+xmldoc.parseError.reason+"<br>"); document.writeln("错误行号:"+xmldoc.parseError.line); </script> </head> <body> </body></html>
用IE浏览器打开这个html文件,可以看到运行结果:
可以看到第9行正是我们添加的这一行。
1.内部DTD文档
<!DOCTYPE 根元素 [定义内容]>
2.外部DTD文档
引入外部的DTD文档分为两种:
(1)当引用的DTD文件是本地文件的时候,用SYSTEM标识,并写上”DTD的文件路径”,如下:
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
(2)如果引用的DTD文件是一个公共的文件时,采用PUBLIC标识,如下方式:
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL">
比如下例:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<!ELEMENT NAME CONTENT>
其中:
- ELEMENT是关键字,是不能修改的
- NAME表示元素名称
- CONTENT是元素类型,必须要大写!CONTENT的内容有三种写法:
(1)EMPTY——表示该元素不能包含子元素和文本,但可以有属性。
(2)ANY——表示该元素可以包含任何在该DTD中定义的元素内容
(3)#PCDATA——可以包含任何字符数据,但是不能在其中包含任何子元素
DTD中这样规定:
<!ELEMENT 家庭(人+,家电*)>
这个DTD规定了家庭元素中可以有1到多个”人”这个子元素,也可以有0到多个”家电”这个子元素。其中的加号”+”和星号”*”的含义与正则表达式中的含义一致。
XML这样写:
<家庭> <人 名字="张晓明" 性别="男" 年龄="25"/> <人 名字="李小钢" 性别="男" 年龄="36" 爱好="作个教育家和伟人"/> <家电 名称="彩电" 数量="3"/></家庭>
关于组合类型,有下述的的修饰符可以使用:
符号 | 用途 | 示例 | 示例说明 |
---|---|---|---|
() | 用来给元素分组 | (古龙|金庸),(王朔|余杰) | 分成两组 |
| | 在列出的对象中选择一个 | (男人|女人) | 表示男人或者女人必须出现,两者至少选其一 |
+ | 该对象必须出现一次或者多次 | (成员+) | 表示成员必须出现,而却可以出现多个成员 |
* | 该对象允许出现0次或者多次 | (爱好*) | 爱好可以出现两次到多次 |
? | 该对象必须出现0次或者1次 | (菜鸟?) | 菜鸟可以出现,也可以不出现,如果出现的话,最多只能出现一次 |
, | 对象必须按指定的顺序出现 | (西瓜,苹果,香蕉) | 表示西瓜、苹果、香蕉必须出现,并且按这个顺序出现 |
DTD中属性的定义是这样的:
<!ATTLIST 元素名称 属性名称 类型 属性特点 属性名称 类型 属性特点...... >
其中,属性的类型有下面5种:
(1) CDATA
(2) ID
(3) IDREF/IDREFS
(4) Enumerated
(5) ENTITY/ENTITIES
属性的特点有如下4种:
(1) #REQUIRED,表示这个属性必须给,不给就报错
(2) #IMPLIED,表示这个属性可以给也可以不给
(3) #FIXED value,表示这个属性必须给一个固定的value值
(4) Default value,表示这个属性如果没有值,就分配一个默认的value值
比如,我们想在学生这个子元素上加上地址这个属性,而且这个属性是必须的,示例如下:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE 班级 SYSTEM "myClass.dtd"><班级> <学生 地址="香港"> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生 地址="澳门"> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生> </班级>
这个时候相应的DTD文件也要更新,不然就会报错,如下:
<!ELEMENT 班级 (学生+)><!ELEMENT 学生 (名字,年龄,介绍)><!ATTLIST 学生 地址 CDATA #REQUIRED><!ELEMENT 名字 (#PCDATA)><!ELEMENT 年龄 (#PCDATA)><!ELEMENT 介绍 (#PCDATA)>
(1)属性类型-CDATA,表示属性值可以是任何字符(包括中文和数字)
<!ATTLIST 木偶 姓名 CDATA #REQUIRED>
<木偶 姓名="匹诺曹"/><木偶 姓名="PiNuocao"/><木偶 姓名="123"/>
(2)属性类型-ID,表明该属性的取值必须是唯一的,但是属性的值不能是以数字开头!
<!ELEMENT 公司职员 ANY><!ATTLIST 公司职员 编号 ID #REQUIRED 姓名 CDATA #REQUIRED>
<公司职员 编号="Z001" 姓名="张三"/><公司职员 编号="Z002" 姓名="李思"/>
(3)属性类型-IDREF/IDREFS
- IDREF属性的值指向文档中其它地方声明的ID类型的值
- IDREFS同IDREF,但是可以具有由空格分开的多个引用。
<!ELEMENT 家庭(人+)><!ELEMENT 人 EMPTY><!ATTLIST 人 relID ID #REQUIRED paraentID IDREFS #IMPLIED name CDATA #REQUIRED>
<家庭> <人 relID="P_1" name="爸爸"/> <人 relID="P_2" name="妈妈"/> <人 relID="P_3" parentID="P_1 P_2" name="儿子"/></家庭>
(4)属性类型-Enumerated,事先定义好一些值,属性的值必须在所列出的值的范围内。
<!ATTLIST person 婚姻状态 (single|married|porced|widowed) #IMPLIED><!ATTLIST person 性别 (男|女) #REQUIRED>
(5)属性类型-ENTITY,实体
实体定义:
- 实体用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了。
- 在DTD定义中,一条!ENTITY语句用于定义一个实体。
- 实体可分为两种类型:引用实体和参数实体。引用实体是被XML文档应用的,而参数实体是被DTD文件本身应用的。
①引用实体:
引用实体主要在XML文档中被应用
语法格式如下,引用实体的定义内容最好放在DTD文件的最后。
<!ENTITY 实体名称 "实体内容">
引用方式:&实体名称; 末尾要带上分号,这个引用将直接转变成实体内容
举例如下:
<!ENTITY copyright "I am a programmer">.... ©right;
②参数实体:
参数实体被DTD文件自身使用
语法格式为:
<!ENTITY % 实体名称 "实体内容">
引用方式为:%实体名称
举例:
<!ENTITY % TAG_NAME "姓名|EMAIL|电话|地址"><!ELEMENT 个人信息 (%TAG_NAME;|生日)><!ELEMENT 客户信息 (%TAG_NAME;|公司名)>
学习DTD的目标在于:
(1)要求我们能够看得懂DTD文件,
(2)我们可以根据给出的DTD写出对应的XML文件
下面我们看一个案例,下述的DTD文件是从W3School在线教程中的DTD案例中拿过来的,细看每一行,我们都应该能够看得懂。
<!ENTITY AUTHOR "John Doe"><!ENTITY COMPANY "JD Power Tools, Inc."><!ENTITY EMAIL "jd@jd-tools.com"> <!ELEMENT CATALOG (PRODUCT+)> <!ELEMENT PRODUCT(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)> <!ATTLIST PRODUCTNAME CDATA #IMPLIEDCATEGORY (HandTool|Table|Shop-Professional) "HandTool"PARTNUM CDATA #IMPLIEDPLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"INVENTORY (InStock|Backordered|Discontinued) "InStock"> <!ELEMENT SPECIFICATIONS (#PCDATA)> <!ATTLIST SPECIFICATIONSWEIGHT CDATA #IMPLIEDPOWER CDATA #IMPLIED> <!ELEMENT OPTIONS (#PCDATA)> <!ATTLIST OPTIONSFINISH (Metal|Polished|Matte) "Matte" ADAPTER (Included|Optional|NotApplicable) "Included"CASE (HardShell|Soft|NotApplicable) "HardShell"> <!ELEMENT PRICE (#PCDATA)> <!ATTLIST PRICEMSRP CDATA #IMPLIEDWHOLESALE CDATA #IMPLIEDSTREET CDATA #IMPLIEDSHIPPING CDATA #IMPLIED> <!ELEMENT NOTES (#PCDATA)>
然后我们可以根据该DTD编写如下最简单的XML文件:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE CATALOG SYSTEM "product.dtd"><CATALOG> <PRODUCT NAME="康帅傅矿泉水" CATEGORY="Table" PARTNUM="12" PLANT="Chicago"> <SPECIFICATIONS WEIGHT="20" POWER="18">这里是细节</SPECIFICATIONS> <PRICE>25</PRICE> <PRICE>28</PRICE> </PRODUCT></CATALOG>
然后我们用Microsoft.XMLDOM校验该XML,会发现没有任何错误。但是要注意编码。
以上就是XML—XML文件约束之DTD详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!