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

时间:2021-07-28 23:58:49

Is it possible in some way, to define an xsd scheme which could validate such xml:

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

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

Problem is that i havn't find any possibility to define smth like:

问题是我没有找到任何定义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>

But i need to check, that SimpleMessage has no child elements or additional attrs :(

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

3 个解决方案

#1


7  

As earlier answers have already mentioned, you can do this easily enough in XSD 1.0 by using the xsi:type attribute instead of defining a new ItemType attribute with the same functionality.

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

XSD 1.1 includes a construct designed to make it easier to support cases like this one, for people who for whatever reason don't want to use xsi:type this way: conditional type assignment. Essentially it allows an element declaration to have simple sequence of XPath / typename pairs; the XPath expressions are evaluated in sequence and when one evaluates to true, the element is associated with the corresponding type. There are restrictions on the XPaths to prohibit looking ahead into the element's descendants or looking up or out into other parts of the XML document (the first helps keep it possible to know, as soon as a scan encounters a start-tag, which type to use for validating an element; the second helps keep validation context-free), so essentially the tests can only be tests on attribute values. Your example can be written thus:

XSD 1.1包含一个结构,旨在使其更容易支持像这样的情况,对于那些因任何原因不想使用xsi的人:以这种方式输入:条件类型赋值。本质上,它允许元素声明具有简单的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>

The third alternative ensures that one of your expected cases must be encountered, for the element to be valid. If it were omitted here, then if neither of the test expressions were true, the element would be assigned the declared type of item, in this case xs:anyType.

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

#2


5  

XSD expressly prohibits such a case. You must change the element names to be unique (or use xsi:type as xcut says, which amounts to the same thing).

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

As a work-around, you could merge the type definitions SimpleMessType and ComplexMessType into a single type with mixed="true" -- and then disentangle the content you receive in your own code after Schema processing is complete. See the * discussion about XSD schema for recursive XML.

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

#3


0  

You cannot do this using the schema structure you proposed, because the structure violates the XML Schema ambiguity rules.

您不能使用您提出的架构结构来执行此操作,因为该结构违反了XML架构歧义规则。

One potential option for you is to define a super-type, say BaseElement, that is empty, and then sub-types, and use xsi:type to override instead of just a normal type attribute. More information on how that works can be found here.

一个可能的选择是定义一个超类型,比如BaseElement,它是空的,然后是子类型,并使用xsi:type来覆盖而不仅仅是普通的类型属性。有关其工作原理的更多信息,请点击此处。

#1


7  

As earlier answers have already mentioned, you can do this easily enough in XSD 1.0 by using the xsi:type attribute instead of defining a new ItemType attribute with the same functionality.

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

XSD 1.1 includes a construct designed to make it easier to support cases like this one, for people who for whatever reason don't want to use xsi:type this way: conditional type assignment. Essentially it allows an element declaration to have simple sequence of XPath / typename pairs; the XPath expressions are evaluated in sequence and when one evaluates to true, the element is associated with the corresponding type. There are restrictions on the XPaths to prohibit looking ahead into the element's descendants or looking up or out into other parts of the XML document (the first helps keep it possible to know, as soon as a scan encounters a start-tag, which type to use for validating an element; the second helps keep validation context-free), so essentially the tests can only be tests on attribute values. Your example can be written thus:

XSD 1.1包含一个结构,旨在使其更容易支持像这样的情况,对于那些因任何原因不想使用xsi的人:以这种方式输入:条件类型赋值。本质上,它允许元素声明具有简单的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>

The third alternative ensures that one of your expected cases must be encountered, for the element to be valid. If it were omitted here, then if neither of the test expressions were true, the element would be assigned the declared type of item, in this case xs:anyType.

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

#2


5  

XSD expressly prohibits such a case. You must change the element names to be unique (or use xsi:type as xcut says, which amounts to the same thing).

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

As a work-around, you could merge the type definitions SimpleMessType and ComplexMessType into a single type with mixed="true" -- and then disentangle the content you receive in your own code after Schema processing is complete. See the * discussion about XSD schema for recursive XML.

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

#3


0  

You cannot do this using the schema structure you proposed, because the structure violates the XML Schema ambiguity rules.

您不能使用您提出的架构结构来执行此操作,因为该结构违反了XML架构歧义规则。

One potential option for you is to define a super-type, say BaseElement, that is empty, and then sub-types, and use xsi:type to override instead of just a normal type attribute. More information on how that works can be found here.

一个可能的选择是定义一个超类型,比如BaseElement,它是空的,然后是子类型,并使用xsi:type来覆盖而不仅仅是普通的类型属性。有关其工作原理的更多信息,请点击此处。