是否有可能以某种方式定义可以验证此类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 :(
答案 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。