“独特粒子属性”违规

Spo*_*ted 6 xml validation xsd

我编写了以下(简化的)模式来验证我收到的一些 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

    <xs:element name="Param">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="RadioAddr" type="xs:string" />
                <xs:element name="DataToRead" type="xs:integer" minOccurs="0" maxOccurs="1" />
                <xs:choice minOccurs="0" maxOccurs="1">
                    <xs:group ref="Group1" />
                    <xs:group ref="Group2" />
                    <xs:group ref="Group3" />
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:group name="Group1">
        <xs:sequence>
            <xs:element ref="Password" />
            <xs:element name="RadioActivated" type="xs:integer" minOccurs="0" maxOccurs="1" />
            <xs:element ref="IdNumber" minOccurs="0" maxOccurs="1" />
            <xs:element ref="AdjustClock" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
    </xs:group>

    <xs:group name="Group2">
        <xs:sequence>
            <xs:element ref="IdNumber" minOccurs="0" maxOccurs="1" />
            <xs:element ref="Password" />
            <xs:element ref="AdjustClock" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
    </xs:group>

    <xs:group name="Group3">
        <xs:sequence>
            <xs:element ref="IdNumber" minOccurs="0" maxOccurs="1" />
            <!-- No password here -->
            <xs:element ref="AdjustClock" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
    </xs:group>

    <xs:element name="Password" type="xs:string" />
    <xs:element name="IdNumber" type="xs:integer" />
    <xs:element name="AdjustClock" type="xs:integer" />

</xs:schema>
Run Code Online (Sandbox Code Playgroud)

验证此架构时,我收到以下错误消息:

无效。错误 - 第 5、25 行:org.xml.sax.SAXParseException;行号:5;列数:25;cos-nonambig:密码和密码(或其替换组中的元素)违反“唯一粒子属性”。在针对此模式进行验证期间,会为这两个粒子创建歧义。

我完全理解这种歧义,但我找不到使我的模式有效的解决方案。

一个可能的解决方案是做类似的事情

<xs:element name="Param>
    <xs:complexType>
        <xs:choice maxOccurs="unbounded">
            <!-- put all the possible elements here -->
        </xs:choice>
    </xs:complexType>
</xs:element>
Run Code Online (Sandbox Code Playgroud)

但是我对这个解决方案的问题是我失去了对我进一步有用的一层抽象(组)(我使用这个模式用 JAXB 生成 Java 类)。

那么,有没有办法使我的模式有效使用,<xs:group>或者我是否必须展平我的模式(如我上面提到的解决方案)?

更新

以下是 XSD 应允许的示例:

允许的最低限度:

<Param>
    <RadioAddr>1</RadioAddr>
</Param>
Run Code Online (Sandbox Code Playgroud)

也是合法的:

<Param>
    <RadioAddr>1</RadioAddr>
    <Password>1234</Password>
</Param>

<Param>
    <RadioAddr>1</RadioAddr>
    <Password>1234</Password>
    <RadioActivated>1</RadioActivated>
    <IdNumber>12345678</IdNumber>
</Param>

<Param>
    <RadioAddr>1</RadioAddr>
    <IdNumber>12345678</IdNumber>
    <Password>1234</Password>
</Param>
Run Code Online (Sandbox Code Playgroud)

kjh*_*hes 5

为了克服唯一粒子属性违规,您必须允许解析器明确知道它在语法中的位置,而不必提前查看多个元素。

当前错误的出现是因为在遇到Password元素时无法知道解析器是 inGroup1还是Group2因为IdNumber是可选的。你可能会做出IdNumber强制替代,但这之间产生歧义Group2Group3超过IdNumber。然后,您可能会尝试使用排序来区xs:choice分组,但随后您会发现元素的可选性使您的努力落空。您可能会删除可选性,如果可以接受组之间的不同排序,那么您可能会有答案。

然而,这将是一个相当奇怪的语法。在这一点上,您可能会像您提到的那样更好地展平,但与其使用 unbounded xs:choice,这将允许其元素的任意和无界重复,您可以通过一个简单xs:sequence的元素来保留一些出现约束:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

  <xs:element name="Param">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="RadioAddr" type="xs:string" />
        <xs:element name="DataToRead" type="xs:integer" minOccurs="0" maxOccurs="1" />
        <xs:element name="RadioActivated" type="xs:integer" minOccurs="0" maxOccurs="1" />
        <xs:element ref="IdNumber" minOccurs="0" maxOccurs="1" />
        <xs:element ref="Password" minOccurs="0"/>
        <xs:element ref="AdjustClock" minOccurs="0" maxOccurs="1" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="Password" type="xs:string" />
  <xs:element name="IdNumber" type="xs:integer" />
  <xs:element name="AdjustClock" type="xs:integer" />

</xs:schema>
Run Code Online (Sandbox Code Playgroud)