`
utopialxw
  • 浏览: 367213 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

DTD和XSD

阅读更多
前面提到过的, DTD ( Document Type Definition ,文档类型定义)就是定义 XML 文档中元素的结构和内容等。其实 DTD 就相当于 XML 中的“词汇”和“语法”,不同的行业可以定义自己的“词汇”和“语法”,以利于解析器验证 XML 文档的有效性,并且这样也利于行业中和行业之间的交流。就相当于只有当两个人对各自说出的词汇都理解对方的时候才能有顺利的交流。这其实就是对 XML 文档使用元素的定义的以层抽象,把它的定义独立出一个文件,以利于对信息的隐藏和扩展。这也可以把它想象成程序语言,比如 C# 中的接口的定义。把 DTD 文件想象成一个接口,而引用这个 DTD 文件的 XML 文档是这个接口的实现类,只要了解了这个 DTD 文件,就大致知道了和这个 DTD 文件相链接的 XML 文档的一些框架信息。

DTD 文件也可以看成是一系列 XML 文档的模板,它定义了相关 XML 文档的元素,属性,排列方式(元素,属性等),元素的内容类型,以及元素的层次结构等。

 

DTD 中元素的声明
<!ELEMENT 元素名(元素描述) >

这里主要介绍元素描述,元素的描述包含两部分:

1.       如果元素是简单元素,即该元素不包含子元素,则描述部分是针对该元素的内容的限制或是规定。这种限制的描述可以是:

#PCDATA :元素的内容只能是可解析的文本数据。

<!ELEMENT 元素名 (#PCDATA)>

EMPTY :元素内容必须为空,但可以包含属性。

< ! ELEMENT 元素名 EMPTY>

2.       如果元素是复杂元素,即该元素包含子元素,则元素描述包含对子元素名的列表(可用正则表达式表达)。元素描述的括号表示内容描述的组合。

<!ELEMENT book(title, author+, summary | content)>

正则表达式用法:
( )     给元素分组                                 (A | B | C), (D | E), F

|              在列出的对象中选择一个            (A | B)

*      对象允许出现 0 到多次               (A*)

+      对象应出现 1 到多次                   (A+)

?      对象可以出现 0 到 1 次         (A?)

,              对象以指定顺序出现                   (A, B, C)

 

同时,如果不能确定一个元素是否含有子元素或是只能包含文本,那么可以将元素定义为混合类型的。简单的混合类型可以是:

<!ELEMENT 元素名 ANY>

表明元素可以定义为以上的任意一种类型。

典型的,可以将元素的定义通过“ , ”和“ | ”组合起来。如:

<!ELEMENT 元素名 (#PCDATA | EMPTY | (A*, B?, C+ | D))>

 

DTD 中属性的声明
<!ATTLIST 元素名 属性名称 属性类型 属性特点 … >

在 DTD 中,元素中的属性是单独定义的,这里主要介绍属性的类型和属性特点。

属性类型:
1. CDATA       表示属性的值只能是可解析的文本数据。

<!ATTLIST 元素名 属性名 CDATA #REQUIRED>

2. 枚举值       表示属性取值是在()中定义的值

<!ATTLIST 元素名 性别 ( 男 | 女 ) #REQUIRED>

3. ID              表示该属性的取值必须是唯一的,可以用来作为该元素的唯一标识符。并且该值(标识符)必须以字母开头。

<!ATTLIST A ID ID # REQUIRED>

则下列定义是合法的:

<A ID=”a001”>content A</A>

下列定义是不合法的:

<A ID=”001”>content A</A>

4. IDREF/IDREFS 表示属性值指向文档中其他声明的 ID 类型值。

<!ATTLIST people perID ID #REQUIRED

                          parentID IDREFS #IMPLIED>

则有如下的 XML 文件定义:

<people perID=”p1” />

<people perID=”p2” />

<perple perID=”p3” parentID=”p1 p2” />

对 IDREFS 中的不同的 ID 的定义,在 XML 文件中要空格空开。

5. ENTITY/ENTITIES 表示该属性的值为一个或多个已定义的实体定义,多个实体之间用空格空开。

<!ATTLIST 元素名 属性名 ENTITY #IMPLIED>

6. NMTOKEN/NMTOKENS 表示属性的值只能由字母、数字、下滑下、句点、冒号、连接符( - )这些符号或多个这些符号构成,多个符号之间用空格空开。

<!ATT:LIST 元素名 属性名 NMTOKENS #REQUIRED>

7. NOTATION 表示该属性的取值为 <!NOTATION…> 中定义的符号。

属性特点:
#REQUIRED 表明该属性在 XML 文件中必须定义。

#IMPLIED            表明该属性在 XML 文件中可有可无。

#FIXED “ value ” 表明该属性的值是固定的。其值就是 value 中定义的值。

“ Default Value ”    为该属性定义一个默认值。

 

DTD 中内部实体的声明
实体的声明格式:

<!ENTITY entity-name “entity-content”>

对实体的引用通过实体名来实现。

实体相当于“宏”,比如 C 语言中的 #define ,它用于将一段文本或是数字用一个名字来命名,并在以后引用到该名字的时候默认用那段定义的文本或是数字来替换。对有些太长的文本,可以减少工作量,而对于给一些数字定义名字,可以改善程序的可读性,不至于看到的就是一些赤裸裸的,没有一点意义的数字。这样也相应的提高了维护性,因为一个值的改变只需要改变一处就可以了,而不用在用到这个字符的地方都去改动。

在 XML 中预定义了一些实体,如在“ XML 概述”中提到过的特殊字符,以及可以通过 # 加 Unicode 码或是十六进制数据来定义一个字符。

实体的使用:

& 实体名;     (注意是 &+ 实体名 + ;)

注: 实体能用于另外一个实体的定义中,但不能位于元素声明中。

内部实体无需先定义后引用,因而需要避免引用循环。

 

DTD 中外部实体的声明
<!ENTITY entity-name SYSTEM/PUBLIC “external entity URI”>

 

DTD 中参数实体
内部参数实体声明:
<!ENTITY %entity-name “entity-content”>

外部参数实体:
<!ENTITY %entity-name “URI”>

参数实体的引用:

% 实体名 ;

参数实体类似于实体,它也是用一个名字去替换这个名字已定义的内容;不同于一般的实体,它只能在外部 DTD 文档中定义和使用,并且它也只能在 DTD 文档中使用。(言外之意就是一般实体是可以在 XML 文件中使用的)并且它需要先定义后使用,同时它也可以应用于元素的定义。

如在 DTD 文档中的定义以及使用:

<!ENTITY % common.attributes
   
'id       
ID   
#IMPLIED
    
account  
CDATA #REQUIRED'
>
<!ATTLIST manufacturer %common.attributes;>
 

DTD 中 Notation 的定义
Notation 定义了一些不是 XML 类型的数据的文档。我还不是很了解它的具体用处,关于它的介绍很少,即使是在 W3C 中的文档。

其定义有两种格式:

<!NOTATION name “external_ID”>

<!NOTATION name “public_ID” “URL”>

如:

<!NOTATION GIF system "image/gif">

<!NOTATION GIF public
  "-//IETF/NOSGML Media Type image/gif//EN"
  "http://www.isi.edu/in-notes/iana/assignments/media-types/image/gif">

注:参考 http://webdesign.about.com/od/dtds/a/aa101700b.htm

 

DTD 文档在 XML 文件中的引用
在 XML 文件中, DTD 文件分为两种:内部 DTD 和外部 DTD 。这两种只是 DTD 文档定义的位置不一样, DTD 文档里的内容是一致的。内部 DTD 将 DTD 文档的定义放到 XML 文件中;而外部 DTD 将 DTD 文档独立出一个文件,通过在 XML 文件中声明 DTD 文档的位置来获取相应的 DTD 文件。

 

内部 DTD 在 XML 文件中的声明
<!DOCTYPE 根元素名 [

       DTD 文档内容

]>

 

外部 DTD 在 XML 文件中的声明
<!DOCTYPE 根元素名 SYSTEM/PUBLIC “ 外部 DTD 文件名及其外置 ”>

 

DTD 的缺陷与 XSD 的出现
DTD 在一定的阶段推动了 XML 的发展,但是它本身存在着一些缺陷:

1.       它没有使用 XML 格式,而是自己定义了一套格式,相对解析器的重用性较差;而且 DTD 的构建和访问没有标准的编程接口,因而解析器很难简单的解析 DTD 文档。

2.       DTD 对元素的类型限制较少;同时其他的约束力也叫弱。

3.       DTD 扩展能力较差。

4.       基于正则表达式的 DTD 文档的描述能力有限。

针对这些原因, W3C 在 2001 年推出了 XML Schema 标准( XSD )。 XSD 具有前面介绍的 DTD 的所有优势和功能。它也用于定义 XML 文档的结构和内容,同时它还可以定义元素的数据类型。更重要的是:

1.       它本身就是 XML 文档结构,因而解析器可以很好的解析 XSD 文档。

2.       它没有自己的一套语法,学习起来相对简单。

3.       它支持一系列的数据类型以及自定义的数据类型,因而具有更强的约束能力。

4.       它具有很好的扩展能力,并且支持命名空间以及属性组等。

个人认为 XSD 优于 DTD 的最主要的一点就是 XSD 使用的是 XML 语法,因而可以很方便的解析 XSD 文档,而要解析 DTD 文档则需要复杂的编程模型,而且效率比较差。

 

XSD 文档结构
<?xml version=”1.0”?>

<xsd:schema xmlns:xsd=”http://www.w3.org/2001/XMLSchema ”>

….

XSD 文档定义内容 …

….

</xsd:schema>

如以下 XSD 文档的定义:

<?xml version=”1.0”?>

<xsd:schema xmlns:xsd=”http://www.w3.org/2001/XMLSchema ”>

       <xsd:element name=”products” type=”productsType”>

              <xsd:complexType name=”productsType”>

                     <xsd:sequence>

                     <xsd:element name=”product” type=”productType” />

                     </xsd:sequence>

              </xsd:complexType>

              <xsd:complexType name=”productType”>

                     <xsd:sequenct>

                            <xsd:element name=”productName” type=”xsd:string” />

                            <xsd:element name=”description” type=”xsd:string” />

                            <xsd:element name=”price” type=”xsd:double” />

<xsd:element name=”quantity” type=”xsd:nonNegativeIntergater” />

                     </xsd:sequence>

              </xsd:complexType>

       </xsd:element>

</xsd:schema>

 

XML 中对 XSD 文档的引用
<?xml version=”1.0”?>

<products xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance ”

       xsi:noNamespaceSchemaLocation=”products.xsd”>

       ….

       ….

</products>

 

XSD 数据类型


原始( Primitive )数据类型:
string            字符串

boolean          布尔值

decimal          十进制,用于准确的定义一个值

float               单精度浮点类型

double           双精度浮点类型

timeDuration   持续时间

dateTime       特定时刻时间

time               每天重复的特定时刻时间

date               日期

anyURI          用于定位文件的 URI

recurringDuration          重复持续出现的时间间隔

 

派生( Derived )数据类型(由 Primitive 数据类型或是 Derived 数据类型导出的数据类型)
integer                         十进制的一个整数序列(由 decimal 导出)

long                             -2^63 到 2^63-1 的数

nonNegativeInteger        大于或等于 0 的整数(由 integer 导出)

positiveInteger                     大于 0 的整数(由 nonNegativeInteger 导出)

int                                -2^31 到 2^31-1 的数

time                             每天特定时间重复出现的一个实例(由 recurringDuration 导出)

date                             从午夜到第二天午夜的一个时间段(由 timeDuration 导出)

 

用户自定义简单数据类型
有些数据仅仅用上述的几种内置的简单数据类型无法完整的表达,比如对电话号码 0571-88909090 这样的表达,如果只是用 string 来限制显然不够完整。而这可以通过 simpleType 元素来组合内置数据类型来实现用户自定义的数据类型,以增强数据类型的定义规则。在定义用户自己的数据类型时,还可以使用一些属性来是表达更加方便完整。

simpleType 元素的属性:
enumeration                 在指定的数据值中选择,限制用户的选值

fractionDigits                限定最大的小数位数,用于控制精度

length                           限定数据长度

minLength                    指定最小长度

maxExclusive                指定数据的最大值(小于)

maxInclusive                指定数据的最大值(小于等于)

minExclusive                指定数据的最小值(大于)

minInclusive                 指定数据的最小值(小于等于)

pattern                         指定数据的显示规范

 

用户自定义数据类型的语法规则
<xsd:simpleType name=” 自定义数据类型的名称 ”>

       <xsd:restriction base=” 自定义数据类型所基于的数据类型名称 ”>

              内容模式的定义 ….

       </xsd:restriction>

</xsd:simpleType>

如上述电话号码的定义:

<xsd:simpleType name=”phoneType”>

       <xsd:restriction base=”xsd:string”>

              <xsd:length value=”13” />

              <xsd:pattern value=”\d{4}-\d{8}” />

       </xsd:restriction>

</xsd:simple>

如果是 enumeration 类型的,则可定义如下:

<xsd:simpleType name=”enumType”>

<xsd:restriction base=”xsd:string”>

       <xsd:enumeration value=”string1” />

       <xsd:enumeration value=”string2” />

       ….

</xsd:restriction>
</xsd:simpleType>

 

pattern 属性值必须是一个正则表达式,用来定义一种匹配模式。正则表达式可以做为一个模板,将某个字符模式与搜索的字符串进行匹配。正则表达式常用的符号及其意义如下:

\             标记为一个特殊字符。

^             匹配字符串的开始位置

$            匹配字符串的结束位置

*            匹配 0 次或多次

+            匹配 1 次或多次

?            匹配 0 次或一次

{n}         n 是一个非负整数,表示匹配 n 次

{n,}        n 是一个非负整数,表示至少匹配 n 次

{n,m}     表示至少匹配 n 次,至多匹配 m 次

.             匹配出 \n 之外的任何单个字符

(pattern)  匹配 pattern ,并获取这一匹配

(?:pattern) 匹配 pattern ,但不获取匹配结果

(?=pattern) 正向预查

(?!pattern) 负向预查

x|y        匹配 x 或 y

[xyz]       匹配 x 或 y 或 z

[^xyz]     不匹配任何 x 或 y 或 z

[a-z]              字符范围

[^a-z]      非字符范围

\b           匹配一个单词边界,也就是每个单词之间的空格位置。

\B           匹配非单词边界。

\cx          匹配由 x 指明的控制字符,如 \cM 匹配一个 control-M 或回车符。 x 为 A~Z , a~z

\d           匹配一个数字,即 [0-9]

\D           匹配一个非字符,即 [^0-9]

\f            匹配一个换页符,即 \x0c

\n           匹配一个换行符,即 \x0a

\r            匹配一个回车符,即 \x0d

\s            匹配任何一个空白符,即 [\f\n\r\t\v]

\S           匹配任何非空白字符,即 [^\f\n\r\t\v]

\t            匹配一个制表符,即 \x09

\v           匹配一个垂直制表符,即 \x0b

\w          匹配任何包含下划线的单词字符

\W          匹配任何不包含下划线的单词字符

\xn          n 为十六进制转义值

\num       num 为正整数,对所获取的匹配的引用,如‘ (.)\1’ 表示任何两个连续相同字符

\n           标识一个八进制转义值等(也可以是一个向后引用)。

\un          n 为四个十六进制表示的 Unicode 字符。

 

复杂数据类型的声明
复杂数据类型包含其他的元素、属性和混合内容等。其声明如下:

<xsd:complexType name=” 复杂数据类型名 ”>

       内容模式定义 ….

</xsd:complexType>

如果元素内容既包含文本(简单数据类型?)也包含子元素,则因在定义 complexType 时把 mixed 属性设置为 true 。如:

<xsd:complexType name=”mixedType” mixed=”true”>

       <xsd:sequence>

              <xsd:element name=”firstName” type=”xsd:string” />

       </xsd:sequence>

</xsd:complexType>

则可以在 XML 文件中定义一下元素:

<contract>

My first name is

<firstName>John</firstName>

</contract>

 

XSD 中元素声明
<xsd:element name=” 元素名称 ” type=” 数据类型 ” default=” 默认值 ” minOccurs=” 该元素最小出现的次数,默认为 0” maxOccurs=” 该元素的最多出现次数,默认为 unbounded” />

其中 minOccurs 的值必须为 nonNegativeInteger

maxOccurs 的值必须为 nonNegativeInteger | unbounded 。

在 Schema 中,一个元素主要由元素名和元素类型决定,元素类型定义一个元素的合法内容。如果元素是简单类型的,则类型因为简单的元素类型;如果元素为复杂元素,则类型因为相应的复杂类型。

 

匿名类型
如果某个类型只被使用到了一次,我们就没有必要为他们定义一个名字,可以直接定义这个类型并使用。如:

<xsd:element name=”city”>

       <xsd:complexType>

              <xsd:element name=”name” type=”xsd:string” />

              <xsd:element name=”state” type=”xsd:string” />

       </xsd:complexType>

</xsd:element>

 

XSD 中属性声明
<xsd:attribute name=” 属性名 ” type=” 属性类型 ” default=” 默认值 ” fixed=” 固定值 ” ref=” 引用属性名 ” use=”optional | required | prohibited” />

属性的类型只能是简单类型。

ref 为对同一个或其他 XML 文档中声明的自定义属性的引用。

属性定义的位置在 complexType 的末尾。

如:

<xsd:complexType name=”stdType”>

       <xsd:sequence>

              <xsd:element name=”name” type=”xsd:string” />

              <xsd:element name=”class” type=”xsd:string” />

       </xsd:sequence>

<xsd:attribute name=”age” type=”xsd:positiveInteger” use=”required” />

</xsd:complexType>

 

全局元素和全局属性
可以把元素和属性在单独的域中定义,然后通过 ref 属性来引用他们。

<xsd:element / xsd:attributer ref=” 要引用的全局元素名 / 全局属性名 ” />

对全局元素和全局属性的定义有一些限制:

1.       全局元素 / 属性不能包含引用,即不能有 ref 属性。

2.       全局元素 / 属性也不能包含 minOccurs 、 maxOccurs 、 use 等属性。

3.       全局元素 / 属性必须包含 type 和 name 属性。

如:

<xsd:element name=”Title” type=”xsd:string” />

<xsd:element name=”ID” type=”xsd:string” />

<xsd:element name=”books” type=”booksType” />

<xsd:complexType name=”booksType”>

       <xsd:element name=”book”>

              <xsd:sequence>

                     <xsd:element ref=”Title” />

              </xsd:sequence>

              <xsd:attribute ref=”ID” />

       </xsd:element>

</xsd:complexType>

 

XSD 中的元素组
sequence 元素:定义组合的元素必须按照定义的顺序显示。

<xsd:sequence>

要组合顺序显示的声明 …

</xsd:sequence>

 

group 元素:使用通用名将一组元素组合在一起。

<xsd:group name=” 组名 ” maxOccurs=”nonNegativeInteger | unbounded” minOccurs=”nonNegativeInteger” ref=” 组名 ”>

       要组合的元素声明 …..

</xsd:group>

例如:

<xsd:element name=”Title” type=”xsd:string” />

<xsd:element name=”books” type=”booksType” />

<xsd:complexType name=”booksType”>

       <xsd:element name=”book”>

              <xsd:sequence>

                     <xsd:group ref=”bookInfo” />

              </xsd:sequence>

              <xsd:attribute ref=”ID” />

       </xsd:element>

</xsd:complexType>

<xsd:group name=”bookInfo”>

       <xsd:sequence>

              <xsd:element name=”Title” type=”xsd:string” />

              <xsd:element name=”Author” type=”xsd:string” />

       </xsd:sequence>

</xsd:group>

 

choice 元素:允许指定多组中的一个,用于互斥情况。

<xsd:choice id=”ID” maxOccurs=”nonNegativeInteger | unbounded” minOccurs=”nonNegativeInteger”>

       要组合的元素声明 …..

</xsd:choice>

 

all 元素:允许元素按任意顺序显示。注: all 元素必须放在 sequence 、 group 、 choice 等元素之前声明。

<xsd:all maxOccurs=”nonNegativeInteger | unbounded” minOccurs=”0 | 1”>

       要组合的元素声明 …..

</xsd:all>

 

XSD 中的属性组
同 XSD 元素组中的 group 元素,在 XSD 属性中也有 group 元素的定义,用来声明一组属性,并可以通过 ref 属性来引用这组属性。

<xsd:attributeGroup name=”group-name”>

       属性 1 声明

       属性 2 声明

       …..

</xsd:attributeGroup>

引用语法:

<xsd:attributeGroup ref=”group-name” />

 

外部导入另一个 XSD 文档
可以通过 include 或是 import 元素导入外部的 XSD 定义:

<include id=”ID” schemaLocation=”filename” />

<import id=”ID” namespace=”namespace” schemaLocation=”filename” />

这两个元素都具有 id 属性,它只是作为一个标识符,它是唯一的,也是可选的。

schemaLocation 是要导入的 XSD 文档的名称。 Namespace 是指被引入 XSD 文件所属的命名空间。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics