如何在xsd:choice元素中定义几个具有相同名称但不同类型的元素?

时间:2010-03-18 09:59:38

标签: xml xsd

是否有可能以某种方式定义可以验证此类xml的xsd方案:

<item_list>
  <item ItemType="SimpleMessage" Caption="Simplest message"/>
  <item ItemType="ComplexMessage" SomeAttr="value">
    <item_data>some text</item_data>
  </item>
</item_list>

问题是我没有找到任何定义smth的可能性:

  <xsd:element name="Items">
      <xsd:complexType>
        <xsd:choice>
          <xsd:element name="item" type="SimpleMessType"/>
          <xsd:element name="item" type="ComplexMessType"/>
        </xsd:choice>
      </xsd:complexType>
  </xsd:element>

但我需要检查一下,SimpleMessage没有子元素或其他attrs :(

3 个答案:

答案 0 :(得分:7)

正如之前的答案已经提到的,您可以使用xsi:type属性在XSD 1.0中轻松完成此操作,而不是定义具有相同功能的新ItemType属性。

XSD 1.1包含一个旨在使其更容易支持此类案例的构造,适用于因任何原因不希望以这种方式使用xsi:type的人:条件类型赋值。本质上,它允许元素声明具有简单的XPath / typename对序列; XPath表达式按顺序计算,当一个计算结果为true时,该元素与相应的类型相关联。 XPath有限制禁止向前看元素的后代或向上或向外查看XML文档的其他部分(第一个有助于在扫描遇到开始标记时保持可能知道,哪个类型为用于验证元素;第二个用于保持验证无上下文),因此基本上测试只能是对属性值的测试。你的例子可以写成:

<xs:element name="item">
  <xs:alternative test="@ItemType='SimpleMessage'" type="SimpleMessType"/>
  <xs:alternative test="@ItemType='SimpleMessage'" type="ComplexMessType"/>
  <xs:alternative type="xs:error"/>
</xs:element>

第三种选择确保必须遇到您的一个预期案例,以使该元素有效。如果这里省略了,那么如果两个测试表达式都不为真,那么将为元素分配声明的item类型,在本例中为xs:anyType

答案 1 :(得分:5)

XSD明确prohibits such a case。您必须将元素名称更改为唯一(或使用 xsi:type ,如xcut所述,这相当于相同的事情。)

作为一种解决方法,您可以将类型定义 SimpleMessType ComplexMessType 合并为一个类型,其中 mixed =“true” - - 然后在架构处理完成后解开您在自己的代码中收到的内容。请参阅有关XSD schema for recursive XML的stackoverflow讨论。

答案 2 :(得分:0)

您无法使用您提议的架构结构执行此操作,因为该结构违反了XML架构模糊规则。

一个潜在的选择是定义一个超类型,比如BaseElement,它是空的,然后是子类型,并使用xsi:type来覆盖而不仅仅是一个普通的{{1}属性。有关其工作原理的更多信息,请参见here