为什么我们需要targetNamespace?
我想了解在XML Schema和WSDL中使用的targetNamespace的用途。 事实上,为了简单起见,我们将这个问题限制在XML Schema中。
我觉得我完全理解(简单)XML命名空间的概念。 按照惯例,我们使用URI / URL,但是我们可以使用任何string,然后我们将其分配给前缀以供XML节点和属性重用,或者简单地作为当前范围的默认命名空间。 到现在为止还挺好 ?
现在inputXML Schema。 出于某种原因,XML Schema的发明者认为简单命名空间的概念是不够的,他们不得不引入目标命名空间。 我的问题是:目标命名空间引入的常规XML命名空间无法提供什么显着的好处? 如果XML文档通过schemaLocation或import语句引用xsd文档,则无论哪种情况,我都会将path引导到正在引用的实际xsd文档。 这就是我想要引用的Schema的唯一定义。 另外,如果我想将此Schema绑定到引用文档中的特定命名空间,为什么我必须复制在我引用的XML Schema中已经定义的精确targetNamespace? 为什么我不能简单地重新定义这个命名空间,但是我想在这个命名空间将被用来引用那个特定的XML Schema文档,我想参考的XML文档?
更新:
举一个例子,如果我在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需要定义一个名为“http://contoso.com/schemas/People”的targetNamespace? 为什么我们需要xsd文件中的targetNamespace定义呢? 在我看来,您必须从schemaLocation的名称空间部分获得的所有内容已包含在XML实例文档中。 在xsd文档中强制使用相同的值来实现targetNamespace的好处是什么?
跟进问题给保罗的答案:
你能给我一个具体的例子,这样的xsd元素名称之间的“冲突”变得明显,这将解释需要targetNamespace?
好的,这里是试图回答我自己的问题。 让我知道,如果它似乎与你相干。 看看由Paul帮助我链接的页面上的例子。
如果我们以上述原始问题中的XML实例为例,我们有两个参考车辆元素的定义。 一个在XML实例文档本身是显式的,可见的,但是我们也必须设想person.xsd XML Schema再次引用同一个车辆定义,作为人员允许的子元素。 如果我们要使用普通的命名空间,每个文档都可以为车辆定义自己的命名空间,那么我们如何知道XML实例正在引用与person.xsd相同的XML Schema定义? 唯一的办法是强制执行一个比原来简单的命名空间更严格的命名空间概念,而且这个概念必须在多个文档中以完全相同的方式编写。
如果我不是在平板电脑上写这个,我会提供一个代码示例,但是在这里我只是试图描述我想要的例子。
想象一下,我们有一个车辆元素的两个不同的XML模式定义。 location1 / vehicles.xsd将包含validation来自该post问题的示例的定义(包含颜色,轮子和座位子元素),而location2 / vehicles.xsd将包含车辆元素的完全不同的定义,具有子元素的年份,型号和音量)。 现在,如果XML实例文档引用location1 Schema(如上例所示),但person.xsd表示person元素可以包含位置2 Schema中定义的车辆子元素,则不包含该概念一个targetNamespace的XML实例将被validation,即使它显然没有合适的车辆作为其person元素的子元素。
目标命名空间然后帮助我们确保,如果两个不同的文档引用相同的第三个XML Schema,他们都在引用同一个Schema,而不仅仅是一个包含相似但不相同的元素的Schema。 。
这有任何意义吗 ?
你似乎在正确的轨道上。 我会在这里提出几点看法,可能会有所帮助。
- 在实例文档中,您使用XML名称空间来标识元素或属性所在的名称空间。
- 在模式文档中,声明将出现在实例中的元素和属性。 他们声明了什么名字空间? 这是targetNamespace的用途。
- 模式文档位置和名称空间不是一回事。 具有相同targetNamespace的多个.xsd文档是相当常见的。 (他们可能包括也可能不包括对方,但通常会包括对方。)
- 实例文档并不总是有一个xsi:schemaLocation元素来告诉parsing器在哪里定位模式。 可以使用各种方法来告诉parsing器在何处定位相关的模式文档。 XSD可能位于本地磁盘或某个Web地址,这不应该影响其中元素的名称空间。
- xsi:schemaLocation是一个提示。 parsing器可以在别处find给定名称空间的模式,这意味着他们必须能够知道模式的名称空间。
- 工具(如数据绑定工具)将预编译模式并生成识别有效文档的代码。 这些必须能够知道声明的元素的名称空间。
我认为你所假设的是,实例文档可以使用xsi:schemaLocation来指定某些模式文档中声明的元素和属性的名称空间。 这是行不通的。 首先,parsing器可以定位除列出的其他模式文档,并且需要知道它们是什么名称空间。 另一方面,它会使模式的推理变得困难或不可能:你将无法查看模式并知道所有内容所属的命名空间,因为这个决定将被推迟到实例写入之前。
问:“按照惯例,我们使用URI / URL,但是我们可以使用任何string,然后我们将其分配给前缀以供XML节点和属性重用,或者简单地作为手头范围的默认命名空间。
答:是的,确切的。
问:“由于某种原因,XML Schema的发明者认为简单命名空间的概念是不够的,他们不得不引入目标命名空间。
答: http : //www.liquid-technologies.com/Tutorials/XmlSchemas/XsdTutorial_04.aspx
将模式分解成多个文件可以有几个优点。 您可以创build可在多个项目中使用的可重用定义。 它们使得定义更容易阅读和更新,因为它们将模式分解成更简单的小单元。
…
这一切都没有命名空间的正常工作,但如果不同的团队开始在不同的文件上工作,那么你有名称冲突的可能性,并且定义来自哪里并不总是显而易见的。 解决scheme是将每个模式文件的定义放在不同的名称空间中。
澄清:
-
XML Schemas的主要目的是声明“词汇表”。
-
这些词汇表可以通过在targetNamespace属性中指定的名称空间来标识。
-
Schema(一个XML文档)可以有一个“名字空间”。 文档描述的“词汇”可以有一个“targetNamespace”。
-
就像XML Schema提供比SGML DTD(XML的原始架构师认为DTD就足够了)更高的抽象层次,XML Schema“targetNamespaces”提供了对“简单名称空间”的抽象级别。
“希望有所帮助
我认为同时查看实例文档和模式文档有助于理解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(别名或别名)就像来宾上的名称标签。 只要你有客人名单(奇迹般地包括他们的国家签发的身份证复印件),每当你遇到一个人,你可以validation他们的身份。 如果遇到有人佩戴的名称与所附参数不匹配,则可能会吓坏(即抛出错误)。
使用模式/实例,您可以:
架构:
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旁边挂出来,或者P只能在V存在的情况下挂出来。 在这种情况下,当V在那里时,P必须挂起,但是如果没有A,那么V可以在任何他们想要的地方移动。
通过这种方式,模式可以非常灵活,定义了所需的任何数据结构,并且能够跟踪任何给定元素的名称空间(默认或前缀)与TNS及相关模式的匹配。
我不清楚你到底在问什么。 很显然,一个模式可以在许多不同的命名空间中包含组件的定义,并且必须有某种方式来表示“这是命名空间N中的元素E的声明”。 XSD的devise者selectdevise语言,以使一个模式文档中的所有声明属于同一个名称空间,称为模块的目标名称空间。 它可能包装不同,但差异将是非常肤浅的。 您认为将模块与命名空间alignment的决定是什么错误?