没有前缀的targetNamespace和xmlns,有什么区别?

83

在 XML Schema 文档中,如果同时存在 targetNamespace 和 xmlns无前缀,该如何处理?

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            targetNamespace="http://example.com/" xmlns="http://example.com/">

它们之间的确切区别是什么? 我的理解是,如果你有一个没有前缀的xmlns,所有没有前缀的元素都会获得该命名空间......令人困惑的是,targetNamespace也是一样。


2
我可能对这个主题缺乏一些知识,但是答案不就是:xmlns是此文档(模式文档)的默认命名空间,而targetNamespace是此模式文档验证的命名空间吗?这样,xmlns和targetNamespace就是两个不同的东西了,不是吗? - Vering
@Vering,我的测试结果与你的第一句话相符,是的,targetNamespace明确指向模式验证的文档。事实上,targetNamespace的存在似乎还需要'xmlns'或'xmlns:xxx'的存在。实际上,您可以将许多'xmlns:xxx'、'xmlns:yyy'和'xmlns'组合在一起,它仍然能够验证。 - daparic
6个回答

84
targetNamespace是XML Schema的一个“工件”,它的目的是指示模式文件描述的特定XML命名空间。

由于XML Schema是一个XML文档,因此可以为XML文件本身定义默认的XML命名空间(这就是xmlns属性的作用);其影响是多方面的:创作和组合。例如,在同一文件中引用模式中定义的项目时,不必为其使用前缀(例如,全局simpleType用作属性或元素的类型)。

根据我的经验,许多XML Schema作者认为这是一种“最佳实践”...所以你走在了正确的道路上。

在XSD方面,targetNamespace规定了模式组件的限定名称的命名空间部分,其中包括元素、属性、组和属性组以及简单和复杂类型。在XSD中定义的一些限定名称(元素和属性)被XML实例文档“直接”使用。其他限定名称,例如类型,可以通过实例XML文档中的xsi:type属性进行引用。其余的(组、属性组)用于通过引用促进模式组合。

我也认为(一般而言),人们从两个角度来设计XSD:
  • 匹配现有的XML。在这种情况下,如果您的XML使用命名空间,则每个使用的命名空间都将生成一个具有匹配targetNamespace属性的XSD模式元素。

  • 纯建模。然后,您可以将targetNamespace视为UML包、数据库模式、Java包或.NET命名空间,并且在此情况下它的含义。从根本上说,它是避免命名冲突的机制;但它也是将模型分区到主题领域等的机制。


33

如果仍然感到困惑,请考虑这三个XSD。它们都定义了一个全局类型和一个引用它的全局元素定义。

首先,像上面发布的XSD。它使用“xsd”作为模式命名空间的前缀,以及目标命名空间的默认命名空间:

<xsd:schema 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="http://example.com/" 
  xmlns="http://example.com/">

  <xsd:element name="aGlobalElement" type="aGlobalType"/>

  <xsd:simpleType name="aGlobalType">
    <xsd:restriction base="xsd:string"/>
  </xsd:simpleType>   
</xsd:schema>  

现在是同样的XSD,但为目标命名空间定义和使用命名空间前缀:

<xsd:schema 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="http://example.com/" 
  xmlns:tns="http://example.com/">

  <xsd:element name="aGlobalElement" type="tns:aGlobalType"/>

  <xsd:simpleType name="aGlobalType">
    <xsd:restriction base="xsd:string"/>
  </xsd:simpleType> 
</xsd:schema>  

最后,一个使用默认命名空间而不是 'xsd' 作为 XML 模式命名空间的版本:

<schema 
  xmlns="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="http://example.com/" 
  xmlns:tns="http://example.com/">

  <element name="aGlobalElement" type="tns:aGlobalType"/>

  <simpleType name="aGlobalType">
    <restriction base="string"/>
  </simpleType>
</schema>

大多数模式作者选择第一个或最后一个,因为如果默认命名空间机制可用,则我们可以将其用于某些内容。


18

xmlns

xmlns属性设置了所描述元素的默认命名空间。默认命名空间应用于所描述元素内的所有未明确声明其他命名空间的元素。

对于WSDL文件,将默认命名空间设置为标准值:http://www.w3.org/ns/wsdl

targetNameSpace

此属性包含您的 Web 服务的名称空间。您可以自由选择此名称空间,但有一个约定规定 URI 应指向服务的 WSDL。

xmlns:tns

该命名空间应设置为与 targetNameSpace 属性相同的 URI。这样,您可以通过此命名空间前缀(tns)引用目标命名空间。

来源:http://tutorials.jenkov.com/wsdl/description.html


2
目标命名空间的URI并不“指向”任何东西 - 它只是命名空间的标识符。它可能是Web服务的URI,但仍然只是用于标记命名空间。 - Suncat2000

7

命名空间就像作用域

targetNamespaceschema元素的一个属性,用于定义XSD文件中的命名空间,即包。按照惯例,我们使用URI/URL,但也可以使用任何字符串。

xmlns是一个属性,用于引用来自当前元素范围的xmlns属性值的元素和数据类型。

例如:

  • xmlns:xsd="http://www.w3.org/2001/XMLSchema"带有前缀xsd,意味着命名空间应该以xsd:为前缀。
  • xmlns="http://www.w3.org/2001/XMLSchema"没有前缀,是默认的。
  • xmlns:p="http://www.example.com/People"带有前缀p,意味着命名空间应该以p:为前缀。

其中xmlns:xsdxmlns:p是QNames,xmlns是本地名称。

以下图像有助于理解XSD,使用Java类比喻:

enter image description here


3

其他回答已经很好了,所以我不会在这里重复它们的解释。然而,如果有来自Java背景的人发现这更简单,请看我想出来的类比:

Original Answer翻译成"最初的回答"

  1. .xsd document is the artifact/.jar file
  2. xmlns is the

    package com.example
    

    statement, you declare at the top of your Java classes.

最初的回答:考虑一下(类比),如果您在Java项目中只有一个单一的包,并且所有的类都声明和定义在一个单独的外部类中。
例如,
    package com.furniture.models

    public class FurnitureShop {

         int noOfTables;
         int noOfChairs;
         int noOfBeds;
         List<Table> tables;
         List<Chair> chairs;
         List<Bed> beds;

         // and now instead of declaring and defining a class for table/chair/bed in a 
         // separate file, you just add it here 
         public static class Table {
             int height;
             int width;
             int length;
             ...
         }

         public static class Chair {
             String color;
             ChairType chairType;
             ...
         }

         public static class Sofa {
             int price;
             String color;
             ...
         }
    }

这就是在新模式下将不同元素组合在单个.xsd文件中的方法。
3. targetNamespace 是您创建的文件的名称。可以自己找出,当创建一个模式时,targetNamespace 用于在xsd文件中命名。
一旦创建了工件(或.xsd文件),您可以按以下方式在其他项目中使用它:
在Java项目中,您可以使用pom.xml(或build.gradle)文件导入库,如下所示:
    <dependency>
       <groupId>com.furniture</groupId>
       <artifactId>furniture-apis</artifactId>
       <version>1.1.1</version>
    </dependency>

在XML中,你需要使用"import"来引入模式。最初的回答。
    <furniture xmlns="http://furniture.com"/>

=== 附录 ===

澄清 -

  1. xmlns 在Java中既用作package语句,也用作import语句。在.xsd文件中,xmlns充当"package"语句,而在.xml文件中,它充当"import"语句。

注:Original Answer翻译成"最初的回答"

-1

经过使用xmllint进行彻底测试,我认为我在这里找到了明确的解释。请考虑以下模式:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yyyzzz.com"
xmlns:p="http://abced.com"
xmlns:q="http://pqr.com"
xmlns="http://yyyzzz.com">

<xsd:element name="recipe" type="recipeType" />

<xsd:complexType name="recipeType">
    <xsd:simpleContent>
        <xsd:extension base="xsd:string">
        <xsd:attribute name="desc" type="xsd:string"  />
        <xsd:attribute name="archetype" type="xsd:string" />
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>
</xsd:schema>

上面的架构可以验证为以下文档:

<?xml version="1.0"?>

<recipe xmlns="http://yyyzzz.com">
    Deciphering the purpose of targetNamespace
</recipe>

这个方法有效的原因是因为xmlns="http://yyyzzz.com"会自动绑定到模式定义的元素上!这意味着它也绑定到了recipeType元素。
现在,使用相同的XML文档,但稍微修改一下模式,也可以进行验证,请仔细查看差异:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://yyyzzz.com"
xmlns="http://eigenfield.aparicio.com"
xmlns:EGboy="http://yyyzzz.com">

<xsd:element name="recipe" type="EGboy:recipeType" />

<xsd:complexType name="recipeType">
    <xsd:simpleContent>
        <xsd:extension base="xsd:string">
        <xsd:attribute name="desc" type="xsd:string"  />
        <xsd:attribute name="archetype" type="xsd:string" />
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>

</xsd:schema> 

如果其他xmlns丢失了,请忽略它,而是仔细看一下type="EGboy:recipeType"。我们不能再依赖于xmlns,因为它有不同的值,因此我们必须在recipeType前面加上前缀EGboy

XML文档甚至不关心EGboy前缀,这个前缀只是为了让模式引用正确的xmlns(如果有多个)。


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