XML 约束

2023-10-16 14:29:49 浏览数 (2)

一个 XML 文档一旦有了约束,那么这个 XML 文档就只能使用约束中创建的元素及属性。如果约束没有创建 <a> 元素,那么 XML 文档就不能使用 <a> 元素。 XML 有两种约束:DTD 和 Schema,这二者都是用来描述 XML 文档结构,限定文档的数据类型的, 只是做法上不一样。

1、XML 约束
1.1、XML 约束介绍

一个 XML 文档一旦有了约束,那么这个 XML 文档就只能使用约束中创建的元素及属性。

如果约束没有创建 <a> 元素,那么 XML 文档就不能使用 <a> 元素。

1.2、XML 两种约束

XML 有两种约束:DTD 和 Schema,这二者都是用来描述 XML 文档结构,限定文档的数据类型的, 只是做法上不一样。

DTD 和 XML Schema 之间的关键区别在于 XML Schema 使用基于 XML 的语法,而 DTD 具有从 SGML DTD 保留的独特语法。虽然 DTD 经常因为需要学习新的语法而受到批评,但语法本身非常简洁。XML Schema 则相反,它很冗长,但也使用标签和 XML,因此 XML 的作者应该发现 XML Schema 的语法不那么令人生畏。

2、DTD 约束
2.1、DTD 简介

DTD : 文档类型定义(Document Type Definition)是一套关于标记符的语法规则。

DTD 主要分为内部定义和外部定义:

内部 DTD 的定义,需要在顶部加入,语法如下:

代码语言:javascript复制
<!DOCTYPE 根元素 [元素声明]>
  • 元素名称:是自定义的名称,它用于定义被约束 XML 文档中的元素。
  • 元素内容:是对元素包含内容的声明,包括数据类型和符号两部分。XML 的元素分为简单元素和复杂元素两种,DTD 中元素的定义共有 5 种形式,其中三种是简单元素的类型。
2.2、DTD 实例

我们来看实例代码 book.xml:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<书架>
    <书>
        <书名>深入理解Java虚拟机</书名>
        <售价>129.00</售价>
    </书>
    <书>
        <书名>Java并发编程实战</书名>
        <售价>97.00</售价>
    </书>
</书架>

与之对应的 DTD 约束文档 book.dtd,代码如下:

代码语言:javascript复制
<!ELEMENT 书架 (书 )>
<!ELEMENT 书 (书名,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>

对 book.dtd 文档所规定的约束详细解释如下:

  • 在第 1 行中,使用 <!ELEMENT…> 语句定义了一个元素,其中 “书架” 是元素的名称,“(书 )” 表示书架元素中有一个或者多个书元素,字符 用来表示它所修饰的成分必须出现一次或者多次;
  • 在第 2 行中,“书” 是元素名称,“(书名,售价)” 表示元素书包含书名、售价这两个子元素,并且这些子元素要按照顺序依次出现;
  • 在第 3-4 行中,“书名”、和 “售价” 都是元素名称,“(#PCDATA)” 表示元素的内容是可解析字符数据(Parsed Character Data),就是普通文本字符串。

那么,创建 DTD 文件步骤:

  • 看 XML 中有几个元素,在 DTD 中就写几个 <!ELEMENT>
  • 判断元素是简单元素还是复杂元素:
    • 简单元素:没有子元素,语法如下: <!ELEMENT 元素名称 (#PCDATA)>
    • 复杂元素:有子元素的元素,语法如下: <!ELEMENT 元素名称 (子元素 )><!ELEMENT 元素名称 (子元素,子元素,……)>
2.3、DTD 引入约束

有了 DTD 文件,如果想使用 DTD 文件来约束 XML 文档,必须在 XML 文档中引入 DTD 文件。

2.3.1、DTD 外部引入

在 XML 文档中引入外部 DTD 文件有两种方式,具体如下:

代码语言:javascript复制
<!DOCTYPE 根元素名称 SYSTEM "外部DTD文件URI">
<!DOCTYPE 根元素名称 PUBLIC "DTD名称" "外部DTD文件URI">

在上述两种引入 DTD 文件的方式中:

  • 第一种方式用来引用本地的 DTD 文件,“外部DTD文件的URI” 是指 DTD 文件的存放位置,它可以是相对于 XML 文档的相对路径,也可以是一个绝对路径;
  • 第二种方式用来引用网络上公共的 DTD 文件,“外部DTD文件的URI” 是指,Internet 上的一个绝对 URL 地址。
2.3.2、DTD 内部引入

在XML中直接嵌入DTD定义语句的完整语法格式如下所示:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE 根元素名 [
    DTD定义语句
    ……
]>
2.4、DTD 语法

暂略


3、Schema 约束
3.1、Schema 约束简介

同 DTD 一样,XML Schema(XML Schema Definition,XSD,XML Schema定义)也是一种用于定义和描述 XML 文档结构与内容的模式语言,它的出现克服了 DTD 的局限性。

3.2、Schema 较 DTD 的优点

通过 XML Schema 与 DTD 的比较,将 XML Schema 所具有的一些显著优点进行列举,具体如下:

  1. DTD 采用的是非 XML 语法格式,缺乏对文档结构、元素、数据类型等全面的描述。而 XML Schema 采用的是 XML 语法格式,而且它本身也是一种 XML 文档,因此,XML Schema 语法格式比 DTD 更好理解;
  2. XML 有非常高的合法性要求,虽然 DTD 和 XML Schema 都用于对 XML 文档进行描述,都被用作验证 XML 合法性的基础。但是, DTD 本身合法性的验证必须采用另外一套机制,而 XML Schema 则采用与 XML 文档相同的合法性验证机制;
  3. XML Schema 对名称空间支持得非常好,而 DTD 几乎不支持名称空间;
  4. DTD 支持的数据类型非常有限。例如,DTD 可以指定元素中必须包含字符文本(PCDATA),但无法指定元素中必须包含非负整数,而 XML Schema 比 DTD 支持更多的数据类型,包括用户自定义的数据类型;
  5. DTD 定义约束的能力非常有限,无法对 XML 实例文档作出更细致的语义限制,例如,无法很好地指定一个元素中的某个子元素必须出现 7-12 次;而 XML Schema 定义约束的能力非常强大,可以对 XML 实例文档作出细致的语义限制。

通过上面的比较可以发现,XML Schema 的功能比 DTD 强大很多,但相应的语法也比DTD复杂很多。Schema 是基于 XML 编写的,XML Schema 约束文件本身就是一个 XML 文档(文件后缀名为.xsd),文件内的代码要符合 XML 语法规范。

3.3、Schema 名称空间

一个 XML 文档可以引入多个 Schema 约束文档,但是,由于约束文档中的元素或属性都是自定义的,因此,在 XML 文档中,极有可能出现代表不同含义的同名元素或属性,导致名称发生冲突。为此,在 XML 文档中,提供了名称空间,它可以唯一标识一个元素或者属性。

这就好比咱们系有两个同名的同学,如果老师要找那个同学,就得给他们的名字前面加个前缀,XXX 班的某某某。这个 “XXX班” 就相当于一个名称空间。

在使用名称空间时,首先必须声明名称空间。名称空间的声明就是在 XML 实例文档中为某个模式文档的名称空间指定一个临时的简写名称(起个别名),它通过一系列的保留属性来声明,这种属性的名字必须是以 “xmlns” 或者以 “xmlns:” 作为开始。它与其它任何 XML 属性一样,都可以通过直接或者使用默认的方式给出。

名称空间声明的语法格式如下所示:

代码语言:javascript复制
<元素名称 xmlns:prefixname="URI">

在上述语法格式中,元素名称指的是在哪一个元素上声明名称空间,在这个元素上声明的名称空间适用于声明它的元素和属性,以及该元素中嵌套的所有元素及其属性。“xmlns:prefixname” 指的是该元素的属性名,它所对应的值是一个 URI 引用,用来标识该名称空间的名称。

我们来修改 book.xm l文件:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<xs:书架 xmlns:xs="http://www.example.org/book/schema"
xmlns="http://www.w3.org/2001/XMLSchema-instance">
    <xs:书>
        <xs:书名>深入理解Java虚拟机</xs:书名>
        <xs:售价>129.00</xs:售价>
    </xs:书>
</xs:书架>

名称空间的使用就是将一个前缀(xs)绑定到代表某个名称空间的 URI(http://www.example.org/book/schema)上。

然后将前缀添加到元素名称前面来说明该元素属于哪个 Schema 文档。

如果一个 XML 文档有很多元素,而且这些元素都在同一个名称空间,这时,给每个元素名称都添加一个前缀将是一件非常烦琐的事情。

这时,可以使用默认的名称空间,默认名称空间声明时不需要加 “别名”,使用这些元素时,也不用加前缀。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns=http://www.example.org/book/schema>
    <书>
        <书名>深入理解Java虚拟机</xs:书名>
        <售价>129.00</xs:售价>
    </书>
</书架>
3.4、Schema 引入约束

如果想通过 XML Schema 文件对某个 XML 文档进行约束,必须将 XML 文档与 Schema 文件进行关联。在 XML 文档中引入 Schema 文件有两种方式:

3.4.1、使用名称空间引入Schema

上面的书架 “book.xml” 文件对应的 XML Schema 约束文件 “book.xsd”:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.org/book" 
    xmlns:tns="http://www.example.org/book"
    elementFormDefault="qualified">
    <element name="书架">
        <complexType>
            <sequence>
                <element name="书">
                    <complexType>
                        <sequence>
                            <element name="书名" type="string" />
                            <element name="售价" type="string" />
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>
</schema>

那么,我们需要在 XML 文档中的根节点中使用 schemaLocation 属性来指定 Schema 文件。schemaLocation 属性有两个值:

第一个值是需要使用的名称空间;

第二个值是供命名空间使用的 XML Schema 文件的路径;

两者之间用空格分隔。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns="http://www.example.org/book" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org/book book.xsd ">
    <书>
        <书名>深入理解Java虚拟机</xs:书名>
        <售价>129.00</xs:售价>
    </书>
</书架>

如果要使用名称空间引入多个 “XML Schema” 文档。修改 “book.xml” 文件:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns="http://www.example.org/book" 
    xmlns:demo="http://www.example.org/demo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org/book book.xsd
                        http://www.example.org/demo demo.xsd ">
    <书>
        <书名>深入理解Java虚拟机</xs:书名>
        <售价>129.00</xs:售价>
    </书>
</书架>
3.4.2、不使用名称空间引入Schema

如果 book.xsd 与引用它的 XML 文件位于同一个目录中,我们可以不使用名称空间来引入 Schema,book.xsd 中不需要定义 targetNamespace(目标名称空间)和 xmlns:tns(所在名称空间)了,book.xsd 代码:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified">
    <element name="书架">
        <complexType>
            <sequence>
                <element name="书">
                    <complexType>
                        <sequence>
                            <element name="书名" type="string" />
                            <element name="售价" type="string" />
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>
</schema>

修改 book.xml 文件,在 book.xml 中也不需要指定默认名称空间了。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="book.xsd">
    <书>
        <书名>深入理解Java虚拟机</xs:书名>
        <售价>129.00</xs:售价>
    </书>
</书架>

“noNamespaceSchemaLocation” 是一个在标准名称空间(http://www.w3.org/2001/XMLSchema-instance)里面定义好的属性,用于指定 “book.xsd” 文档位置。

3.5、DTD 语法

暂略

0 人点赞