of {$slidecount} ½ {$title} ATZJG.NET {$author}

首页






XML

Document Type Definitions
XML Schema



Haifeng Xu


(hfxu@yzu.edu.cn)

This slide is based on Jeffrey D. Ullman's work, which can be download from his website.

目录

XML 参考资料

XML 参考资料

XML 系列教程
http://www.w3school.com.cn/x.asp

格式规范并且合法的 XML (Well-Formed and Valid XML)

格式规范并且合法的 XML

XML 可以应用于两种不同的模式:

  1. 格式规范的 XML(Well-Formed XML) 允许用户自定义标签.
  2. 合法的 XML(Valid XML) 包括一个 DTD, 即文档类型定义(Document Type Definition). 它指定了允许使用的标签并给出了如何嵌套它们的语法.

参考资料

XML 验证器
http://www.runoob.com/xml/xml-validator.html

格式规范的 XML(Well-Formed XML)

格式规范的 XML(Well-Formed XML)

以一个 XML 声明开始, 形如 <?xml ... ?>

声明为:

<?xml version = "1.0" standalone = "yes" ?>

文档需要有一个根元素(root element), 或根标签(root tag). 它围住了里面的嵌套标签.

标签(Tags)

标签(Tags)

标签通常是成对出现的, 如 <FOO> ... </FOO>

也允许单标签, 如 <FOO/>

标签可以随意嵌套.

XML 标签是大小写敏感的.

例子: 格式规范的 XML

例子: 格式规范的 XML

<?xml version = "1.0" standalone = "yes" ?>
<BARS>
  <BAR>
    <NAME>Joe's Bar</NAME>
    <BEER>
      <NAME>Bud</NAME>
      <PRICE>2.50</PRICE>
    </BEER>
    <BEER>
      <NAME>Miller</NAME>
      <PRICE>3.00</PRICE>
    </BEER>
  </BAR>
  <BAR>
	  ...
  </BAR>
</BARS>

DTD 的结构

DTD 的结构

<!DOCTYPE <root tag> [
  <!ELEMENT <name> (<componets>)>
  ... more elements ...
]>

DTD 中的元素

DTD 中的元素

元素的描述由它的标签名称和由圆括号括起来的任意嵌套子标签的描述组成.

叶子(文本元素) 有 #PCDATA(Parsed Character DATA) 指明.

PCDATA 与 CDATA 的区别

XML 中的CDATA区(CDATA section)允许对XML处理器隐藏类似 < 和 & 的字符. 这是因为这些字符具有特殊的意义:

一个CDATA区以字符 <![CDATA[ 开始, 以 ]]> 结束. 例如:

<company><![CDATA[Fitzgerald & Daughters]]></company>

References

  1. http://www.w3.org/TR/REC-xml/#sec-cdata-sect
  2. Michael Fitzgerald, XML HACKS. 靳京、徐亚莉著. P17.

例子: DTD

例子: DTD

<!DOCTYPE BARS [
  <!ELEMENT BARS (BAR*)>
  <!ELEMENT BAR (NAME, BEER+)>
  <!ELEMENT NAME (#PCDATA)>
  <!ELEMENT BEER (NAME,PRICE)>
  <!ELEMENT PRICE (#PCDATA)>
]>

元素的描述

元素的描述

子标签必须依次出现.

标签名后面可以跟一个符号, 以表示它是否可以重复出现, 次数是多少.

符号 | 表示“或者”的意思, 即用它可以组成一个选项列表, 但仅有一个选项可以选择.

例子: 元素的描述

例子: 元素的描述

通常(西方)人名前面可以有一个头衔(比如: "Prof."), 然后是 first name, last name.

现在假设要表示这样一个元素 NAME, 但除了可以表示上面所述的人名外, 它或者可以是一个 IP 地址.

<!ELEMENT NAME (
  (TITLE?, FIRST, LAST) | IPADDR
)>

DTD 的使用

DTD 的使用

例子: (1)

例子: (1)

<?xml version = "1.0" standalone = "no" ?>
<!-- *** The DTD *** -->
<!DOCTYPE BARS [
  <!ELEMENT BARS (BAR*)>
  <!ELEMENT BAR (NAME, BEER+)>
  <!ELEMENT NAME (#PCDATA)>
  <!ELEMENT BEER (NAME, PRICE)>
  <!ELEMENT PRICE (#PCDATA)>
]>
<!-- *** The document *** -->
<BARS>
  <BAR>
    <NAME>Joe's Bar</NAME>
    <BEER>
      <NAME>Bud</NAME>
      <PRICE>2.50</PRICE>
    </BEER>
    <BEER>
      <NAME>Miller</NAME>
      <PRICE>3.00</PRICE>
    </BEER>
  </BAR>
  <BAR> ...
  </BAR>
</BARS>

例子: (2)

例子: (2)

假设 BARS DTD 存放在文件 bar.dtd 中.

<?xml version = "1.0" standalone = "no" ?>
<!DOCTYPE BARS SYSTEM "bar.dtd">
<BARS>
  <BAR>
    <NAME>Joe’s Bar</NAME>
    <BEER>
      <NAME>Bud</NAME>
      <PRICE>2.50</PRICE>
    </BEER>
    <BEER>
      <NAME>Miller</NAME>
      <PRICE>3.00</PRICE>
    </BEER>
  </BAR>
  <BAR> ...
  </BAR>
</BARS>

第二行 <!DOCTYPE BARS SYSTEM "bar.dtd"> 从文件 bar.dtd 中取得 DTD.

属性(Attributes)

属性(Attributes)

XML 中的开始标签可以包含属性(attributes).

在 DTD 中,
<!ATTLIST E ... >
声明了元素 E 的属性, 后面是它的数据类型.

例子: 属性(Attributes)

例子: 属性(Attributes)

BAR 元素具有一个名为 kind 的属性, 是一个字符串, 用以描述这个酒吧.

<!ELEMENT BAR (NAME BEER*)>
  <!ATTLIST BAR kind CDATA #IMPLIED>

例子: 属性的使用

例子: 属性的使用

在一个允许使用 BAR 标签的文档中, 我们可能会看到下面的内容:

<BAR kind = "sushi">
  <NAME>Homma's</NAME>
  <BEER>
    <NAME>Sapporo</NAME>
    <PRICE>5.00</PRICE>
  </BEER>
  ...
</BAR>

标识符和引用(ID's and IDREF's)

标识符和引用(ID's and IDREF's)

属性可以作为一个对象到另一个对象的指针.

允许 XML 文档成为一个普通的图(graph), 而不只是一个树(tree).

创建标识符(ID)

创建标识符(ID)

给定元素 E 及其类型为 ID 的属性 A.

当在 XML 文档中使用标签 <E> 时, 对其属性 A 指定唯一的值.

如:
<E A = "xyz">

创建引用(IDREF)

创建引用(IDREF)

为使元素 F 指向另一个具有 ID 属性的元素, 我们给定 F 一个类型为 IDREF 的属性.

或者, 令属性具有 IDREFS 类型, 从而 F 元素可以引用任意多个其他元素.

例子: ID's and IDREF's

例子: ID's and IDREF's

新的 BARS DTD 同时包含了 BARBEER 子元素.

BARBEER 具有 ID 属性 name.

BAR 具有 SELLS 子元素, 它由一个数(某啤酒的价格)和指向该啤酒的 IDREF 属性 theBeer 组成.

BEER 具有属性 soldBy, 它是指向所有销售该啤酒的酒吧的一个 IDREFS.

The DTD

The DTD

<!DOCTYPE BARS [
  <!ELEMENT BARS (BAR*, BEER*)>
  <!ELEMENT BAR (SELLS+)>
    <!ATTLIST BAR name ID #REQUIRED>
  <!ELEMENT SELLS (#PCDATA)>
    <!ATTLIST SELLS theBeer IDREF #REQUIRED>
  <!ELEMENT BEER EMPTY>
    <!ATTLIST BEER name ID #REQUIRED>
    <!ATTLIST BEER soldBy IDREFS #IMPLIED>
]>

例子: A Document

例子: A Document

<BARS>
  <BAR name = "JoesBar">
    <SELLS theBeer = "Bud">2.50</SELLS>
    <SELLS theBeer = "Miller">3.00</SELLS>
  </BAR> ...
  <BEER name = "Bud" soldBy = "JoesBar
    SuesBar ..." /> ...
</BARS>

空元素(Empty Elements)

空元素(Empty Elements)

我们可以在元素的属性内部完成所有的工作.

另一个例子: SELLS 元素可以具有名为 price 的属性, 而不是用SELLS的值来表示价格.

例子: 空元素(Empty Elements)

例子: 空元素(Empty Elements)

在 DTD 中, 声明:

<!ELEMENT SELLS EMPTY>
  <!ATTLIST SELLS theBeer IDREF #REQUIRED>
  <!ATTLIST SELLS price CDATA #REQUIRED>

文档中的 SELLS 标签如下, 注意空元素标签闭合的写法.

<SELLS theBeer = "Bud" price = "2.50" />

XML 模式

XML 模式

XML 模式是描述 XML 文档结构的另一种方式, 比 DTD 更为强大.

XML 模式的模式声明本身是一个 XML 文档.

XML-模式文档的结构

XML-模式文档的结构

<? xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs =
"http://www.w3.org/2001/XMLschema">
...
</xs:schema>

xs:element 元素

xs:element 元素

xs:element 具有下面两个属性.

  1. name: 所定义的元素标签名
  2. type: 元素的类型.
    • 可以是一个 XML-Schema 类型, 如: xs:string.
    • 或者是在文档自身中定义的类型名.

Q: XML Schema 中如何声明空标签?

例子: xs:element

例子: xs:element

<xs:element name="NAME" type="xs:string" />

如: <NAME>Joe's Bar</NAME>

复杂类型(Complex Types)

复杂类型(Complex Types)

为描述包含子元素的元素, 我们使用 xs:complexType.

一个复杂类型的典型子元素是 xs:sequence, 它本身包含了一列用 xs:element 描述的子元素.

例子: a Type for Beers

例子: a Type for Beers

<xs:complexType name = "beerType">
  <xs:sequence>
    <xs:element name = "NAME" type = "xs:string"
      minOccurs = "1" maxOccurs = "1" />
    <xs:element name = "PRICE" type = "xs:float"
      minOccurs = "0" maxOccurs = "1" />
  </xs:sequence>
</xs:complexType>


参考 http://www.w3school.com.cn/schema/schema_complex_indicators.asp

属于 beerType 类型的一个元素

属于 beerType 类型的一个元素

<xxx>
  <NAME>Bud</NAME>
  <PRICE>2.50</PRICE>
</xxx>

这里我们不知道属于此类型(beerType) 的元素名称是什么.

定义某个子元素应用了某个复杂类型

如果需要声明某个子元素从属于某个复杂类型, 则应在XML Schema中如下写明:

<xs:element name = "Movies">
  <xs:complexType>
    <xs:sequence>
	  <xs:element name="Movie" type="movieType" minOccurs="0" maxOccurs="unbounded" />
	</xs:sequence>
  </xs:complexType>
</xs:element>

详见书上P.306 图11-19的例子.

例子: a Type for Bars

例子: a Type for Bars

<xs:complexType name="barType">
  <xs:sequence>
    <xs:element name="NAME"
      type="xs:string"
      minOccurs="1" maxOccurs="1" />
    <xs:element name="BEER"
      type="beerType"
      minOccurs="0" maxOccurs="unbounded" />
  </xs:sequence>
</xs:complexType>

子元素 <BEER> 可以出现零到无穷次, 这与 DTD 中的 * 类似.

xs:attribute

xs:attribute

元素 xs:attribute 可以用在复杂类型中, 用以指出属于该类型的元素的属性.

xs:attribute 的属性:

例子: xs:attribute

例子: xs:attribute

<xs:complexType name = "beerType">
  <xs:attribute name = "name"
    type = "xs:string"
    use = "required" />
  <xs:attribute name = "price"
    type = "xs:float"
    use = "optional" />
</xs:complexType>

属于上面新定义类型 beerType 的一个元素

属于上面新定义类型 beerType 的一个元素

<xxx name="Bud" price="2.50" />

受限的简单类型

受限的简单类型

Restrictions

Restrictions

受限的简单类型中元素 restriction 中的描述限制的属性有:

例子: 关于酒吧 license 的简单枚举类型

下面是名为 license 的简单枚举类型

<xs:simpleType name = "license">
  <xs:restriction base = "xs:string">
    <xs:enumeration value = "Full" />
    <xs:enumeration value = "Beer only" />
    <xs:enumeration value = "Sushi" />
  </xs:restriction>
</xs:simpleType>

例子: 价格限制在 $[1,5)$ 区间

例子: 价格限制在 $[1,5)$ 区间

<xs:simpleType name = "price">
  <xs:restriction  base = "xs:float"
    minInclusive = "1.00"
    maxExclusive = "5.00" />
</xs:simpleType>

XML 模式中的键

XML 模式中的键

一个 xs:element 元素可以有一个 xs:key 子元素.

含义: 在这个元素内, 被某个选择器(selector) 路径到达的所有子元素在某些域的组合上取值唯一.

例子: 在一个 BAR 元素内, BEER 子元素的 name 属性是唯一的.

例子: 键

例子: 键

<xs:element name = "BAR" ... >
    . . .
  <xs:key name = "barKey">
    <xs:selector xpath = "BEER" />
    <xs:field xpath = "@name" />
  </xs:key>
    . . .
</xs:element>

外键

外键

在元素 xs:element 中的子元素 xs:keyref 指出在这个元素中, 某些(由选择器selector和域field定义的)值, 必作为值出现在某个键中.

例子: 外键

例子: 外键

假设我们已经定义元素 BAR 中的子元素 NAME 是关于 BARS 的键.

我们希望声明 DRINKER 元素具有子元素 FREQ. FREQ 的一个属性 bar 是一个指向 BAR 子元素 NAME 的外键.

例子: XML 模式中的外键

例子: XML 模式中的外键

<xs:element name = "DRINKERS">
    . . .
  <xs:keyref name = "barRef"
    refers = "barKey"
    <xs:selector xpath = "DRINKER/FREQ" />
    <xs:field xpath = "@bar" />
  </xs:keyref>
</xs:element>

End






Thanks very much!

This slide is based on Jeffrey D. Ullman's work, which can be download from his website.