XSD unique constraint on attribute of sibling elements of a specific type

后端 未结 1 1275
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-17 18:03

I have an XML document structured as Q&A which follows the following format (edited for clarity):


    
        &l         


        
相关标签:
1条回答
  • 2020-12-17 18:56

    Just change the selector to <xs:selector xpath="answer"/> and you'll be fine. In general it is good to avoid XPaths like .//*, if only for performance reasons.

    This is the XML Schema for the XML sample you've provided that I think is working the way you want:

    <?xml version="1.0" encoding="utf-8" ?>
    <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="question" type="questionType">
            <xs:unique name="AnswerIdUnique">
                <xs:selector xpath="answer"/>
                <xs:field xpath="@id"/>
            </xs:unique>
        </xs:element>
        <xs:complexType name="questionType">
            <xs:sequence>
                <xs:element name="answer" type="answerType" minOccurs="2" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="answerType">
            <xs:sequence>
                <xs:element ref="question" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
            <xs:attribute name="id" type="xs:token" use="required"/>
        </xs:complexType>
    </xs:schema>
    

    Your posted XML validates fine with the above; duplicating any sibling answer's id yields a validation error. For example, the following XML:

    <question> 
        <answer id="1"> 
            <question> 
                <answer id="1"/> 
                <answer id="2"/> 
                <answer id="1"/> 
            </question> 
        </answer> 
        <answer id="1"> 
            <question> 
                <answer id="1"/> 
                <answer id="2"/> 
            </question> 
        </answer> 
    </question> 
    

    When validated (in QTAssistant, should be similar to the message in Visual Studio since it is based on the same technology), these are the errors:

    Error occurred while loading [], line 6 position 5
    There is a duplicate key sequence '1' for the 'AnswerIdUnique' key or unique identity constraint.
    Error occurred while loading [], line 9 position 3
    There is a duplicate key sequence '1' for the 'AnswerIdUnique' key or unique identity constraint.
    Document1.xml is invalid.
    

    Below is a screenshot from Visual Studio 2010 showing the above XML validation against the XSD I've posted; while the problems are inadvertently reported as warnings, they are, nonetheless, reported.

    VS2010 showing unique constraint errors

    I've randomly picked an online validator (http://xsdvalidation.utilities-online.info/) and validated the same XML and XSD I've posted; the error is reported as:

    org.xml.sax.SAXParseException: Duplicate unique value [1] declared for identity constraint of element "question".org.xml.sax.SAXParseException: Duplicate unique value [1] declared for identity constraint of element "question".

    One thing you have to pay attention to is when you have a target namespace for your XSD; in that case, it is needed to define an alias for all of the involved namespaces, and use them in your selectors.

    UPDATE: And the XSD with namespaces:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://localhost" xmlns="http://localhost" targetNamespace="http://localhost" elementFormDefault="qualified" attributeFormDefault="unqualified">
        <xs:element name="question" type="questionType">
            <xs:unique name="AnswerIdUnique">
                <xs:selector xpath="tns:answer"/>
                <xs:field xpath="@id"/>
            </xs:unique>
        </xs:element>
        <xs:complexType name="questionType">
            <xs:sequence>
                <xs:element name="answer" type="answerType" minOccurs="2" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="answerType">
            <xs:sequence>
                <xs:element ref="question" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
            <xs:attribute name="id" type="xs:token" use="required"/>
        </xs:complexType>
    </xs:schema>
    

    Please notice the introduction of the tns prefix and the use of it in the selector.

    0 讨论(0)
提交回复
热议问题