XSD:命名空间和默认命名空间有什么区别?

8
也许问题的标题有些误导,这是因为我无法用一句话来解释我的问题。在w3school教程中,有一个示例:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3schools.com"
           xmlns="http://www.w3schools.com"
           elementFormDefault="qualified">
    ...
    ...
</xs:schema>

作者指出:xmlns:xs="http://www.w3.org/2001/XMLSchema"表示:

模式中使用的元素和数据类型来自“http://www.w3.org/2001/XMLSchema”命名空间。它还指定来自“http://www.w3.org/2001/XMLSchema”命名空间的元素和数据类型应以xs为前缀。

然而,作者还指出targetNamespace="http://www.w3schools.com"表示:

此模式定义的元素(注意:to、from、heading、body)来自“http://www.w3schools.com”命名空间。

我不理解前面的段落。第一段指出元素来自 http://www.w3.org/2001/XMLSchema 命名空间,而第二段指出元素来自 http://www.w3schools.com 命名空间。
在我看来,这两个句子互相矛盾。
请问您能告诉我哪一个是正确的吗?每一句的真实含义是什么?
谢谢您的时间。
此致敬礼
2个回答

16

默认命名空间、限定名称和前缀

默认命名空间是没有映射到任何前缀的命名空间。您可以使用以下方式声明它:

xmlns="a-string-that-is-usually-an-uri"

如果在XML文件中有这样一条声明,任何未添加前缀的元素都属于该命名空间。未添加前缀的属性总是属于无命名空间

您可以在XML文档中有几个命名空间声明,但每个范围内只能有一个默认命名空间。您也不需要有任何默认命名空间。范围包括元素本身及其后代。在下面的文档中,有两个默认命名空间。 ns2 命名空间替换了其声明所在的元素和其后代中的 ns1 命名空间:

<root xmlns="ns1">
    <text>This is ns1</text>
    <child xmlns="ns2">
        <text>This is ns2</text>
    </child>
</root>

上述文档中有两个<text>元素。实际上,它们是完全不同的元素,因为每个元素都属于不同的命名空间。它们具有相同的本地名称,但其限定名称不同。

如果您有相同命名空间的声明,例如:

xmlns:p="a-string-that-is-usually-an-uri"
您正在使用前缀p映射命名空间,可以由上下文中的任何元素使用(考虑一个格式正确的文档,不一定有效)。对于有效的文档,属于命名空间的元素应该通过它进行限定,要么作为声明默认命名空间的元素的无前缀后代(或自身),要么作为声明将该前缀映射到该命名空间的元素的有前缀后代(或自身)。前缀也可用于限定属性。
通过使用前缀,您可以在根元素处拥有所有声明,并且合格的元素可以混合使用。
<root xmlns:p="ns1" xmlns:q="ns2" xmlns="ns0">
    <p:text>This is ns1</p:text>
    <q:child xmlns="ns2">
        <q:text>This is ns2</q:text>
        <p:text>This is ns1 again!</p:text>
        <text>This is ns0</text>
    </q:child>
</root>

上述每个<text>元素都属于不同的命名空间。

花点时间阅读这篇指南:理解XML命名空间。它很简短,如果你仔细阅读,就一定会非常清楚地了解XML中的命名空间是如何工作的。如果您愿意,也可以阅读XML命名空间规范,这是官方文档。

XSD中的目标命名空间

关于您正在阅读的教程文件。

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3schools.com"
           xmlns="http://www.w3schools.com"
           elementFormDefault="qualified">
    ...
    ...
</xs:schema>

该文档有两个命名空间声明以及一个目标命名空间声明。由于它也是一个模式,所以它包含属于目标命名空间类型定义。这可能会令人困惑,因为模式是使用XML声明其他XML文档规则的XML文档。将XSD文档视为普通的XML文档,你可以将一个命名空间映射到xs前缀,另一个则是默认命名空间。你也可以合法地使用不同的前缀:

<abc:schema xmlns:abc="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3schools.com"
           xmlns:xyz="http://www.w3schools.com"
           elementFormDefault="qualified">
    <abc:complexType name="MyType"> ...</abc:complexType>
    <abc:element name="myElementOne" type="xyz:MyType" />
    <abc:element name="myElementTwo" type="abc:string" />
</abc:schema>

如果你仔细观察上面的示例,你可能会看到以下关联:

  1. schemacomplexTypeelement 元素以及 string 类型都属于 http://www.w3.org/2001/XMLSchema 命名空间。
  2. 模式中没有属于 http://www.w3schools.com 命名空间的元素或属性,因为这是一个模式,它实际上在定义那些元素。
  3. MyType 复杂类型是 http://www.w3schools.com 命名空间的一部分。这是因为它是在模式中声明的,而模式的 targetNamespacehttp://www.w3schools.com。由于该命名空间映射到 xyz 前缀,则在引用它时需要使用 prefix。这就是第一个元素的 type 属性所发生的,与第二个元素的 type 属性引用了 http://www.w3.org/2001/XMLSchema 命名空间下的 string 类型相同。

你也可以像这样编写上述模式。这不会有任何区别:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3schools.com"
           xmlns:xyz="http://www.w3schools.com"
           elementFormDefault="qualified">
    <complexType name="MyType"> ...</complexType>
    <element name="myElementOne" type="xyz:MyType" />
    <element name="myElementTwo" type="string" />
</schema>

请注意现在默认命名空间存在,它是http://www.w3.org/2001/XMLSchema,因此该命名空间的所有类型和元素都是无前缀的。

然而,最好遵循约定并将前缀映射到XSD命名空间(通常为xsxsd)。

关于冲突的句子:

实际上,它们并不矛盾。但是它们写得不好(也许在它们的原始上下文中可能会好一些)。第一句话:

模式中使用的元素和数据类型来自“http://www.w3.org/2001/XMLSchema”命名空间。它还指定,来自“http://www.w3.org/2001/XMLSchema”命名空间的元素和数据类型应以xs为前缀。

将XSD文档视为常规XML文件。在任何XML文件中,根元素中的xmlns =“ns1”之类的命名空间声明是在声明无前缀元素来自ns1 默认命名空间。在句子所描述的情况下,作者是指所有带前缀的元素(如elementcomplexTypesimpleTypesequence)和类型(如stringintegerdecimal),因为xs前缀被映射到XSD命名空间。作者谈论的是XML文件中使用的元素和类型,而不是定义的。

下一句话是关于targetNamespace的,它是特定于XSD规范的属性。它声明了所有类型的命名空间:

targetNamespace=”http://www.w3schools.com”表示此模式定义的元素(注意,to、from、heading、body)来自“http://www.w3schools.com”命名空间。

这涉及您为类型和元素分配的名称。当您创建声明该命名空间的实例时,您将使用这些元素:

<note xmlns="http://www.w3schools.com">...</note>
或者
<x:note xmlns:x="http://www.w3schools.com">...</x:note>

但是在XSD中,您正在定义它们。如果您从未使用 type ref 等属性引用其中创建的任何其他类型或元素,则甚至不需要在模式中声明 xmlns =“ http://www.w3schools.com”


我可以添加 xmlns="xs" 并编写一个更兼容的 XSD 吗? - Marco Sulla

0
   default namespace serve only one purpose, it allows use of namespace qualified xml components without namespace prefix. 

只是给你一个解决上述问题的提示,当你定义一个组件并设置它的targetNamespace时,需要考虑;而当你引用组件时,则要考虑默认命名空间(或带有前缀的命名空间)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接