XML学习笔记二:XML规范:DTD详解


、DTD:文档类型定义

1、简介:

1)DTD 可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。

2)DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。


2、内部申明:DOCTYPE

1)语法:假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:

<!DOCTYPE 根元素 [元素声明]>

2)例如:带有 DTD 的 XML 文档实例(请在 IE5 以及更高的版本打开,并选择查看源代码):

<?xml version="1.0"?>
<!DOCTYPE request [
  <!ELEMENT request (appnt,insured,product,service)>
  <!ELEMENT appnt      (#PCDATA)>
  <!ELEMENT insured    (#PCDATA)>
  <!ELEMENT product    (#PCDATA)>
  <!ELEMENT service    (#PCDATA)>
]>
<request>
  <appnt>George</appnt>
  <insured>John</insured>
  <product>Reminder</product>
  <service>Don't forget the meeting!</service>
</request>

以上 DTD 解释如下:
!DOCTYPE request (第二行)定义此文档是 request 类型的文档。
!ELEMENT request (第三行)定义 request 元素有四个元素:"appnt、insured、product、service"
!ELEMENT appnt 	 (第四行)定义 appnt   元素为 "#PCDATA" 类型
!ELEMENT insured (第五行)定义 insured 元素为 "#PCDATA" 类型
!ELEMENT product (第六行)定义 product 元素为 "#PCDATA" 类型
!ELEMENT service (第七行)定义 service 元素为 "#PCDATA" 类型

3、外部申明:

1)语法1:

<!DOCTYPE 根元素 SYstem "文件名">

2)例如:这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:

<?xml version="1.0"?>
<!DOCTYPE request SYstem "request.dtd">
<request>
  <appnt>George</appnt>
  <insured>John</insured>
  <product>Reminder</product>
  <service>Don't forget the meeting!</service>
</request>


这是包含 DTD 的 "request.dtd" 文件
<!ELEMENT request (appnt,service)>
<!ELEMENT appnt   (#PCDATA)>
<!ELEMENT insured (#PCDATA)>
<!ELEMENT product (#PCDATA)>
<!ELEMENT service (#PCDATA)>

3)语法2:如果引用的外部文件一个公共的文件时,

<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL">

例子:
<?xml version="1.0"?>
<!DOCTYPE request PUBLIC "request.dtd" "http://java.sun.com">
<request>
  <appnt>George</appnt>
  <insured>John</insured>
  <product>Reminder</product>
  <service>Don't forget the meeting!</service>
</request>


4、XML 构建模块

所有的 XML 文档均由以下简单的构建模块构成:
1)元素:就是标签。<reqiest></request><appnt></appnt>
2)属性属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的.

<appnt name="sam-sho">George</appnt>

3)实体:即定义一个变量指向一个内容。分为引用实体和参数实体。


4)PCDATA:

A、被解析的字符数据,为 XML 元素的开始标签与结束标签间的文本。

B、PCDATA 是会被解析器解析的文本。不应当包含任何 &、< 或者 > 字符;需要使用 &amp;、&lt; 以及 &gt; 实体来分别替换它们。

5)CDATA:是不会被解析器解析的文本


5、DTD-元素:元素的定义规范如下:


在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:

<!ELEMENT 元素名称 类别>
或者
<!ELEMENT 元素名称 (元素内容)>


元素名称后面可以 类型或者内容内容需要用()括起来,用“,”、“|”、“*”、“?”、“+”等分开表示,顺序必须保持一致。

简单介绍一些具体的语法实例:

1)空元素:空元素通过类别关键词EMPTY进行声明:

<!ELEMENT 元素名称 EMPTY>
例子:
<!ELEMENT person EMPTY>
XML例子:
<person />

2)只有 PCDATA 的元素:通过圆括号中的 #PCDATA 进行声明:

<!ELEMENT 元素名称 (#PCDATA)>
例子:
<!ELEMENT from (#PCDATA)>
XML例子:
<person>SooZhou</person>

3)带有任何内容的元素:
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:

<!ELEMENT 元素名称 ANY>
例子:
<!ELEMENT note ANY>

4)带有子元素(序列)的元素:
带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:

<!ELEMENT 元素名称 (子元素名称 1)>
或者
<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>
例子:
<!ELEMENT request(to,from,heading,body)>

当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。

"request" 元素的完整声明是:

<!ELEMENT request (to,body)>
<!ELEMENT to      (#PCDATA)>
<!ELEMENT from    (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body    (#PCDATA)>


5)声明只出现一次的元素

<!ELEMENT 元素名称 (子元素名称)>
例子:
<!ELEMENT note (message)>

上面的例子声明了:message 子元素必须出现一次,并且必须只在 "note" 元素中出现一次。


6)声明最少出现一次的元素: “ + ”

<!ELEMENT 元素名称 (子元素名称+)>
例子:
<!ELEMENT note (message+)>

上面的例子中的加号声明了:message 子元素必须在 "note" 元素内出现至少一次。


7)其他:

声明出现零次或多次的元素  “*”
<!ELEMENT 元素名称 (子元素名称*)>
例子:
<!ELEMENT note (message*)>
上面的例子中的星号声明了:子元素 message 可在 "note" 元素内出现零次或多次。


声明出现零次或一次的元素 “?”
<!ELEMENT 元素名称 (子元素名称?)>
例子:
<!ELEMENT note (message?)>
上面的例子中的问号声明了:子元素 message 可在 "note" 元素内出现零次或一次。


声明“非.../既...”类型的内容
例子:
<!ELEMENT note (to,header,(message|body))>
上面的例子声明了:"note" 元素必须包含 "to" 元素、"from" 元素、"header" 元素,以及非 "message" 元素既 "body" 元素。


声明混合型的内容
例子:
<!ELEMENT note (#PCDATA|to|from|header|message)*>
上面的例子声明了:"note" 元素可包含出现零次或多次的 PCDATA、"to"、"from"、"header" 或者 "message"。

6、DTD - 属性 Attlist关键字

在 DTD 中,属性通过 ATTLIST 声明来进行声明。


1)语法:

<!ATTLIST 元素名称 属性名称 属性类型 认值>


例子:
DTD 实例:
<!ATTLIST payment type CDATA "check">
XML 实例:
<payment type="check" />


2)属性的类型和值:



例如:规定一个认的属性值:

DTD:
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">

合法的 XML:
<square width="100" />

分析:"square" 被定义为带有 CDATA 类型的 "width" 属性的空元素。如果宽度没有被设定,其认值为0 。


①、#required——属性值是必需的

A、语法:

<!ATTLIST 元素名称 属性名称 属性类型 #required>

B、实例

DTD:
<!ATTLIST person number CDATA #required>

合法的 XML:
<person number="5677" />

非法的 XML:
<person />

C、分析:没有认值选项,但是仍然希望强制作者提交属性的话,请使用关键词 #required


②、#IMPLIED——属性不是必需的

A、语法:

<!ATTLIST 元素名称 属性名称 属性类型 #IMPLIED>

B、实例

DTD:
<!ATTLIST contact fax CDATA #IMPLIED>

合法的 XML:
<contact fax="555-667788" />

合法的 XML:
<contact />

C、分析:不希望强制作者包含属性,并且您没有认值选项的话,请使用关键词 #IMPLIED。


③、#FIXED value——属性值是固定的

A、语法:

<!ATTLIST 元素名称 属性名称 属性类型 #FIXED "value">

B、实例

DTD:
<!ATTLIST sender company CDATA #FIXED "Microsoft">

合法的 XML:
<sender company="Microsoft" />

非法的 XML:
<sender company="W3School" /> 认只能是Microsoft

C、分析:希望属性拥有固定的值,并不允许作者改变这个值,请使用 #FIXED 关键词。如果作者使用了不同的值,XML 解析器会返回错误


④、列举属性

A、语法:

<!ATTLIST 元素名称 属性名称 (en1|en2|..) 认值>

B、实例:

DTD 例子:
<!ATTLIST payment type (check|cash) "cash">

XML 例子:
<payment type="check" />

或者
<payment type="cash" />

C、分析:希望属性值为一系列固定的合法值之一,请使用列举属性值。

7、DTD - 实体:Entity 关键字

实体是用于定义引用普通文本或特殊字符的快捷方式的变量。分为引用实体和参数实体

第一、引用实体是对实体的引用。实体可在内部或外部进行声明。


1)内部申明

①、语法

<!ENTITY 实体名称 "实体的值">

②、实例:

DTD 例子:
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "copyright W3School.com.cn">

XML 例子:
<author>&writer;&copyright;</author>

③、分析:一个实体由三部分构成: 一个和号 (&),一个实体名称,以及一个分号 (;)。


2)外部申明:使用SYstem 关键字

①、语法:

<!ENTITY 实体名称 SYstem "URI/URL">

②、实例

DTD 例子:
<!ENTITY writer SYstem "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYstem "http://www.w3school.com.cn/dtd/entities.dtd">

XML 例子:
<author>&writer;&copyright;</author>


第二、参数实体。

被DTD文件自身使用。

1)语法:使用 %

<!ENTITY   % 实体名称 "实体的值">


引用的时候:使用 % 实体名称用法与上面一致。


8、自己试着去分析Struts的DTD规范。struts-2.3.dtd文件代码如下

<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
 * $Id: struts-2.0.dtd 651946 2008-04-27 13:41:38Z apetrelli $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License,Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an
 * "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND,either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
-->
<!-- START SNIPPET: strutsDtd -->

<!--
   Struts configuration DTD.
   Use the following DOCTYPE

   <!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
-->

<!-- *****************  以上为注释********************   -->

<!ELEMENT struts ((package|include|bean|constant)*,unkNown-handler-stack?)>     
<!ATTLIST struts
    order CDATA #IMPLIED
>

<!-- 
1、ELEMENT:定义struts元素的子元素: ()内的为元素的名称:
	1)、(package|include|bean|constant)*:使用 “|” ,为四个元素必须有一个,  且使用“*”,表示可以出现0次或多次
	2)、unkNown-handler-stack? :表示这个名字的标签可以出现0次或1次

2、ATTLIST:定义struts元素的属性:
	1)、属性名称为 order,
	2)、类型为 CDATA ,不会被解析的文本(即字符串)
	3)、#IMPLIED,这个属性不是必须的


-->

<!ELEMENT package (result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)>
<!ATTLIST package
    name CDATA #required
    extends CDATA #IMPLIED
    namespace CDATA #IMPLIED
    abstract CDATA #IMPLIED
    strict-method-invocation CDATA #IMPLIED
    externalReferenceResolver NMTOKEN #IMPLIED
>

<!-- 
1、ELEMENT:定义package元素的子元素: ()内的为元素的名称:
	1)、result-types? :result-types 元素可出现0或1次
	2)、action* :action标签可以出现0次或多次

2、ATTLIST:定义package元素的属性:
	1)、定义了6个属性名称分别为 name、extends、namespace、abstract、 strict-method-invocation、externalReferenceResolver
	2)、类型为 CDATA ,不会被解析的文本(即字符串)
	3)、属性externalReferenceResolver,的类型为NMTOKEN,即其他合法的xml名称。可以自定义一个xml
	4)、只有name属性是必须的,其选择即可。


-->

<!ELEMENT result-types (result-type+)>

<!ELEMENT result-type (param*)>
<!ATTLIST result-type
    name CDATA #required
    class CDATA #required
    default (true|false) "false"
>

<!-- 
1、ELEMENT:定义result-types元素的子元素: ()内的为元素的名称:
	1)、result-type+ :result-type 元素至少出现一次,即一定要有一个

2、ELEMENT:定义result-type元素的子元素: ()内的为元素的名称:
	1)、param* :param元素可以有0次或多次

3、ATTLIST:定义result-type元素的属性:
	1)、定义了3个属性名称分别为 name、class、default
	2)、类型为 CDATA ,不会被解析的文本(即字符串)
	3)、属性default,的类型为枚举的其中一个,这边可以选择true或false,认值为false
	4)、name和class属性是必须的

-->


<!ELEMENT interceptors (interceptor|interceptor-stack)+>

<!ELEMENT interceptor (param*)>
<!ATTLIST interceptor
    name CDATA #required
    class CDATA #required
>

<!ELEMENT interceptor-stack (interceptor-ref*)>
<!ATTLIST interceptor-stack
    name CDATA #required
>

<!ELEMENT interceptor-ref (param*)>
<!ATTLIST interceptor-ref
    name CDATA #required
>

<!ELEMENT default-interceptor-ref (#PCDATA)>
<!ATTLIST default-interceptor-ref
    name CDATA #required
>

<!ELEMENT default-action-ref (#PCDATA)>
<!ATTLIST default-action-ref
    name CDATA #required
>

<!ELEMENT default-class-ref (#PCDATA)>
<!ATTLIST default-class-ref
    class CDATA #required
>

<!ELEMENT global-results (result+)>

<!ELEMENT global-exception-mappings (exception-mapping+)>

<!ELEMENT action ((param|result|interceptor-ref|exception-mapping)*,allowed-methods?)>
<!ATTLIST action
    name CDATA #required
    class CDATA #IMPLIED
    method CDATA #IMPLIED
    converter CDATA #IMPLIED
>

<!ELEMENT param (#PCDATA)>
<!ATTLIST param
    name CDATA #required
>

<!ELEMENT result (#PCDATA|param)*>
<!ATTLIST result
    name CDATA #IMPLIED
    type CDATA #IMPLIED
>

<!ELEMENT exception-mapping (#PCDATA|param)*>
<!ATTLIST exception-mapping
    name CDATA #IMPLIED
    exception CDATA #required
    result CDATA #required
>

<!ELEMENT allowed-methods (#PCDATA)>

<!ELEMENT include (#PCDATA)>
<!ATTLIST include
    file CDATA #required
>

<!ELEMENT bean (#PCDATA)>
<!ATTLIST bean
    type CDATA #IMPLIED
    name CDATA #IMPLIED
    class CDATA #required
    scope CDATA #IMPLIED
    static CDATA #IMPLIED
    optional CDATA #IMPLIED
>

<!ELEMENT constant (#PCDATA)>
<!ATTLIST constant
    name CDATA #required
    value CDATA #required
>

<!ELEMENT unkNown-handler-stack (unkNown-handler-ref*)>
<!ELEMENT unkNown-handler-ref (#PCDATA)>
<!ATTLIST unkNown-handler-ref
    name CDATA #required
>

<!-- END SNIPPET: strutsDtd -->


9、根据DTD,自己写XML文件

1)DTD为如下文件

<!DOCTYPE CATALOG [

<!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 PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|discontinued) "InStock">

<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>

<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte" 
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">

<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>

<!ELEMENT NOTES (#PCDATA)>

]>

2)自己写的XML如下:

<?xml version="1.0" encoding="UTF-8"?>

	<!-- DTD  start-->
<!DOCTYPE CATALOG [

<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools,Inc.">
<!ENTITY EMAIL "jd@jd-tools.com">

<!ELEMENT CATALOG (PRODUCT+)>  

<!ELEMENT PRODUCT
(SPECIFICATIONS+,NOTES?)>

<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|discontinued) "InStock">

<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>

<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte" 
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">

<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>

<!ELEMENT NOTES (#PCDATA)>

]>

	<!-- DTD  end-->


	<!--
		分析:
	    1、实体:定义三个实体 
	    	1)AUTHOR、COMPANY、EMAIL 
		
		2、PRODUCT元素:
			1)PRODUCT+ 至少出现一次
			2)内部有元素:SPECIFICATIONS+(一定有一个),NOTES?(0次或1次)
			2)属性:NAME、CATEGORY、PARTNUM、PLANT、INVENTORY 都不是必须的

		3、SPECIFICATIONS元素:一定有一个 
			1)内容:PCDATA,可解析。不能出现 < 等
			2)属性:都是可选属性,WEIGHT,POWER 
		
		4、OPTIONS元素:
			1)内容:PCDATA
			2)属性:可选属性,FINISH、ADAPTER、CASE。
			3)属性类型都是枚举,固定有认值
		
		5、PRICE元素:
			1)内容:PCDATA 
			2)属性:可选属性,MSRP、WHOLESALE、STREET、SHIPPING 
		
		6、NOTES元素
	-->

<CATALOG>

	<PRODUCT NAME="牙膏">
		<SPECIFICATIONS WEIGHT="" POWER="">AAAA</SPECIFICATIONS>		
		<OPTIONS FINISH="Polished" ADAPTER ="Optional" CASE="NotApplicable">BBBB</OPTIONS>
		<PRICE MSRP="" WHOLESALE="" STREET="" SHIPPING="">CCCC</PRICE>
		<NOTES>ddddD</NOTES>
	</PRODUCT>
	
	
	<PRODUCT NAME="牙膏">
		<SPECIFICATIONS WEIGHT="" POWER="">AAAA</SPECIFICATIONS>		
		<OPTIONS FINISH="Polished" ADAPTER ="Optional" CASE="NotApplicable">BBBB</OPTIONS>
		<PRICE MSRP="" WHOLESALE="" STREET="" SHIPPING="">CCCC</PRICE>
		<NOTES>ddddD</NOTES>
	</PRODUCT>
	
</CATALOG>

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念