验证xml格式

XML 格式验证:DTD 与 XML Schema 详解

XML(可扩展标记语言)的灵活性使其广泛应用于数据交换和存储,但这种灵活性也带来了格式混乱的风险。为确保 XML 文档的结构合法性和数据有效性,需要通过语义约束机制进行验证。目前主流的 XML 验证方式有两种:DTD(文档类型定义)XML Schema(XML 模式)

DTD(Document Type Definition,文档类型定义)

DTD 是最早的 XML 语义约束标准,通过定义元素、属性、实体等规则,规范 XML 文档的结构。它语法简单,易于理解,但功能有限。

DTD 的引入方式

DTD 可以嵌入 XML 文档内部,或作为外部文件引用,主要有三种引入方式:

(1)内部 DTD

DTD 规则直接定义在 XML 文档内部,仅对当前文档有效。

语法格式

<?xml version="1.0"?>
<!DOCTYPE 根元素 [
  <!-- DTD规则定义 -->
]>
<!-- XML文档内容 -->

示例

<?xml version="1.0"?>
<!DOCTYPE note [
  <!ELEMENT note (to, from, body)>  <!-- note元素必须包含to、from、body子元素,顺序固定 -->
  <!ELEMENT to (#PCDATA)>          <!-- to元素只能包含文本 -->
  <!ELEMENT from (#PCDATA)>        <!-- from元素只能包含文本 -->
  <!ELEMENT body (#PCDATA)>        <!-- body元素只能包含文本 -->
]>
<note>
  <to>ll</to>
  <from>zh</from>
  <body>hello</body>
</note>
(2)外部 DTD

DTD 规则存储在独立的.dtd文件中,可被多个 XML 文档共享,便于维护。

语法格式

<?xml version="1.0"?>
<!DOCTYPE 根元素 SYSTEM "外部DTD文件路径">
<!-- XML文档内容 -->

示例

  • note.dtd(外部 DTD 文件):
  <!ELEMENT note (to, from, body)>
<!ELEMENT to (#PCDATA)>
  <!ELEMENT from (#PCDATA)>
<!ELEMENT body (#PCDATA)>
  • XML 文档引用:

    <?xml version="1.0"?>
      <!DOCTYPE note SYSTEM "note.dtd">
    <note>
        <to>ll</to>
      <from>zh</from>
        <body>hello</body>
    </note>
(3)公用 DTD

由权威机构制定的公共 DTD(如 HTML、SVG 的标准 DTD),通过PUBLIC关键字引入,需指定唯一标识名。

语法格式

<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公用DTD地址">

示例(HTML5 的 DTD):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

DTD 的核心语法

(1)元素声明

定义 XML 元素的结构,包括子元素、文本内容等。

基本语法

<!ELEMENT 元素名称 元素类型描述>

元素类型描述

  • PCDATA:元素只能包含文本(Parsed Character Data),不能有子元素。

    <!ELEMENT name (#PCDATA)>  <!-- name元素只能是文本 -->
  • 子元素模型:通过符号定义子元素的组成和顺序:

    • ,:子元素必须按顺序出现(如(a, b, c))。
  • |:子元素任选其一(如(a | b | c))。

    • ?:元素可出现 0 次或 1 次(如a?)。
    • *:元素可出现 0 次或多次(如a*)。
    • +:元素可出现 1 次或多次(如a+)。
      示例
    <!-- 简历必须包含名字、性别、年龄;电话/手机选一个;家庭住址可选;兴趣爱好可多个;教育经历至少一个 -->
      <!ELEMENT 简历 (名字, 性别, 年龄, (电话 | 手机), 家庭住址?, 兴趣爱好*, 教育经历+)>
  • EMPTY:元素必须是空元素(无内容)。
<!ELEMENT br EMPTY>  <!-- <br/> 是合法的,<br>内容</br> 不合法 -->
  • ANY:元素可包含任意内容(文本或子元素)。

    <!ELEMENT note ANY>  <!-- note元素内容无限制 -->
(2)属性声明

定义元素的属性规则,包括属性名、类型、约束和默认值。

基本语法

<!ATTLIST 元素名 
  属性名1 属性类型1 约束1 [默认值1]
  属性名2 属性类型2 约束2 [默认值2]
>

属性约束类型

  • #REQUIRED:属性必须存在,无默认值。
  • #IMPLIED:属性可选,无默认值。
  • #FIXED:属性值固定为默认值,不可修改。
  • 直接指定默认值:属性可选,未指定时使用默认值。

常用属性类型

  • CDATA:属性值为字符串。

  • (枚举值1 | 枚举值2 | …):属性值只能是枚举中的一个。

    <!ATTLIST file type (txt | csv | json) #REQUIRED>  <!-- type属性只能是txt、csv或json -->
  • ID:属性值为唯一标识符(整个文档中不可重复)。

  • IDREF:属性值引用另一个元素的ID属性。

示例

<?xml version="1.0"?>
<!DOCTYPE email [
  <!ELEMENT email (body)>
  <!ATTLIST email 
    from CDATA #REQUIRED  <!-- from属性必须存在,值为字符串 -->
    to CDATA #REQUIRED    <!-- to属性必须存在 -->
    priority (high | low) "low"  <!-- priority可选,默认low -->
  >
  <!ELEMENT body (#PCDATA)>
]>
<email from="zh" to="ll">
  <body>hello</body>
</email>

DTD 的优缺点

  • 优点:

    • 语法简单,易于学习和编写。
  • 解析速度快,兼容性好(所有 XML 解析器都支持)。

  • 缺点:

    • 不支持数据类型(如整数、日期),只能通过字符串间接约束。
  • 不支持命名空间(难以处理多个 DTD 的冲突)。
    • 扩展性差,复杂结构约束能力有限。

XML Schema(XML 模式)

XML Schema(简称 XSD)是 W3C 推出的新一代 XML 约束标准,解决了 DTD 的诸多缺陷。它本身是 XML 文档,支持数据类型、命名空间和复杂约束,功能更强大。

XML Schema 的基本结构

示例(定义 note 元素的 Schema):

<?xml version="1.0"?>
<xs:schema 
  xmlns:xs="http://www.w3.org/2001/XMLSchema"  <!-- 引入Schema命名空间前缀xs -->
  targetNamespace="http://example.com/note"    <!-- 当前Schema的命名空间 -->
  xmlns="http://example.com/note"              <!-- 默认命名空间 -->
  elementFormDefault="qualified">              <!-- 元素必须用命名空间限定 -->

  <!-- 定义note元素,类型为复杂类型(包含子元素) -->
  <xs:element name="note">
    <xs:complexType>
      <xs:sequence>  <!-- 子元素按顺序出现 -->
        <xs:element name="to" type="xs:string"/>    <!-- to元素为字符串类型 -->
        <xs:element name="from" type="xs:string"/>  <!-- from元素为字符串类型 -->
        <xs:element name="body" type="xs:string"/>  <!-- body元素为字符串类型 -->
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

XML Schema 的核心语法

(1)命名空间与引用

XML Schema 通过命名空间(Namespace)避免元素名冲突,XML 文档需声明引用的 Schema。

XML 文档引用 Schema 的示例

<?xml version="1.0"?>
<note 
  xmlns="http://example.com/note"  <!-- 默认命名空间与Schema的targetNamespace一致 -->
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  <!-- Schema实例命名空间 -->
  xsi:schemaLocation="http://example.com/note note.xsd">  <!-- 绑定命名空间与Schema文件 -->
  
  <to>ll</to>
  <from>zh</from>
  <body>hello</body>
</note>
(2)数据类型

XML Schema 提供了丰富的数据类型,分为简单类型(无子元素和属性)和复杂类型(可包含子元素或属性)。

简单类型
  • 内建类型:直接使用的预定义类型,如:

    • 字符串:xs:stringxs:normalizedString(替换换行 / 制表符为空格)。
    • 数值:xs:integerxs:decimalxs:float
    • 日期时间:xs:date(如2023-10-01)、xs:dateTime(如2023-10-01T12:00:00)。
    • 布尔值:xs:booleantruefalse)。
  • 自定义简单类型:通过限制、列表或联合内建类型派生。

    示例 1:限制类型(年龄必须在 0-120 之间)

    <xs:simpleType name="ageType">
        <xs:restriction base="xs:integer">  <!-- 基于整数类型限制 -->
        <xs:minInclusive value="0"/>      <!-- 最小值0 -->
          <xs:maxInclusive value="120"/>    <!-- 最大值120 -->
      </xs:restriction>
      </xs:simpleType>
    <!-- 使用自定义类型 -->
      <xs:element name="age" type="ageType"/>

示例 2:列表类型(多个年龄值)

<xs:simpleType name="ageListType">
  <xs:list itemType="ageType"/>  <!-- 基于ageType的列表 -->
</xs:simpleType>
<xs:element name="ages" type="ageListType"/>  <!-- 合法值:"18 25 30" -->

示例 3:联合类型(价格或日期)

  <xs:simpleType name="priceOrDateType">
  <xs:union memberTypes="xs:decimal xs:date"/>  <!-- 可接受小数或日期 -->
  </xs:simpleType>
<xs:element name="value" type="priceOrDateType"/>  <!-- 合法值:"99.9" 或 "2023-10-01" -->
复杂类型

用于定义包含子元素或属性的元素,通过<xs:complexType>声明。

示例:带属性的复杂类型

<xs:element name="book">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="author" type="xs:string"/>
    </xs:sequence>
    <!-- 定义属性 -->
    <xs:attribute name="id" type="xs:integer" use="required"/>  <!-- 必需属性id -->
    <xs:attribute name="category" type="xs:string" default="fiction"/>  <!-- 可选属性,默认fiction -->
  </xs:complexType>
</xs:element>

合法的 XML 元素

<book id="1001">
  <title>XML Guide</title>
  <author>John</author>
</book>

XML Schema 的优缺点

  • 优点:

    • 支持丰富的数据类型(整数、日期等),约束更精确。
  • 支持命名空间,可组合多个 Schema 文件。

    • 本身是 XML 文档,易于解析和扩展。
    • 支持复杂结构约束(如条件判断、嵌套类型)。
  • 缺点:

    • 语法较复杂,学习成本高。
  • 解析速度较 DTD 慢(因功能更强大)。

DTD 与 XML Schema 的对比

特性 DTD XML Schema
语法 非 XML 格式,自有语法 纯 XML 格式,遵循 XML 语法
数据类型 仅支持字符串等简单类型 支持丰富的内建类型和自定义类型
命名空间支持 不支持 支持,可避免命名冲突
扩展性 好,支持类型派生和组合
约束能力 基础结构约束 复杂结构、数据范围、条件约束等
学习曲线 简单 较复杂
兼容性 所有 XML 解析器支持 需支持 Schema 的解析器

选择建议

  • 简单场景(如小型配置文件):使用 DTD,简洁高效。
  • 复杂场景(如数据交换、强类型约束):使用 XML Schema,功能更全面。