使用其他命名空间中的元素的XSD

24

我有两个XSD文件,它们定义了不同的文档。假设A.xsd定义一个名为ElementA的元素作为根元素,并具有一些复杂规则。现在B.xsd定义了一个元素ElementB,该元素应在某个地方使用ElementA

例如,我希望ElementB的XML文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ElementB xmlns="http://example.com/namespace/for/ElementB">
  <foo>Bla</foo>
  <bar>Blub</bar>
  <ElementA xmlns="http://example.com/namespace/for/ElementA">
    <!-- ... -->
  </ElementA>
</ElementB>

那么B.xsd可能看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://example.com/namespace/for/ElementB" targetNamespace="http://example.com/namespace/for/ElementB" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="ElementB">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="foo" type="xs:string" />
        <xs:element name="bar" type="xs:string" />

        <!-- And now I want to include ElementA somehow -->
        <xs:element name="ElementA" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
问题在于我不想将B.xsdElementA的规范克隆一遍,因为还有一些文档只有ElementA作为根元素(即ElementB是某种容器文档)。
那么,如何在完全基于已存在的XSD上允许在ElementB中使用ElementA呢?
2个回答

40

实际上,有两种不同的方式来组成XML Schema文档:<xs:import><xs:include>。当包含文档的命名空间与被引用的命名空间相同时,应使用xs:include,因此这并不是您要寻找的内容。当您需要引用被引用模式中的所有(或子集)元素,并且它们在不同的目标命名空间中时,xs:import更适合您的情况。关于差异在这里有一个问题:What's the difference between xsd:include and xsd:import?

无论如何,回到这个具体问题。您可能需要像这样的东西:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema 
    xmlns="http://example.com/namespace/for/ElementB"
    targetNamespace="http://example.com/namespace/for/ElementB"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    xmlns:ea="http://example.com/namespace/for/ElementA">
 <xs:import namespace="http://example.com/namespace/for/ElementA" schemaLocation="A.xsd" /> 
 <xs:element name="ElementB">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="foo" type="xs:string" />
    <xs:element name="bar" type="xs:string" />
    <!-- This introduces a element named ElementA that uses the ComplexType ea:ElementA defined in A.xsd -->
    <xs:element name="ElementA" type="ea:ElementA" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

尽管您需要A.xsd来创建ElementA的复杂类型,以便在B.xsd中使用,如所示。

这篇文章提供了一些很好的信息和例子,并包括了对一些不同组合策略的讨论:http://www.xfront.com/ZeroOneOrManyNamespaces.html


谢谢,看起来很不错,我会试一下。不过有一个问题,ea: 命名空间前缀是从哪里来的?还是这是 A.xsd 中类型定义的名称? - poke
只需在代码窗口向右滚动 - 它被引用为xs:schema元素中的最后一个属性:xmlns:ea="http://example.com/namespace/for/ElementA"。您可以为其指定任何前缀,就像默认目标命名空间一样(尽管按照惯例,每个人都选择xsxsd)。 - daveaglick
哦,我没有往下滚动那么远,错过了那个,抱歉 xD 还有谢谢你的帮助,我会尽快尝试并发布我的结果 :) - poke
@somedave:我也处于类似的情况。但我的问题是,elementB没有命名空间声明,而只有elementA有一个命名空间声明。那么我应该如何包含它呢?此外,elementA没有xsd。唯一需要检查的是,如果elementA包含该命名空间声明。 - Ashwin
如果ElementA有一个名为Bazz的子元素,则验证库会在该元素上给出错误提示:“元素'Bazz':不应存在此元素”。这是什么原因呢? - Jawaid
A.xsd应该放在什么位置?在我的情况下,B.xsd试图导入A.xsd,但找不到A.XSD。 - Sai Ram Reddy

1
你可以使用 <xsd:import> 标签来导入另一个命名空间下的模式。

3
你能给我一个示例来说明如何在我的例子中使用它吗?你的链接并没有真正解释那个。 - poke

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