XSD称作XML架构定义语言,它为为XML处理环境提供了一种类型系统,在未来的 XML 处理中扮演核心角色,尤其是在 Web 服务领域,它将作为构建更高级别抽象的重要基础之一。
(注:以下文章来源于MSDN)。
一 XSD简介
我们首先考虑1+2等于几的问题
1 + 2 = ?
在软件中,回答此类问题所需的信息是由类型系统来提供的。编程语言使用类型系统来简化生成优质代码的任务。类型系统定义了一组可供开发人员在其程序设计中选择使用的类型和操作。一个类型定义一个值空间,或者换句话说,定义一组可能的值。例如,如果上面的操作数被认为是数值类型,答案就可能是 3;但如果它们被认为是字符串型,答案就可能是 “12”,具体情况取决于 “+” 运算符是如何定义的。
类型系统的主要好处之一是,编译器可以使用它在运行前确定代码中是否包含错误,这样就避免了可能产生大量的错误。编译器还可以利用类型系统信息针对给定类型生成操作代码。另外,编译器和运行库都在很大程度上依赖类型系统来确定在使用某个特定类型时如何分配内存空间,这使得开发人员可以不关注这些单调乏味的工作。
许多语言和运行库还允许在运行时以编程方式检查类型信息。这种在运行时检查类型信息的技术通常被称为反射。在今天的主流编程环境中,反射扮演了重要角色。在这些编程环境中,虚拟机(例如,公共语言运行库或 JVM)提供大多数程序所需的额外服务(例如,安全、垃圾回收、序列化、远程方法调用甚至是 Web 服务集成)。
图 1. 类型信息的好处
XML 1.0 是一个缺乏智能类型系统的语言的典型示例。如果没有类型系统,则在 XML 1.0 文档中找到的信息只能被视为文本。这就要求开发人员事先知道“真正的类型”,以便他们在代码中执行必要的强制。
XML 架构定义语言 (XSD) 为 XML 处理环境提供了一种类型系统。在小容器中,XML 架构可以描述您要使用的类型。符合 XML 架构类型的 XML 文档通常是指实例文档,这与类和对象间传统的面向对象的 (OO) 关系非常相似(请参见图 2)。这是一种跳离文档类型定义 (DTD) 的基本工作方式的概念切换,它可在映射到传统的编程语言或数据库类型系统时提供更大的灵活性。在这些环境中,XML 架构大大否决了 DTD 的使用
图 2. OO 与 XML 概念
XML 架构只有在一种完全以 XML 为中心的方式下,才能够提供图 1 所示的全部好处。包含 XML 架构类型信息的逻辑 XML 文档通常被称为后架构验证信息集 (PSVI)。PSVI 使得如下操作成为可能:像在其他编程环境中一样,在运行时执行基于 XML 架构的反射。总的说来,XML 架构预计将在未来的 XML 处理中扮演核心角色,尤其是在 Web 服务领域,它将作为构建更高级别抽象的重要基础之一。
二 数据类型:值和词法空间
XML 架构提供了一个内置数据类型清单,开发人员可以使用它来约束文本。所有这些类型都可以在 http://www.w3.org/2001/XMLSchema 命名空间中找到。每种类型都有一个定义好的值空间。类型的值空间仅仅是可用在给定类型的实例中的一组值。
图 3. 字节值空间
例如,XML 架构提供了一种名为字节的内置类型,它具有从 -128 到 127 的值空间。另一个示例是 XML 架构中的布尔类型,它的值空间非常简单,因为它只有以下两个值:真 和假。共有 44 种内置类型供您选择,每种都有不同的值空间以满足不同数据建模的需要。
图 4 阐释了许多内置类型都被定义为另外一种类型的值空间的子集,也称为通过限制派生。例如,字节型值空间是短整型值空间的子集,短整型值空间又是整型值空间的子集,而整型值空间又是长整型值空间的子集,等等。因此,基本集合论告诉我们,一种派生类型的实例也是它的任一祖先类型的有效实例。(严格地说,它们是 anySimpleType 本身的子集。)
尽管编程语言使用值空间信息来计算需要多大的内存来表示值,开发人员却极少需要担心将它们表示为文本的问题。然而,对于 XML,却不能忽视一个事实,那就是实例将很可能序列化为 XML 1.0 文件,这需要以词法形式表示值。如果每个 XML 架构处理器都独立地决定如何进行此操作,那么互操作性很快就会失去。因此,除了定义每种类型的值空间外,XML 架构还定义了它们所允许的词法表示形式。
图 4. 类型子集
例如,布尔型的真值可以表示为 “true” 或 “1”,而布尔型的假值可以表示为 “false” 或 “0”。双精度型值 10 可以表示为 “10”、“10.0” 或 “10.0000”,甚至可表示为 “0.01E3”。而日期型的“2003 年 1 月 1 日”就可以用词法格式表示为“2003-01-01”。如果使任何类型的词法格式(以及任何可能的变化形式)都符合标准,开发人员就可以不考虑代码实际序列化方式的复杂性,而专门处理代码中的值。
三 在命名空间中定义类型
除了提供内置类型外,大部分编程语言还允许开发人员定义他们自己的类型,它们通常被称为用户定义类型 (UDT)。在定义 UDT 时,大部分编程语言还允许您用命名空间来限定它们,以便使它们不会与其他恰好与其具有相同名称的 UDT 相混淆。图 5 显示了一个 C# 命名空间定义和一个与之类似的 XML 架构定义。正如您所看到的一样,XML 架构还支持在命名空间内定义类型。
图 5. 在命名空间中定义类型
xsd:schema 元素确定命名空间中的内容范围,而targetNamespace 属性指定命名空间的名称。例如,下面的 XML 架构模板定义一个新的名为http://example.org/publishing 的命名空间:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/publishing"
xmlns:tns="http://example.org/publishing"
>
<xsd:simpleType name="AuthorId">
...
</xsd:simpleType>
<xsd:complexType name="AuthorType">
...
</xsd:complexType>
<xsd:element name="author" type="tns:AuthorType"/>
<xsd:attribute name="authorId" type="tns:AuthorId"/>
...
</xsd:schema>
位于 xsd:schema 元素内的所有内容(作为直接子级)都被认为是全局的,因此它们会自动与目标命名空间相关联。在上例中,http://example.org/publishing 命名空间中共有 4 个元素:AuthorId、AuthorType、author 和 authorId。因此,无论何时在架构内引用其中的一个元素,都必须使用命名空间限定的名称。
为了使用命名空间限定的名称,还将需要另外一个命名空间声明,该声明映射到架构的 targetNamespace 值。上面显示的 “tns” 命名空间声明的作用就在于此。因此,无论何时需要引用我们在架构中定义的内容,都可以在名称前加上 “tns” 前缀,如本例所示。
您可以在 xsd:schema 元素内定义两种类型:简单类型(使用 xsd:simpleType)和复杂类型(使用 xsd:complexType)。简单类型只能分配给纯文本元素和属性,因为它们并不定义结构,而是定义值空间。具有附加结构的元素(例如,带有属性或子元素的元素)必须定义为复杂类型。
除了定义类型,您还可以在架构内定义全局元素(使用 xsd:element)和属性(使用 xsd:attribute),并为它们指定类型。在上例中,我定义了一个名为 author 的全局元素和一个名为 authorId 的全局属性。因为这些构造也是全局的,所以当我们在实例文档中使用它们时,必须通过目标命名空间对其进行限定。下面的 XML 文档包含前面定义的 author 元素的一个实例:
<x:author xmlns:x="http://example.org/publishing">
...
</x:author>
下面的 XML 文档包含全局 authorId 属性:
<publication xmlns:x="http://example.org/publishing"
x:authorId="333-33-3333"/>
也可以使用 http://www.w3.org/2001/XMLSchema-instance 命名空间中的 type 属性为实例文档中的元素显式指定类型。这个命名空间包含少数只能用在实例文档中的属性。使用类型属性类似于在一些编程语言中的类型间进行强制转换。下例为 genericId 元素(尚未在架构中定义)显式指定 AuthorId 类型:
<genericId
xmlns:x="http://example.org/publishing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="tns:AuthorId">333-33-3333</genericId>
请注意,AuthorId 和我们指定给上面显示的全局 authorId 属性的类型是相同的。这表明您能够为属性或纯文本元素指定简单类型以约束它们的值。同样,一定要注意到,用于指定类型的 xsi:type 技术只能应用于元素,而不能应用于属性。
|