XML Schema Header&命名空间配置

时间:2011-11-22 15:58:24

标签: xml xsd schema

从DTD迁移到XSD,由于某种原因,转换是一个颠簸的过渡。我了解如何在<xs:schema>根标记内部定义模式,但是过了标题&amp;命名空间声明的东西对我来说尤其令人困惑。

我一直在努力遵循W3S上精心布置的教程,但即使是那个教程也似乎预先承担了很多知识。

我想我正在寻找的是国王的英语解释,说明哪些属性做了什么,他们去哪里,为什么:

  • 的xmlns
  • 的xmlns:XS
  • 的xmlns:的xsi
  • 的targetNamespace
  • 的xsi:的schemaLocation

在某些情况下,我会看到这些元素/属性的不同变体,例如xsi,它似乎有两个不同的符号,如xsi:schemaLocation="..."xs:import schemaLocation="..."

我想在所有这些微小的变化中,我似乎无法对这些变化做出正面或反面。提前感谢为这种混乱带来任何清晰度!

2 个答案:

答案 0 :(得分:61)

您需要了解的第一件事是XML命名空间。如果您有时间浪费,可以阅读the specification。我发现这是与XML相关的更清晰的规范之一。如果你不理解它所说的一切并不重要,它是一个很好的基础。但这是一个快速的破坏。

XML元素和属性有一个名称。当您看到<test att="hello"/>时,您正在查看名称为&#34; test&#34;的元素,其中我们有一个名称为&#34; att&#34;的属性。但这并不是整个故事......

XML是一种语法,允许您混合来自不同标记语言的内容。例如,当使用XSLT将XML文档转换为XHTML页面时,您将至少处理XML中定义的三种标记语言:输入文档,XSLT和XHTML。如果每个人保留自己的元素/属性名称并且不允许任何冲突,这样的混合将变得相当困难。

输入XML命名空间。 XML命名空间定义了一个&#34;球体&#34;元素和属性名称具有实际语义。元素&#34;模板&#34;在XSLT命名空间中具有明确定义的含义。元素&#34; complexType&#34; XML Schema名称空间中具有明确定义的含义。如果您希望使用自己的标记语言使用XML,那么只要您在不同的命名空间中这样做,就可以这样做。

为了确保命名空间是唯一的,您需要提供一些唯一标识符。该规范决定了URI的使用,通常以HTTP URL的形式。原因很简单:这样的URL往往是很好的唯一标识符。但它也是导致混淆的一个非常常见的原因,因为人们认为URL确实具有意义,或者在XML处理期间将通过网络访问。 非常清楚情况并非如此!此URL不需要指向任何现有资源。它不会经历任何转换或被解析为网络地址。即使两个URL指向完全相同的东西,当它们相差一个字符时,它们也被视为不同的名称空间。命名空间标识符只是一个字符串,并且区分大小写。没什么。

随着名称空间的引入,XML元素或属性的名称突然由两部分组成:名称空间和本地名称。那&#34;测试&#34; <test/>中只有本地名称。所谓的完全合格的名字&#34;由命名空间和本地名称的一种不可见的组合组成。有时会使用符号{namespace URI}local-name,但这只不过是惯例。

所以现在我们需要能够在XML文档中使用名称空间。为了声明命名空间,XML具有硬编码机制。它使用特殊字符串xmlns来允许进行名称空间声明。它可以通过以下两种方式之一完成:将命名空间绑定到前缀,或将其声明为默认命名空间。

绑定到前缀时,表单如下:xmlns:prefix="namespace URI"。这是XML文档中的一个示例:

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

我们现在将名称空间http://www.foo.com绑定到前缀foo。只要将此前缀放在元素或属性的名称前面,我们就会声明他们已成为该命名空间的一部分。

这里需要注意的是,实际前缀绝对没有任何意义。以下XML文档在语义上完全相同:

<bar:root xmlns:bar="http://www.foo.com">
    <bar:test />
</bar:root>

前缀只是表示命名空间的便捷方式。它使我们不必每次都完全使用URI。

Next up是默认命名空间。可以使用xmlns="namespace URI"声明默认命名空间。您可以抽象地将此视为将命名空间绑定到空前缀。再次使用相同的XML文档,但这次没有前缀:

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

使用起来更方便一些。那为什么要有前缀呢?当我们混合来自不同名称空间的内容时,他们开始发挥作用:

<root xmlns="http://www.foo.com">
    <so:test xmlns:so="http://stackoverflow.com" />
</root>

这次它是一个不同的XML文档。我们的root元素位于http://www.foo.com命名空间中,但test元素位于http://stackoverflow.com,因为我们已经绑定了so前缀并使用了test它在<root xmlns="http://www.foo.com"> <test /> <so:test xmlns:so="http://www.stackoverflow.com" xmlns="http://www.bar.com"> <test /> </so:test> </root>

您还注意到,可以在XML文档中的任何元素上声明名称空间。该声明的范围(以及绑定到前缀,如果适用)则成为该元素及其内容。

这有时会变得令人困惑,甚至更多,因为声明可能会互相覆盖。查看此文档:

root

花点时间弄清楚每个元素的命名空间......这是一个很好的练习。

http://www.foo.com位于命名空间test中。第一个test元素也在该命名空间中,因为我们还没有使用前缀,但我们在该默认命名空间的范围内。前缀为so的第二个http://www.stackoverflow.com元素位于命名空间test中,因为它是我们绑定前缀的内容。

那么那里是第三个最里面的http://www.bar.com元素。它的名称空间是什么?它没有前缀,因此它必须位于默认命名空间中。但是,我们在第二个测试元素中更改了默认命名空间!所以现在最里面的元素属于http://www.foo.com命名空间,而不是http://www.w3.org/2001/XMLSchema

困惑了吗?请记住以下内容:

  • 命名空间只是一个字符串。 URI用作获取唯一标识符的便捷方式。
  • 前缀用于表示命名空间,但其名称没有任何意义。只需将其视为占位符。
  • 您可以设置默认命名空间。其范围内没有前缀的所有元素都将成为其中的一部分。

呼。现在,进入W3C XML Schema。所有这些与它有什么关系?

嗯,对于初学者来说,XML Schema本身是XML中定义的标记语言。所以它有理由得到它自己的命名空间。该命名空间正式为S。如果你将<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> </xsd:schema> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> </xs:schema> <schema xmlns="http://www.w3.org/2001/XMLSchema"> </schema> 写成小写,那就错了。开始明白为什么有些人真的讨厌命名空间?

以下三个文件完全相同:

xs

重要的是我们正在使用来自XML Schema名称空间的东西。但是,作为惯例,人们倾向于在XML Schema中使用前缀xsdhttp://www.w3.org/2001/XMLSchema-instance

当我们有XML文档时,我们可能希望指定它的架构所在的位置。多个模式可以与XML文档相关,因为我们已经声明语言可以混合在XML中。为了说XML文档是模式的实例,再次提供了一个特殊的命名空间:xsi。按照惯例,我们倾向于将此命名空间绑定到前缀schemaLocation。但同样,这不是强制性的。

在该架构实例命名空间中定义了几个属性。其中包括noNamespaceSchemaLocation<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.foo.com/schema"> </root> 。看一下这个文件:

xsi

那里发生了什么?首先,我们声明我们将前缀http://www.w3.org/2001/XMLSchema-instance绑定到命名空间noNamespaceSchemaLocation。然后我们在该命名空间中使用了一个属性:<root xmlns:huh="http://www.w3.org/2001/XMLSchema-instance" huh:noNamespaceSchemaLocation="http://www.test.com/schema"> </root> 。该属性告诉我们模式的位置,以验证文档中不在任何特定名称空间中的那些部分。以下XML文档在语义上完全相同:

noNamespaceSchemaLocation

请记住,前缀名称没有任何意义。他们是占位符。那么,noNamespaceSchemaLocation属性的含义是什么?基本上,它告诉我们在哪里可以找到模式。现在与名称空间URI相反,这绝对是可用于从网络或本地存储中获取内容的东西。验证文档中声明的模式的XML处理器可能会尝试获取它。

然后有一个名为noNamespaceSchemaLocation的事实。模式定义了一个&#34;目标命名空间&#34;。这样做是说明它定义的元素和属性的命名空间是什么。但是可以省略目标命名空间。在这种情况下,我们已经获得了没有命名空间的XML文档的模式。这种模式可以用http://www.w3.org/2001/XMLSchema-instance来引用。

在许多情况下,架构实际上会定义命名空间。为了说明哪个架构属于哪个命名空间,我们可以使用schemaLocation命名空间中的另一个属性:http://www.foo.com。该属性可以包含名称空间URI和模式URI的对(由空格分隔)。假设我们有位于http://www.myschemas.com/foo-schema的名称空间<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema"> </root> 的模式。然后我们可以说明如下:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema http://www.bar.com http://www.randomschemas.com/bar-schema">
</root>

这是一个包含多个命名空间位置对的示例:

http://www.w3.org/2001/XMLSchema-instance

这里需要记住的是http://www.w3.org/2001/XMLSchema内容用于作为模式实例的XML文档。名称空间xs:import是用于定义模式本身的名称空间。


所以到现在为止,我们依靠URI和具有特殊含义的怪异属性。这就是命名空间的问题:它们看起来非常复杂,直到你弄清楚它们有多简单。只需密切关注哪个前缀绑定到哪个名称空间URI,并知道该URI定义了什么。

我需要针对您的问题解决另外两个模式:xs:includexs。请注意我在这里如何使用xmlns前缀约定,因为我们正在谈论W3C XML Schema。

include元素可用于将模式与相同的目标名称空间组合。基本上它允许我们将模式模块化为更小的部分并将它们组合在一起。

import元素的排序方式相同,但对于具有不同目标名称空间的模式。这允许我们组合不同标记语言的模式。


所以回顾一下:

  • xmlns:prefix:用于指定默认命名空间。
  • prefix:用于将命名空间绑定到http://www.w3.org/2001/XMLSchema
  • xs:XML Schema的命名空间。按惯例,通常绑定到http://www.w3.org/2001/XMLSchema-instance前缀,但这不是强制性的,也不是自动完成的。
  • xsi:定义一系列有用的名称空间,用于声明XML文档如何作为模式实例的详细信息。按惯例,通常绑定到targetNamespace前缀,但这不是强制性的,也不是自动完成的。
  • schemaLocation:可以在XML Schema(在根元素上)中使用的属性,用于指定这是一个模式定义的命名空间。
  • http://www.w3.org/2001/XMLSchema-instance:命名空间{{1}}定义的属性之一,用于指示可以为一个或多个命名空间找到一个或多个模式的位置。

我的最后建议:找到一些方便的方法来验证文档对模式并稍微玩一下。试验命名空间,包含和导入。使用多个名称空间创建文档并尝试使用范围。

之后,检查XML本身,XML名称空间和XML Schema的规范。它是硬核阅读,但如果你顺利通过它,你将会理解许多人在使用XML多年后似乎仍然想念它。最终它都有意义。

祝你好运!

答案 1 :(得分:2)

回答您的疑问:

  1. xmlns - 实例文档中使用的唯一值,用于指示XML是哪个架构的实例(或者它将验证哪个架构)。即使命名空间未标识实际的模式文件,也应该有一个模式来定义此命名空间。
  2. xmlns:xs - 称为名称空间前缀,并按照实例文档中使用的惯例来指示XML中使用的类型来自何处。您可以将此视为C#中的using或VB中的imports。例如,xmlns:xs="http://mySharedTypes"表示在这个XML中,我的一些类型来自命名空间“http:// mySharedTypes”,这些类型将以“xs”为前缀。
  3. xmlns:xsi - 如上所述。事实上,在引用W3C模式名称空间http://www.w3.org/2001/XMLSchemahttp://www.w3.org/2001/XMLSchema-instance时,按惯例使用xs和xsi前缀。然而,这些名称空间前缀只是约定,实际上可以是任何东西。
  4. targetNamespace - 您在架构定义中放入的唯一值,它为您在架构中定义的命名空间提供了类型。因此,如果有人想要使用模式中的类型,那么它们必须包含与targetNamespace具有相同值的xmlns属性。
  5. xs:import schemaLocation - 这通常是另一个架构的相对路径,但并非所有xml处理器都能识别它。因此,您可以选择链接到xs:import中的另一个架构,作为架构文件本身的一种快捷方式。导入中的另一个属性是schema targetNamespace,这是必需的。
  6. xsi:schemaLocation - 虽然它与import属性的名称相同,但它的定义不同。按照惯例,xsi名称空间前缀引用http://www.w3.org/2001/XMLSchema-instance名称空间中的类型,这些类型在实例文档中使用,而不是在模式文档中使用。
  7. 对不起,如果上述内容不明确,那就是一个开放式的问题,你可以为这些点中的任何一个写出大量材料。如果您需要明确任何一点,请询问 - 我很乐意提供,或者创建一个范围更窄的新问题。