XML Namespace 命名空间

根据 Namespaces in XML W3C 推荐标准的定义,XML 命名空间 是由国际化资源标识符 (IRI) 标识的 XML 元素和属性集合;该集合一般称做 XML“词汇”。html

定义 XML 命名空间的主要动机之一是在使用和重用多个词汇时避免名称冲突。XML 模式用于为 XML 实例建立一个词汇并频繁使用命名空间。所以,正确理解命名空间概念对于从整体上理解 XML 模式和实例验证相当重要。浏览器

命名空间在多个方面相似于 Java 中的程序包:oracle

  • Java 中的程序包能够包含许多可重用的类和接口。一样,XML 中的命名空间能够有许多可重用的元素和属性。
  • 要使用程序包中的类或接口,必须使用程序包名称彻底限定该类或接口。一样,要使用命名空间中的元素或属性,必须使用命名空间彻底限定该元素或属性。
  • Java 程序包可能有一个内部类,该类并不直接位于程序包内部,而是借助它的外围类“属于”该程序包。命名空间也是如此:某些元素或属性可能并不直接在命名空间中,而是借助它的父元素或外围元素而属于命名空间。这是一个传递关系。若是桌子上有一本书,而桌子在地面上,则根据传递关系,这本书位于地面上;尽管这本书并不是 直接位于地面上。

 

所以,能够看出 XML 概念中的命名空间与 Java 中的程序包并没有多大区别。这种对比旨在简化对 XML 中命名空间的了解,并帮助您直观认识命名空间的概念。工具

在本文中,您将了解:ui

  • 命名空间在 XML 中的做用
  • 如何声明和使用命名空间
  • 默认命名空间与无命名空间之间的区别
  • 如何使用 XML 模式建立命名空间,以及
  • 命名空间中的限定和非限定元素/属性之间的区别。

声明和应用命名空间

命名空间被声明为元素的属性。并不必定只在根元素声明命名空间;而是能够在 XML 文档中的任何元素中进行声明。声明的命名空间的范围起始于声明该命名空间的元素,并应用于该元素的全部内容,直到被具备相同前缀名称的其余命名空间声明覆盖—其中,元素内容是指该元素的 <opening-tag> 和 </closing-tag> 之间的内容。命名空间声明以下:spa

<someElement xmlns:pfx="http://www.foo.com" />3d

在属性 xmlns:pfx 中,xmlns 相似于一个保留字,它只用于声明命名空间。换言之, xmlns 用于绑定命名空间,但其自己并不绑定到任何命名空间。所以,以上示例其实是将前缀“pfx”与命名空间“http://www.foo.com”绑定在一块儿。code

一般将 XSD 或 XS 用做 XML 模式命名空间的前缀,但具体使用什么前缀彻底取决于我的。您能够选择将前缀 ABC 用于 XML 模式命名空间,这是合法的,但没有什么意义。使用有意义的命名空间前缀加强了 XML 文档的清晰性。请注意,前缀只用做占位符,而且必须经过能够识别命名空间的 XML 分析器进行解释才能使用绑定到该前缀的实际命名空间。在 Java 类比中,命名空间绑定能够比做声明一个变量,而且每当引用该变量时,它将被所赋与的值替换。orm

在上一个命名空间声明示例中,每当在命名空间范围中引用前缀“pfx”时,它将被解释为绑定到实际的命名空间 ( http://www.foo.com):xml

在 Java 中: String pfx = "http://www.library.com"

在 XML 中: <someElement xmlns:pfx="http://www.foo.com" />

尽管命名空间一般看上去像 URL,但这并不意味着实际声明和使用命名空间时必定要链接到互联网上。实际上,一般将命名空间用做能够在互连网空间中共享词汇和不显示内容的虚拟“容器”。在互连网空间中,URL 是惟一的—所以,您一般选择使用 URL 来惟一标识命名空间。在浏览器中键入命名空间 URL 并不意味着它将显示该命名空间中的全部元素和属性;它只是一个概念。

但这里存在一种误解:尽管 Namespaces in XML W3C 推荐标准声明该命名空间名称应为 IRI,但它对此并没有强制规定。所以,我还可使用如下代码:

<someElement xmlns:pfx=" foo" />

该代码彻底合法。

至此应明了,要使用命名空间,首先应使用前缀绑定将其绑定,而后在须要时使用该前缀。但为何不能从一开始便使用命名空间限定元素或属性呢?首先,因为命名空间(做为 IRI)很是长,所以毫无疑问会使 XML 文档杂乱不堪。第二,也是最重要的,它可能对语法形成严重影响,或者具体一点说,可能对 XML 的生产规则形成严重影响—缘由是 IRI 可能包含 XML 1.0 W3C 推荐标准 不容许在 XML 标记中使用的字符。

无效) <http://www.library.com:Book />
有效) <lib:Book xmlns:lib="http://www.library.com" />

 下面的元素 Title 和 Author 与命名空间 http://www.library.com 关联:

<?xml version="1.0"?>
<Book xmlns:lib="http://www.library.com">
    <lib:Title>Sherlock Holmes</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

在下面的示例中, Sherlock Holmes - III 和 Sherlock Holmes - I 的元素 Title 和 Author 与命名空间http://www.library.com 关联, Sherlock Holmes - II 的元素 Title 和 Author 与命名空间 http://www.otherlibrary.com关联。

<?xml version="1.0"?>
<Book xmlns:lib="http://www.library.com">
    <lib:Title>Sherlock Holmes - I</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
    <purchase xmlns:lib="http://www.otherlibrary.com">
        <lib:Title>Sherlock Holmes - II</lib:Title>
        <lib:Author>Arthur Conan Doyle</lib:Author>
    </purchase>
    <lib:Title>Sherlock Holmes - III</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

Namespaces in XML W3C 推荐标准规定了某些命名空间约束:

  1. 以三字母序列 x、m 和 l(采用任何大小写组合)开头的前缀被保留,供 XML 和 XML 相关的规范使用。尽管这不是一个严重错误,但绑定此类前缀并不可取。前缀 xml 根据定义绑定到命名空间名称 http://www.w3.org/XML/1998/namespace
  2. 只有已声明并绑定到命名空间的前缀才能使用。(是否曾经试过在 Java 中使用没有声明的变量?)

如下代码违反了这些约束:

<?xml version="1.0"?>
<Book xmlns:XmlLibrary="http://www.library.com">
    <lib:Title>Sherlock Holmes - I</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

[错误]:前缀 lib 未绑定到命名空间。 
[不可取]:前缀 XmlLibrary 以“Xml”开头。

 

单个默认命名空间(而非多个默认命名空间)

重复限定一个要在命名空间中使用的元素或属性可能会很是麻烦。这种状况下,能够声明一个 {默认命名空间}。记住,不管在任什么时候候都只能存在一个 {默认命名空间}。所以,术语“多个默认命名空间”在其实是不正确的。

声明一个 {默认命名空间} 意味着,若是 {默认命名空间} 声明范围内的任何元素未使用前缀显式限定,则该元素将被隐式限定。与带前缀的命名空间同样,{默认命名空间} 也能够被覆盖。{默认命名空间} 声明以下:

<someElement xmlns="http://www.foo.com"/>

 

<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

这种状况下,元素 Book、Title 和 Author 与命名空间 http://www.library.com 关联。

记住,命名空间的范围起始于声明该命名空间的元素。所以,元素 Book 还与 {默认命名空间}关联,这是由于它没有前缀。

<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes - I</Title>
    <Author>Arthur Conan Doyle</Author>
    <purchase xmlns="http://www.otherlibrary.com">
        <Title>Sherlock Holmes - II</Title>
        <Author>Arthur Conan Doyle</Author>
    </purchase>
    <Title>Sherlock Holmes - III</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

在以上的示例中, Sherlock Holmes - III 和 Sherlock Holmes - I 的元素 Book、 Title 和 Author 与命名空间http://www.library.com 关联, Sherlock Holmes - II 的元素 purchase、 Title 和 Author 与命名空间http://www.otherlibrary.com 关联。

默认命名空间和属性

默认命名空间不该用于属性;所以,要将命名空间应用于属性,必须显式限定该属性。此处的属性 isbn {没有命名空间},而属性 cover 与命名空间 http://www.library.com 关联。

<?xml version="1.0"?>
<Book isbn="1234"
      pfx:cover="hard"
      xmlns="http://www.library.com"
      xmlns:pfx="http://www.library.com">
    <Title>Sherlock Holmes</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

取消声明命名空间

Namespaces in XML 1.0 W3C 推荐标准不容许取消绑定已经绑定的前缀,而 Namespaces in XML 1.1 W3C 推荐标准则容许这样作。1.0 没有理由不容许取消绑定,不过该错误已经在 1.1 中获得修正。没必要知道此差异,这是由于支持 Namespaces in XML 1.1 的 XML 分析器并很少。

尽管取消绑定带前缀的命名空间有一些差异,但这两个版本均容许您取消绑定或删除已声明的 {默认命名空间}:用其余 {默认命名空间} 声明(覆盖声明中的命名空间为空)覆盖已声明的 {默认命名空间}。取消绑定命名空间与未声明命名空间具备一样的效果。此处的 Sherlock Holmes - III 和 Sherlock Holmes - I 的元素 Book、Title 和 Author 与命名空间 http://www.library.com 关联,而Sherlock Holmes - II 的元素 purchase、 Title 和 Author {没有命名空间}:

<someElement xmlns="" />
<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes - I</Title>
    <Author>Arthur Conan Doyle</Author>
    <purchase xmlns="">
        <Title>Sherlock Holmes - II</Title>
        <Author>Arthur Conan Doyle</Author>
    </purchase>
    <Title>Sherlock Holmes - III</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

此处是根据 XML 1.0 规范中的命名空间取消绑定前缀的无效示例,而根据 XML 1.1 中的命名空间取消绑定前缀则是有效的:

<purchase xmlns:lib="">

今后处开始,前缀 lib 不能在 XML 文档中使用,由于只要您在元素 purchase 的范围内,它就保持未声名状态。固然,您彻底能够再次定义它。

 

无名称空间

若是范围中没有默认命名空间,便不存在命名空间。{默认命名空间} 是使用 xmlns 显式声明的命名空间。若是未使用 xmlns 声明 {默认命名空间},则不能说元素位于 {默认命名空间} 中。这种状况下,咱们能够说元素位于 {无命名空间} 中。当已声明的 {默认命名空间} 被取消声明时,也将应用 {无命名空间}。

摘要:

  • 声明的命名空间的范围起始于声明该命名空间的元素,并应用于该元素的全部内容,直到被具备相同前缀名称的其余命名空间声明覆盖
  • 带前缀的命名空间和 {默认命名空间} 均可以被覆盖。
  • 带前缀的命名空间和 {默认命名空间} 均可以被取消声明。
  • {默认命名空间} 不直接应用于属性。
  • 仅当显式声明 {默认命名空间} 时,该命名空间才存在。若是未声明默认命名空间,则不该使用术语 {默认命名空间}。
  • 若是范围中没有默认命名空间,便不存在命名空间。

 

命名空间和 XML 模式

到目前为止,咱们已经了解了如何声明和使用现有命名空间。如今,让咱们了解如何建立一个新命名空间,并使用 XML 模式将元素和属性添加到其中。

XML 模式首先是一个 XML。换言之,同任何其余 XML 文档同样,XML 模式使用元素和属性构建。此“构建材料”必须出自命名空间http://www.w3.org/2001/XMLSchema,它是已声明和保留的命名空间,其中包含 W3C XML 模式结构规范 和 W3C XML 模式数据类型规范 中定义的元素和属性。不该将元素或属性添加到该命名空间。

使用这些构建块,能够根据须要建立新元素和属性,并对这些元素和属性附加所需的约束,并将其保留在某个命名空间中。(请参见 图 1。)XML 模式将此特殊命名空间称做 {目标命名空间},即新建的元素和属性将驻留到的命名空间。

图 1:XML 模式命名空间中的元素和属性用于编写 XML 模式文档,

该文档生成由用户定义的元素和属性并将其置于 {目标命名空间} 中。

此 {目标命名空间} 随后用于验证 XML 实例。

 

此 {目标命名空间} 从 XML 实例中引用,以确保实例文档的有效性。(请参见 图 2 。)在验证过程当中,验证器验证明例中所用的元素/属性是否存在于已声明的命名空间中,并检查是否对其结构和数据类型存在其余约束。

图 2:从 XML 模式到 XML 模式实例

限定或未限定

在 XML 模式中,咱们能够选择指定实例文档是必须限定全部元素和属性,仍是只限定全局声明的元素和属性。不管作出什么样的选择,都将验证整个实例。那么,咱们为何有两个选择呢?

答案是“可管理性”。当咱们选择 限定 时,咱们指定实例中的全部元素和属性都必须有一个命名空间,这将加强实例的命名空间复杂性。好比,当因将某些局部声明变为全局声明和/将某些全局声明变为局部声明而修改了模式时,根本不会影响实例文档。相反,若是选择 非限定,则指定只有实例中全局声明的元素和属性才必须具备命名空间,从而隐藏实例的命名空间复杂性。但在此情形下,好比,当因将某些局部声明变为全局声明和/将某些全局声明变为局部声明而修改了模式时,将影响全部实例文档 — 且实例再也不有效。若是试图根据已修改的 XML 模式验证该实例,则 XML 模式验证器将报告验证错误。所以,必须根据 XML 模式中所做的修改修正命名空间,才能从新使该实例有效。

<?xml version="1.0" encoding="US-ASCII"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="http://www.library.com"
        targetNamespace="http://www.library.com"
        elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    <element name="Book" type="tns:BookType" />
    <complexType name="BookType">
        <sequence>
            <element name="Title" type="string" />
            <element name="Author" type="string" />
        </sequence>
    </complexType>
</schema>

元素 <schema> 的最近子元素为全局声明,而其余元素则为局部声明。在以上示例中, Book 和 BookType 被全局声明,而 Title 和Author 则被局部声明。

能够经过将模式元素属性 elementFormDefault 和 attributeFormDefault 设置为 qualified 或 unqualified 表示在限定和非限定之间的选择。

elementFormDefault   = (qualified | unqualified) :unqualified
attributeFormDefault = (qualified | unqualified) :unqualified

当将 elementFormDefault 设置为 qualified 时,它表示在该语法的实例中,必须使用前缀或经过设置 {默认命名空间} 来显式限定全部元素。 unqualified 设置意味着只有全局声明的元素才 必须 被显式限定,而局部声明的元素 不得 被限定。在此情形下,限定一个局部声明是错误的。一样,将 attributeFormDefault 设置为 qualified 时, 必须使用前缀显式限定实例文档中的全部属性。

注意,{默认命名空间} 不该用于属性;所以,不能使用 {默认命名空间} 声明限定属性。 Unqualified 好像暗示经过包含的元素位于命名空间中。这颇有趣,对吧?

在下图中,概念符号空间相似于命名空间分区的非规范性概念。例如,若是将命名空间比做电冰箱,那么符号空间就是冰箱中的架子。就像架子对电冰箱中的整个空间进行分区同样,符号空间对命名空间进行分区。

命名空间中有三个主要分区:一个用于全局元素声明,一个用于全局属性声明,一个用于全局类型声明 (complexType/simpleType)。这种安排表示,全局元素、全局属性和全局类型能够具备相同的名称,并能够在 {目标命名空间} 中共存而不发生任何名称冲突。此外,每一个全局元素和全局 complexType 拥有其本身的符号空间来包含局部声明。

让咱们来看看属性对 elementFormDefault 和 attributeFormDefault 的四种可能的值组合。

情形 1: elementFormDefault=qualified, attributeFormDefault=qualified

此处,{目标命名空间} 直接包含全部元素和属性;所以在该情形中,必须限定全部元素和属性。

情形 2: elementFormDefault=qualified, attributeFormDefault=unqualified

 

此处,{目标命名空间} 直接包含全部元素,且这些元素的相应属性包含在相应元素的符号空间中。所以,在该情形中,只须限定元素,而不得限定属性,除非属性是全局声明的。

情形 3: elementFormDefault=unqualified, attributeFormDefault=qualified

此处,{目标命名空间} 直接包含全部属性和仅全局声明的元素,同时这些元素在其符号空间中包含其子元素。所以,在该情形中,只虚限定全局声明的元素和全部属性。

情形 4: elementFormDefault=unqualified, attributeFormDefault=unqualified

 

此处,{目标命名空间} 直接包含仅在全局声明的元素,同时这些元素在其符号空间中包含其子元素。每一个元素在其符号空间中包含相应的属性;所以,在该情形中,只需限定仅在全局声明的元素和属性。

以上各图用于直观说明命名空间内直接包含的内容或传递式包含的内容(取决于elementFormDefaultattributeFormDefault 的值)。该设置表示直接位于{目标命名空间} 中的元素/属性必须在相应的 XML 实例中拥有一个与其关联的命名空间,而未直接(传递式)位于 {目标命名空间} 中的元素/属性不得在相应的 XML 实例中拥有一个与其关联的命名空间。

目标命名空间和无目标命名空间

如今,咱们知道 XML 模式建立新元素和属性并将其置于称做 {目标命名空间} 的命名空间中。但若是在该模式中未指定 {目标命名空间} 又会怎么样?若是未指定属性targetNamespace,则将不存在 {目标命名空间} — 这是合法的 —但在targetNamespace 属性中指定一个空 URI 则是“非法”的。

例如,如下代码无效。不能为 {目标命名空间} 指定一个空 URI:

<schema targetNamespace="" . . .>

在此情形中,若是不存在 {目标命名空间},则如前所述,则将新建的元素和属性保存在 {无命名空间} 中。(使用术语 {默认命名空间} 是错误的。)要验证相应的 XML 实例,相应的 XML 实例必须使用 http://www.w3.org/2001/XMLSchema-instance 命名空间中的 noNamespaceSchemaLocation 属性来引用没有目标命名空间的 XML 模式。

结论

衷心但愿此命名空间概述可以帮助您更轻松地迁移到 XML 模式。Oracle XML 开发人员工具包 (XDK) Namespaces in the XML 1.0 W3C 推荐标准中的 W3C 命名空间;您能够经过使用 SAXParserFactory 和 DocumentBuilderFactory 类中的setNamespaceAware(boolean) 方法打开/关闭命名空间检查(使用 Oracle XDK 中的 JAXP API)。

 

参考: XML 模式:了解命名空间   http://www.oracle.com/technetwork/cn/articles/srivastava-namespaces-098626-zhs.html