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

Nik*_*nko 14 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>
Run Code Online (Sandbox Code Playgroud)

问题是我没有找到任何定义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>
Run Code Online (Sandbox Code Playgroud)

但我需要检查,SimpleMessage没有子元素或额外的attrs :(

C. *_*een 7

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

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>
Run Code Online (Sandbox Code Playgroud)

第三种方法确保必须遇到您的一个预期案例,以使该元素有效.如果在此省略,那么如果两个测试表达式都不为真,则item在这种情况下将为元素分配声明的类型xs:anyType.


WRe*_*ach 5

XSD明确禁止此类案件.您必须将元素名称更改为唯一(或使用xsi:类型,xcut所示,这相当于相同的事情).

作为解决方法,您可以将类型定义SimpleMessTypeComplexMessType合并为具有mixed ="true"的单个类型- 然后在Schema处理完成后解开您在自己的代码中收到的内容.请参阅有关递归XML的XSD架构的stackoverflow讨论.


xcu*_*cut 0

您无法使用您建议的架构结构来执行此操作,因为该结构违反了 XML 架构歧义规则。

您的一个潜在选择是定义一个超类型(例如BaseElement,空的),然后定义子类型,并使用xsi:type来覆盖 而不仅仅是普通type属性。有关其工作原理的更多信息可以在此处找到。