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

定义 XML 命名空间的主要动机之一是在使用和重用多个词汇时避免名称冲突。XML 模式用于为 XML 实例创建一个词汇并频繁使用命名空间。因此,正确理解命名空间概念对于从总体上理解 XML 模式和实例验证至关重要。

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

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

因此,可以看出 XML 概念中的命名空间与 Java 中的程序包并无多大区别。这种对比旨在简化对 XML 中命名空间的了解,并帮助您直观认识命名空间的概念。

在本文中,您将了解:

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

声明和应用命名空间

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

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

在属性 xmlns:pfx 中,xmlns 类似于一个保留字,它只用于声明命名空间。换言之, xmlns 用于绑定命名空间,但其本身并不绑定到任何命名空间。因此,以上示例实际上是将前缀“pfx”与命名空间“http://www.foo.com”绑定在一起。

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

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

在 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=""
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

XML Namespace 命名空间的更多相关文章

  1. XML的命名空间

    XML命名空间提供避免元素命名冲突的方法. 命名冲突:在XML中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突. 这个XML文档携带着某个表格中的信息: <ta ...

  2. XML Namespace (xmlns) 属性

    http://www.w3school.com.cn/xml/xml_namespaces.asp XML Namespace (xmlns) 属性 XML 命名空间属性被放置于元素的开始标签之中,并 ...

  3. Android中XML的命名空间、自定义属性

    命名空间(namespace) XML 命名空间提供避免元素命名冲突的方法. 举个例子,A学校有名学生叫做林小明,B学校也有名学生叫林小明,那我们如何识别这两名拥有相同名字的同学呢?这时候命名空间就派 ...

  4. The tag 'DataGridTextColumn' does not exist in XML namespace ....

    错误 10 The tag 'DataGridTextColumn' does not exist in XML namespace 'http://schemas.microsoft.com/win ...

  5. Java 异常 —— java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible

    项目中有个 WebService 接口,调试时使用 Main 方法运行,别人的机器上都能运行,就笔者的机器出问题.他们说是RP的问题…… 异常信息: java.io.InvalidClassExcep ...

  6. 4.C++中的函数重载,C++调用C代码,new/delete关键字,namespace(命名空间)

    本章主要内容: 1)函数重载 2)C++调用C代码 3)new/delete关键字实现动态内存分配 4)namespace命名空间 大家都知道,在生活中,动词和不同的名词搭配一起,意义都会大有不同,比 ...

  7. 解决 weblogic poi3.9 报错 a different type with name "javax/xml/namespace/QName"

    解决 java.lang.LinkageError: loader constraint violation: loader (instance of weblogic/utils/classload ...

  8. Weblogic 9.2 启动时报错 javax.xml.namespace.QName

    启动Weblogic 时会报错.javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionU ...

  9. Aspose WorkbookDesigner打开文件异常"Error xml namespace"

    错误描述: 平台是VS2010的.Net Framework 需要用Aspose的WorkbookDesigner打开excel文件的时候产生异常 异常码是Aspose.Cells.Exception ...

随机推荐

  1. 创建 Windows 7/8 的计算机修复光盘或工具

    Windows 7 Windows 8 控制面板--系统和安全--操作中心--恢复

  2. java学习笔记(三)字符串

    字符串String 创建方法: 一·通过new创建  String  str1= new String("abc"); 二 直接创建   String str2="abc ...

  3. 黄聪:深入理解PHP Opcode缓存原理

    什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...

  4. C# new 和 override.

    http://www.dotblogs.com.tw/skychang/archive/2012/05/10/72114.aspx?fid=60865

  5. CF 369C . Valera and Elections tree dfs 好题

    C. Valera and Elections   The city Valera lives in is going to hold elections to the city Parliament ...

  6. Android使用KSOAP2调用WebService及正确导入jar包的问题(转)

    Android使用KSOAP2调用WebService及正确导入jar包的问题(转)     错误信息 最近在学Android使用KSOAP2调用现有的Webservice的方法,期间在网上找了很多代 ...

  7. sqlserver函数大全

    一旦成功地从表中检索出数据,就需要进一步操纵这些数据,以获得有用或有意义的结果.这些要求包括:执行计算与数学运算.转换数据.解析数值.组合值和聚合一个范围内的值等. 下表给出了T-SQL函数的类别和描 ...

  8. nginx 环境搭建(基于linux)

    Nginx是一种服务器软件,故而其最主要.最基本的功能当然是可以与服务器硬件结合,让程序员可以将程序放在Nginx服务器上,将程序发布出去,让成千上万的网民可以浏览.除此之外,Nginx是一种高性能的 ...

  9. Oracle中增加,修改,删除表中的列

    有些时候,当一个表已经建好,并且已经使用后,发现需要对表结构进行修改,这个时候就要对表中的列进行增删查改操作. 为表增加新列: ALTER TABLE table_name ADD ( column_ ...

  10. 什么时候用position

    postion的情况有很多,fixed是固定,在我们需要把元素固定在某一个位置时使用 absolute和relative要配合使用,要把一个元素固定在另一个元素内某个位置时使用,外部元素为relati ...