"This element is not expected" error: xs:sequence versus xs:all

"This element is not expected" error: xs:sequence versus xs:all

我有一些 XML 我正在为此编写一个验证器工具,以便我们的客户可以测试他们的示例提要,但我对 XSD 还很陌生。我已经到了根据 cookie cutter 示例正确验证所有内容的地步,所以我想抛出一些其他场景。我想出的第一个是在基本节点中有不同顺序的元素。

示例: 我正在使用以下 complexType 来验证每个事务节点

<xs:complexType name="transactionType">
    <xs:sequence>
        <xs:element type="xs:string" name="id"/>
        <xs:element type="xs:string" name="type"/>
        <xs:element type="xs:float" name="amount"/>
        <xs:element type="xs:string" name="description"/>
        <xs:element type="xs:string" name="status"/>
        <xs:choice>
            <xs:element name="transacted_on" type="xs:date"/>
            <xs:element name="transacted_at" type="xs:date"/>
        </xs:choice>
        <xs:choice>
            <xs:element name="posted_on" type="xs:date"/>
            <xs:element name="posted_at" type="xs:date"/>
        </xs:choice>
    </xs:sequence>
</xs:complexType>

以下示例节点的顺序正确,因此可以正确验证

<transaction>
    <id>20150617-123456</id>
    <type>DEBIT</type>
    <amount>17.44</amount>
    <description>Debit Card: CAFE  06/16/15</description>
    <status>POSTED</status>
    <transacted_on>2015-06-17</transacted_on>
    <posted_on>2015-06-16</posted_on>
</transaction>

但我希望能够以任何顺序排列元素。所以像下面这样的东西将正确验证。这个想法是所有元素都存在并且可以按任何顺序排列。

<transactions>
    <transaction>
        <amount>17.44</amount>
        <id>20150617-123456</id>
        <type>DEBIT</type>
        <description>Debit Card: CAFE  06/16/15</description>
        <status>POSTED</status>
        <transacted_on>2015-06-17</transacted_on>
        <posted_on>2015-06-16</posted_on>
    </transaction>
    <transaction>
        <id>20150617-123456</id>
        <type>CREDIT</type>
        <amount>17.44</amount>
        <description>VISA Card: payment</description>
        <status>POSTED</status>
        <transacted_on>2015-06-17</transacted_on>
        <posted_on>2015-06-16</posted_on>
    </transaction>
</transactions>

我做了一些研究,很快就被指向使用 xs:all 元素,它应该完全符合我的要求。所以我更改了我的架构以使用 xs:all 而不是 xs:sequence.

<xs:complexType name="transactionType">
    <xs:all>
        <xs:element type="xs:string" name="id"/>
        <xs:element type="xs:string" name="type"/>
        <xs:element type="xs:float" name="amount"/>
        <xs:element type="xs:string" name="description"/>
        <xs:element type="xs:string" name="status"/>
        <xs:choice>
            <xs:element name="transacted_on" type="xs:date"/>
            <xs:element name="transacted_at" type="xs:date"/>
        </xs:choice>
        <xs:choice>
            <xs:element name="posted_on" type="xs:date"/>
            <xs:element name="posted_at" type="xs:date"/>
        </xs:choice>
    </xs:all>
</xs:complexType>

当我 运行 进行此更改后进行验证时,我仍然收到错误消息:

This element is not expected. Expected is ( id ).

我在这里错过了什么?

XML 架构不允许 xs:choice 成为 xs:all 的子级。

解决方法:

  1. xs:choice 个元素周围添加一个包装器元素。
  2. 放弃 xs:all 并通过 xs:sequence 以固定顺序生活。

我建议在实践中 xs:sequence 工作正常并且避免了这个问题以及 xs:all 经常出现的其他问题,包括违反 Unique Particle Principle.