为什么我们需要targetNamespace?

时间:2012-03-24 16:45:12

标签: xml namespaces xsd

我想了解在XML Schema和WSDL中使用的targetNamespace的目的。实际上,为了简单起见,我们将这个问题限制为XML Schema。

我觉得我完全理解(简单)XML命名空间的概念。按照惯例,我们使用URI / URL,但我们可以使用任何字符串,然后我们将其分配给前缀以供XML节点和属性重用,或者仅用作手头作用域的默认命名空间。到目前为止,这么好吗?

现在进入XML Schema。出于某种原因,XML Schema的发明者认为简单命名空间的概念是不够的,他们不得不引入targetNamespace。我的问题是:targetNamespace引入了哪些重要的好处,而普通的XML命名空间无法提供这些好处?如果XML文档通过schemaLocation或import语句引用xsd文档,则在任何一种情况下,我都会给出引用的实际xsd文档的路径。这是唯一定义我想要引用的Schema的内容。如果另外我想将此Schema绑定到我的引用文档中的特定命名空间,为什么我必须复制已在我引用的XML Schema中定义的精确targetNamespace?为什么我不能简单地重新定义这个命名空间,但是我想在XML文档中使用这个命名空间来引用我想要引用的特定XML Schema文档?

更新

举个例子,如果我在XML实例文档中有以下内容:

<p:Person
   xmlns:p="http://contoso.com/People"
   xmlns:v="http://contoso.com/Vehicles"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation=
    "http://contoso.com/schemas/Vehicles
     http://contoso.com/schemas/vehicles.xsd
     http://contoso.com/schemas/People
     http://contoso.com/schemas/people.xsd">
   <name>John</name>
   <age>28</age>
   <height>59</height>
   <v:Vehicle>
      <color>Red</color>
      <wheels>4</wheels>
      <seats>2</seats>
   </v:Vehicle>
</p:Person>

为什么例如people.xsd Schema需要定义一个targetNamespace,即“http://contoso.com/schemas/People”?为什么我们需要xsd文档中的targetNamespace定义?在我看来,您必须从schemaLocation的名称空间部分获得的所有内容已经包含在XML实例文档中。在xsd文档中强制存在具有相等值的targetNamespace有什么好处?

保罗回答的后续问题:

你能给我一个具体的例子,说明xsd元素名称之间的这种“冲突”变得明显,这可以解释对targetNamespace的需求吗?


好的,这是试图回答我自己的问题。如果它对您来说似乎是连贯的,请告诉我。查看保罗链接页面上的示例帮助了我。

如果我们在上面的原始问题中采用XML实例示例,我们有两个对车辆元素定义的引用。一个在XML实例文档本身中是显式且可见的,但我们还必须想象person.xsd XML Schema再次引用相同的车辆定义作为person的允许子元素。如果我们使用普通的命名空间,允许每个文档为车辆定义自己的命名空间,我们怎么知道XML实例引用车辆的相同XML Schema定义,就像person.xsd一样?唯一的方法是强制执行命名空间的概念,该概念比原始的简单概念更严格,并且必须在多个文档中以完全相同的方式编写。

如果我不是在平板电脑上写这个,我会提供一个代码示例,但在这里我将尝试描述我想到的例子。

想象一下,我们为车辆元素提供了两种不同的XML Schema定义。 location1 / vehicles.xsd将包含从该帖子的问题验证示例的定义(包含颜色,轮子和座位子元素),而location2 / vehicles.xsd将包含完全不同的车辆元素定义,(比如说) ,包含子元素年份,型号和体积)。现在,如果XML实例文档引用了location1 Schema,就像上面示例中的情况一样,但是person.xsd说person元素可以包含在location2 Schema中定义的类型的vehicle子元素,那么没有概念对于targetNamespace,XML实例将验证,即使它显然没有正确类型的工具作为其person元素的子元素。

目标命名空间然后帮助我们确保如果两个不同的文档引用相同的第三个XML模式,它们都是引用相同模式的契约,而不仅仅是包含相似但不相同的元素的模式另一个...

这有意义吗?

4 个答案:

答案 0 :(得分:17)

你似乎走在了正确的轨道上。我会在这里提出一些可能有所帮助的观点。

  • 在实例文档中,您使用XML命名空间来标识元素或属性所在的命名空间。
  • 在架构文档中,您声明将出现在实例中的元素和属性。他们声称的名称空间是什么?这就是targetNamespace的用途。
  • 架构文档位置和命名空间不是一回事。具有相同targetNamespace的多个.xsd文档是很常见的。 (它们可能相互包含,也可能不相互包含,但通常会相互包含。)
  • 实例文档并不总是有一个xsi:schemaLocation元素来告诉解析器在哪里找到模式。可以使用各种方法来告知解析器在何处定位相关的模式文档。 XSD可能位于本地磁盘或某个Web地址上,这不应影响其中元素的命名空间。
    • xsi:schemaLocation是一个提示。解析器可以在其他地方找到给定命名空间的模式,这意味着它们必须能够知道模式的命名空间。
    • 工具(例如数据绑定工具)将预编译模式并生成识别有效文档的代码。这些必须能够知道声明元素的名称空间。

我认为你假设的是实例文档可以使用xsi:schemaLocation指定在某个模式文档中声明的元素和属性的命名空间。这不起作用。首先,解析器可以找到除列出的那些之外的其他模式文档,并且需要知道它们用于什么命名空间。另一方面,它会使模式的推理变得困难或不可能:您将无法查看模式并知道所有内容所属的名称空间,因为该决定将被推迟到写入实例。

答案 1 :(得分:14)

  

问:“按照惯例,我们使用URI / URL,但我们可以使用任何字符串,即   然后我们分配一个前缀,供XML节点和属性重用,或者   仅用作当前范围的默认命名空间。“

答:是的,确实。

  问:“出于某种原因,XML Schema的发明者感受到了这一概念   简单的命名空间是不够的,他们不得不介绍   的targetNamespace“。

答:http://www.liquid-technologies.com/Tutorials/XmlSchemas/XsdTutorial_04.aspx

  

将模式分解为多个文件可以有几个优点。您可以创建可在多个项目中使用的可重用定义。它们使定义更易于阅读和版本,因为它们将模式分解为更小的单元   更易于管理。

     

...

     

如果没有命名空间,这一切都很好,但如果不同的团队开始   处理不同的文件,然后你有可能名字   冲突,定义的位置并不总是很明显   来自。解决方案是为每个模式放置定义   文件在不同的命名空间内。

澄清:

  • XML Schema的主要目的是声明“词汇表”。

  • 这些词汇表可以通过targetNamespace属性中指定的命名空间来识别。

  • Schema(XML文档)可以具有“命名空间”。文档描述的“词汇表”可以有“targetNamespace”。

  • 正如XML Schema提供比SGML DTD更高级别的抽象(XML的原始架构师认为DTD已经足够),XML Schema“targetNamespaces”提供了对“简单命名空间”的抽象级别。

'希望有所帮助

答案 2 :(得分:11)

我认为同时查看实例文档和模式文档有助于理解targetNamespace的作用。考虑一下(基于您的实例文档):

<p:Person
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://localhost:8080/scribble/xml/Person"
        xmlns:v="http://localhost:8080/scribble/xml/Vehicle"
        xsi:schemaLocation="
            http://localhost:8080/scribble/xml/Person
            http://localhost:8080/scribble/xml/person.xsd">
    <name>John</name>
    <age>28</age>
    <height>59</height>
    <v:Vehicle>
        <color>Red</color>
        <wheels>4</wheels>
        <seats>2</seats>
    </v:Vehicle>
</p:Person>

没有为文档指定默认命名空间,但p:*和v:*是特定NS URI的别名。现在看一下架构文档本身:

<?xml version="1.0" encoding="UTF-8"?>
<schema
    xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://localhost:8080/scribble/xml/Person"
    elementFormDefault="qualified"
    xmlns:v="http://localhost:8080/scribble/xml/Vehicle">

    <import
        namespace="http://localhost:8080/scribble/xml/Vehicle"
        schemaLocation="http://localhost:8080/scribble/xml/v.xsd"/>

    <element name="Person">
        <complexType>
            <sequence>
                <element name="name" form="unqualified" type="NCName"/>
                <element name="age" form="unqualified" type="integer"/>
                <element name="height" form="unqualified" type="integer"/>
                <element ref="v:Vehicle"/>
            </sequence>
        </complexType>
    </element>

</schema>

<?xml version="1.0" encoding="UTF-8"?>
<schema
    xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://localhost:8080/scribble/xml/Vehicle"
    elementFormDefault="qualified">

    <element name="Vehicle">
        <complexType>
            <sequence>
                <element name="color" form="unqualified" type="NCName"/>
                <element name="wheels" form="unqualified" type="integer"/>
                <element name="seats" form="unqualified" type="integer"/>
            </sequence>
        </complexType>
    </element>
</schema>

如果查看标记上的属性,对于两个模式文档,默认名称空间为“http://www.w3.org/2001/XMLSchema”,但targetNamespace是在实例文档中用作别名名称空间的名称。

targetNamespace是实例的预期命名空间,无论架构文档的命名空间和实例文档中指定的任何其他命名空间如何。

我觉得将它想象为举办一个有客人名单的聚会以及带名字标签的客人会有所帮助。可以考虑架构文档中的targetNamespace,例如来宾列表中的名称。实例文档中的xmlns,别名或非别名,就像guest虚拟机上的名称标签一样。只要你有客人名单(奇迹般地包括他们国家颁发的身份证的复印件),无论何时遇到某人你都可以验证他们的身份。如果您遇到名称标签与附加参数不匹配的人,您可能会惊慌失措(即抛出错误)。

使用架构/实例,您有:

架构:

targetNamespace="http://localhost:8080/scribble/xml/Person"
targetNamespace="http://localhost:8080/scribble/xml/Vehicle"

实例:

xmlns:p="http://localhost:8080/scribble/xml/Person"
xmlns:v="http://localhost:8080/scribble/xml/Vehicle"

或者......任何在聚会中遇到的任何昵称为“v”的客人(除非另有规定的特殊规则),房屋的任何楼层或后院或泳池中的客人都更好地符合客人的描述在名为http://localhost:8080/scribble/xml/Vehicle的访客列表中。或者他们是入侵者。

这些特殊规则可能会说,如果它们紧挨着P,则V只能挂出,或者如果V存在,则P只能挂出。在这种情况下,当V在那里时P必须挂起,但是V可以在他们想要的任何地方进行,而不需要A在那里。

这样一种模式可以非常灵活,几乎可以定义任何所需的数据结构,并且能够通过将任何给定元素的名称空间(默认或前缀)匹配回TNS和关联模式来跟踪其中的内容。 / p>

答案 3 :(得分:4)

我不清楚你究竟在问什么。显然,模式可以包含许多不同命名空间中组件的定义,并且必须有一些方式来说明“这是命名空间N中元素E的声明”。 XSD的设计者选择设计语言,以便一个模式文档中的所有声明都属于同一名称空间,称为模块的目标名称空间。它的封装可能不同,但差别很小。您认为将模块与命名空间对齐的决定到底是什么问题?