“独特粒子归因”违规

时间:2015-07-30 09:04:25

标签: 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>

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

  

无效。错误 - 第5行,第25行:org.xml.sax.SAXParseException;   lineNumber:5; columnNumber: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>

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

那么,有没有办法使用<xs:group>使我的架构有效,或者我必须展平我的架构(就像我上面提到的解决方案一样)?

更新

以下是XSD应该允许的示例:

允许的最小值:

<Param>
    <RadioAddr>1</RadioAddr>
</Param>

也是合法的:

<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>

1 个答案:

答案 0 :(得分:4)

要击败Unique Particle Attribution违规,您必须允许解析器明确地知道它在语法中的位置,而不必向前看多个元素。

出现当前错误是因为无法知道何时遇到Password元素,解析器是Group1还是Group2,因为IdNumber是可选的。您可以强制使用IdNumber,但这会在Group2Group3之间IdNumber之间产生歧义。然后,您可以尝试使用排序来区分xs:choice组,但之后您会发现元素的可选性会破坏您的努力。您可以删除选项,如果组之间的顺序不同,那么您可以得到答案。

然而,这将是一个相当奇怪的语法。在那一点上,你可能会更好地扁平化,但是你可以通过一个无限制的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> 元素代替:

$('tr.invoicerow').each(function () {

                    var RowProductNames = $(this).find("input.invoiceproduct").val();
                    if (RowProductNames == InvoiceProductName) {

                     var c=parseInt($(this).find("td input.invoicerate").val())+parseInt(USER_INPUTTED_VALUE);
                     $(this).find("td input.invoicerate").val(c);
                    } else {
                        row = "<tr class='invoicerow'><td hidden><input class='dcid' value=" + deliverychallanid + "></td><td><input class='case invoicechkbox' type='checkbox'></td><td><input class='form-control invoiceproduct' id='invoiceproduct_" + rowno + "' value=" + InvoiceProductName + "></td><td><input class='form-control invoiceunit' id='invoiceunit_" + rowno + "' value=" + InvoiceUnit + "></td><td><input class='form-control invoicerate' id='invoicerate_" + rowno + "' value=" + InvoiceRatePerUnit + "></td><td><input class='form-control invoicenos' id='invoicenos_" + rowno + "'value=" + 0 + "></td><td><input class='form-control invoicequantity' id='invoicequantity_" + rowno + "' value=" + 0 + "></td><td><input class='form-control invoicecapacity' id='invoicecapacity_" + rowno + "'value=" + value.Capacity + "></td><td><input class='form-control invoiceamount' id='invoiceamount_" + rowno + "' value=" + Totalamount + "></td></tr>"
                        $('#invoicebody').append(row);
                    }

                });
            }