目标命名空间和XML命名空间

6

w3schools 页面中,以下为一种 schema 声明形式。

<?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>

在这里,

targetNamespace 定义了正在定义的 XML 文档的命名空间——可以在“此”XSD 中使用哪些标签(元素)和哪些属性。

xmlns=http://www.w3schools.com/schema/schema_schema.asp

另一方面,<p> 定义了 XML 文档中的名称的默认命名空间,那些没有在 "这个" XSD 中定义的名称。因此,解析器首先查找在 targetNamespace 中声明的命名空间。如果它不能在其中找到名称,则继续尝试在 xmlns 中找到下一个名称。

如果我在模式声明中跳过 targetNamespace 属性,那么我会错过什么?虽然我有 xmlnstargetNamespace,但对我来说它们是多余的,因为它们引用的是相同的命名空间。

注意:我看过了What does "xmlns" in XML mean?以及其他一些讨论。

3个回答

19
为了理解targetNamespacexmlns之间的区别,可以思考以下内容。
XSD是一种描述XML模式的语言。任何计算机语言都必须以某种方式表达,即具有某些运算符、关键字等。所有这些东西都被称为语法。
XSD的作者(即W3C)决定不发明另一种语法,而是使用XML本身来描述它。因此,XSD是用XML表达的。XML是其载体。
本质上,这是一种巧合。 XSD作者出于方便而选择了它(确实存在方便之处)。但这不是必要条件。例如,还有另一种名为RELAX NG的XML模式语言,它不基于XML。
但是,一旦XML是所有XSD文本的载体,您就必须处理与XML特定的事物,其中包括xmlns。基本上,它为给定XML文件的元素分配默认命名空间。它与恰好在该文件中描述的XML模式无关。它只是该XML文件的约定(无论其内容如何)。
相反,targetNamespace是XSD语言本身的构成部分。它指定由模式描述的XML元素将属于哪个命名空间。 targetNamespacexmlns之间确实存在一些冗余。但是没有办法利用(利用)它们中的任何一种来消除其中之一。可以这样想:
XML将被解析并转换为其他内容(例如XML信息集)由XML解析器完成。这样的解析器不需要了解XSD,其输出也不会是XML。因此,所有特定于XML的事物都将丢失(即xmlns、命名空间前缀等)。

然后,该信息集(或其他内容)将被传递给XSD处理器,该处理器从头开始,并且必须手头拥有所有必要的信息。因此,targetNamespace将是唯一告诉它有关该XML模式的目标命名空间的内容!


谢谢回答。听起来像是我想要找到的,但还不能确定。对 XSD 还不熟悉。过一天左右再写。 - Roam

9
一个模式定义了一组类型、元素、属性等。如果指定了targetNamespace属性,则这些组件将在特定的命名空间中定义,如果没有targetNamespace属性,则将在空命名空间(或无命名空间)中定义。因此,targetNamespace对于目标XML文档的语义至关重要:元素是否在某个命名空间中存在?
schema中的xmlns属性基本上是一个方便的事情,在目标文档的语义方面并没有意义。这会影响您在模式中引用数据类型和组件时的方式。
考虑这两种选择。在第一种选择中,默认命名空间与目标命名空间相同。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/animal" xmlns="http://www.example.com/animal"
    elementFormDefault="qualified">

    <xsd:simpleType name="Animal">
        <xsd:restriction base="string">
            <xsd:enumeration value="Dog" />
            <xsd:enumeration value="Cat" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:element name="animal" type="Animal" />
    <xsd:element name="date" type="xsd:dateTime" />

</xsd:schema>

在第二种方案中,默认命名空间与XML Schema命名空间相同。请注意类型引用的“倒置”。
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/animal"
    xmlns:tns="http://www.example.com/animal" elementFormDefault="qualified">

    <simpleType name="Animal">
        <restriction base="string">
            <enumeration value="Dog"/>
            <enumeration value="Cat"/>
        </restriction>
    </simpleType>

    <element name="animal" type="tns:Animal" />
    <element name="date" type="dateTime" />

</schema>

然而,无论选择哪种方式,<animal><date> 都存在于 http://www.example.com/animal 命名空间中。该文档

<animal xmlns="http://www.example.com/animal" />

这将对两种选择都有效。


谢谢回答。听起来像是我想要找到的,但还不能确定。对 XSD 还不熟悉。过一天左右再写。 - Roam

6

如果您考虑两个简单的例子,targetNamespace和默认命名空间声明(xmlns=...)之间的区别可能会更清晰。首先:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://example.com/ns"
           xmlns:tns="http://example.com/ns"
           xmlns:ns2="http://example.com/ns2"
           elementFormDefault="qualified">

   <xs:import namespace="http://example.com/ns2"/>

   <xs:complexType name="T1"/>
   <xs:element name="doc" type="tns:T1"/>
   <xs:element name="note" type="ns2:T1"/>
</xs:schema>

这里没有什么复杂的:模式文档声明了一个复杂类型和两个元素,全部在目标命名空间http://example.com/ns中。由于它们在命名空间中,任何引用元素声明或类型定义的文档都需要使用命名空间限定名称。

这两个元素声明分别引用了一个类型;两种类型都具有本地名称T1,但它们位于不同的命名空间,因此限定名称tns:T1和ns2:T1是不同的。

第二个示例声明完全相同的元素和类型,但在声明中使用略微不同的XML语法:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://example.com/ns"
           xmlns="http://example.com/ns"
           xmlns:ns2="http://example.com/ns2"
           elementFormDefault="qualified">

   <xs:import namespace="http://example.com/ns2"/>

   <xs:complexType name="T1"/>
   <xs:element name="doc" type="T1"/>
   <xs:element name="note" type="ns2:T1"/>
</xs:schema>

唯一的区别是命名空间http://example.com/ns 被声明为默认命名空间(使用xmlns="http://example.com/ns"),因此doc元素声明可以使用未限定名称来引用该命名空间中的类型T1。
默认命名空间也可以很容易地设置为http://example.com/ns2--或者(如@ forty-two提供的示例之一所示)http://www.w3.org/2001/XMLSchema
当您理解这两个示例的工作原理时,您将了解targetNamespace属性和默认命名空间声明之间的关系(以及为什么不同)。

我明白了,targetNamespace 是 XSD 特定的,它确定了模式中声明的类型将在哪个命名空间中,xmlns 是 XML 特定的,用于指定 XML 元素的默认命名空间。 - Olivier Boissé
2
不。targetNamespace属性指定模式文档中声明的所有顶级元素、属性和类型名称的命名空间部分;xmlns属性指定如何解释未带前缀的名称。 - C. M. Sperberg-McQueen
基本上,xmlns 就像是一个“导入”,用于使用现有的命名空间,而 targetNamespace 则定义了一个(新的)命名空间? - das Keks
1
@dasKeks - 嗯,不是的,那些不是我会用的词,也不是大多数人会用的词。形如“xmlns = ...”的命名空间声明决定了XML解析器在其范围内解释未加前缀的名称,就像“xmlns:foo = ...”决定了它们如何解释具有前缀“foo”的名称一样。命名空间声明可以在任何XML文档中使用。XSD xsd:schema/@targetNamespace 属性为架构文档中声明或定义的所有顶级元素和类型指定了命名空间名称。 - C. M. Sperberg-McQueen

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