【问题标题】:Why do we need targetNamespace?为什么我们需要 targetNamespace?
【发布时间】:2012-04-08 20:32:56
【问题描述】:

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

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

现在进入 XML 模式。出于某种原因,XML Schema 的发明者认为简单命名空间的概念是不够的,他们不得不引入 targetNamespace。我的问题是:targetNamespace 引入了普通 XML 命名空间无法提供的哪些显着优势?如果 XML 文档通过 schemaLocation 或使用 import 语句引用 xsd 文档,无论哪种情况,我都会给出被引用的实际 xsd 文档的路径。这是唯一定义我要引用的模式的内容。另外,如果我想将此 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 架构需要定义一个 targetNamespace,即“http://contoso.com/schemas/People”?为什么我们需要 xsd 文档中的 targetNamespace 定义呢?在我看来,您必须从 schemaLocation 的命名空间部分获得的一切都已包含在 XML 实例文档中。在 xsd 文档中强制存在具有相同值的 targetNamespace 有什么好处?

保罗回答的后续问题:

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


好的,这里尝试回答我自己的问题。让我知道它是否对你来说是连贯的。查看 Paul 链接的页面上的示例对我有帮助。

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

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

想象一下,对于一个车辆元素,我们有两个不同的 XML 模式定义。 location1/vehicles.xsd 将包含验证本文问题示例的定义(包含颜色、车轮和座椅子元素),而 location2/vehicles.xsd 将包含一个完全不同的车辆元素定义,(例如, 带有子元素 year、model 和 volume)。现在,如果 XML 实例文档引用 location1 Schema,就像上面的例子一样,但是 person.xsd 说 person 元素可以包含 location2 Schema 中定义的类型的车辆子元素,那么没有这个概念对于 targetNamespace,XML 实例会进行验证,即使它显然没有正确的车辆类型作为其 person 元素的子元素。

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

这有意义吗?

【问题讨论】:

    标签: xml namespaces xsd


    【解决方案1】:

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

    A:是的,没错。

    问:“出于某种原因,XML Schema 的发明者觉得 简单的命名空间是不够的,他们不得不引入 目标命名空间。”

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

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

    ...

    这一切都可以在没有命名空间的情况下正常工作,但如果不同的团队开始 处理不同的文件,那么你就有可能命名 冲突,并且在定义的位置并不总是很明显 来自。解决方案是放置每个模式的定义 位于不同命名空间中的文件。

    澄清:

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

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

    • 架构(XML 文档)可以有一个“命名空间”。文档描述的“词汇表”可以有一个“targetNamespace”。

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

    '希望有帮助

    【讨论】:

    • 保罗,感谢您这么快的回答!我将在我原来的问题中发布一个后续问题,以保持讨论的一般性和 cmets 流之外......
    • XMLSchema-instance 有什么神圣之处吗?
    • 顺便说一句很棒的链接!那里解释得很好
    【解决方案2】:

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

    【讨论】:

    • 亲爱的迈克尔,很荣幸得到您的答复!回到我做很多 xslt 的日子里,我经常看到你的名字 :)。当然这一切都是有道理的,我只是很难自己看清楚。
    【解决方案3】:

    您似乎走在正确的轨道上。我将在这里提出几点可能会有所帮助。

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

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

    【讨论】:

      【解决方案4】:

      我认为同时查看实例文档和模式文档有助于理解 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,无论是否有别名,就像来宾上的名称标签。只要你有客人名单(奇迹般地包括他们国家签发的身份证的复印件),每当你遇到某人时,你就可以验证他们的身份。如果您遇到佩戴与附加参数不匹配的姓名标签的人,您可能会大吃一惊(即抛出错误)。

      使用架构/实例,您可以:

      架构:

      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 的客人名单上。或者他们是入侵者。

      这些特殊规则可能会这样说,只有当 V 紧挨着 P 时,V 才能出去玩,或者 P 只有在 V 存在时才能出去玩。在这种情况下,当 V 在那里时,P 必须挂起,但 V 几乎可以去任何他们想去的任何地方,而 A 不在。

      通过这种方式,架构可以非常灵活,几乎可以定义任何所需的数据结构,并且能够通过将任何给定元素的命名空间(默认或前缀)匹配回 TNS 和相关架构来跟踪去向。

      【讨论】:

        【解决方案5】:

        这是我个人的理解。
        也许是因为一个 Xml Schema 可以“导入”其他 Xml Schema,比如

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

        如果你只使用“xsi:schemaLocation”告诉xml解析器在xml中使用的命名空间在哪里找到定义,那么在导入其他xml架构的xml架构中,解析器仍然不知道你在哪个命名空间想要使用(例如,在 Xml Schema 中您决定使用 targetNamespace="http://www.example.org/note",但在 Xml 即时您使用 xmlns:n="http://www.example.org/balabala")。
        一言以蔽之,让xml验证器轻松找到您要使用的定义。
        targetNamespace and xmlns

        【讨论】:

          猜你喜欢
          • 2019-06-09
          • 2014-06-18
          • 2017-02-26
          • 2011-04-03
          • 2017-07-27
          • 2020-09-21
          • 2020-03-09
          • 2018-12-24
          • 1970-01-01
          相关资源
          最近更新 更多