How to use unique and keyref properly in XML schema?

本小妞迷上赌 提交于 2019-12-13 13:39:12

问题


I have this XML schema but I don't know how to complete it in order to achieve what I need. I searched a lot online about unique and keyref usage, but all I can find are basic examples.

This is my schema:

    <xs:element name="access" type="myaccess" />

    <xs:complexType name="myaccess">
        <xs:sequence>
            <xs:element name="user" type="myuser" minOccurs="0" maxOccurs="unbounded">
                <xs:unique name="u_idunique">
                    <xs:selector xpath="user" />
                    <xs:field xpath="@id" />
                </xs:unique>
            </xs:element>
            <xs:element name="authorization" type="myauthorization" minOccurs="0" maxOccurs="unbounded">

            <!-- HERE I WANT A KEYREF TO id attribute of user element -->
            <!-- HERE I WANT A KEYREF TO id attribute of building element OR door element -->

            </xs:element>
            <xs:element name="building" type="mybuilding" minOccurs="0" maxOccurs="unbounded" >
                <!-- I DON'T KNOW HOW TO SPECIFY THAT id of building, id of door and id of gate are in the same scope -->
                <xs:unique name="b_idunique">
                    <xs:selector xpath="building" />
                    <xs:field xpath="@id" />
                </xs:unique>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="myuser">
        <xs:attribute name="id" type="my_id" use="required" />
        <xs:attribute name="name" type="xs:string" use="required" />
        <xs:attribute name="phone" type="my_string_numeric" use="required" />
    </xs:complexType>

    <xs:complexType name="mybuilding">
        <xs:sequence>
            <xs:element name="door" type="mydoor" minOccurs="0" maxOccurs="unbounded">
                <!-- I DON'T KNOW HOW TO SPECIFY THAT id of building, id of door and id of gate are in the same scope -->
                <xs:unique name="d_idunique">
                    <xs:selector xpath="door" />
                    <xs:field xpath="@id" />
                </xs:unique>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="my_id" use="required" />
        <xs:attribute name="name" type="xs:string" use="required" />
        <xs:attribute name="country" type="xs:string" use="required" />
    </xs:complexType>

    <xs:complexType name="mydoor">
        <xs:sequence>
            <xs:element name="gate" type="mygate" maxOccurs="unbounded">
                <!-- I DON'T KNOW HOW TO SPECIFY THAT id of building, id of door and id of gate are in the same scope -->
                <xs:unique name="g_idunique">
                    <xs:selector xpath="gate" />
                    <xs:field xpath="@id" />
                </xs:unique>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="my_id" use="required" />
        <xs:attribute name="address" type="xs:string" use="required" />
        <xs:attribute name="status" type="mystatus" default="DISABLED" />
    </xs:complexType>

    <xs:complexType name="mygate">
        <xs:attribute name="id" type="my_id" use="required" />
        <xs:attribute name="type" type="mytype" use="required" />
        <xs:attribute name="status" type="mystatus" default="DISABLED" />
    </xs:complexType>

    <xs:complexType name="myauthorization">
        <xs:sequence>
            <xs:element name="validityperiod" type="myvalidityperiod" />
        </xs:sequence>
        <xs:attribute name="idu" type="my_id" use="required" />
        <xs:attribute name="idao" type="my_id" use="required" />
    </xs:complexType>

    <!-- OMITTED USELESS PART OF THE SCHEMA -->

</xs:schema>

I have two problems:

  • I don't know how to specify that the id field of building, the id field of door and the id field of gate are in the same scope and I can't have 2 id equals (two building can't have the same id, but also a door and a building can't share the same id)
  • I don't know how to use correctly the keyref element.
    1. I'd like that idu filed of authorization element is an id that is present in one of the user elements (see [*] below).
    2. I'd like that the idao field of authorization element is an id that is present in one of the building elements OR one of the door elements.

[*] I tried to write this, but it's not working:

<xs:keyref name="useridkeyref" refer="u_idunique">
    <xs:selector xpath="authorization" />   
    <xs:field xpath="@idu" />
</xs:keyref>

I know this is not a short question and I thanks everyone in advance for reading it. I hope I can get some help. Thank you!


回答1:


Unique constraints and keys are scoped at the element level - you need to put the constraint not inside each individual element, but inside the access element that is a common ancestor of them all.

<xs:element name="access" type="myaccess">
  <xs:key name="user_id">
    <xs:selector xpath="user" />
    <xs:field xpath="@id" />
  </xs:key>
  <xs:key name="access_id">
    <xs:selector xpath="building | building/door | building/door/gate" />
    <xs:field xpath="@id" />
  </xs:key>
  <xs:keyref name="user_ref" refer="user_id">
    <xs:selector xpath="authorization" />
    <xs:field xpath="@idu" />
  </xs:keyref>
  <xs:keyref name="access_ref" refer="access_id">
    <xs:selector xpath="authorization" />
    <xs:field xpath="@idao" />
  </xs:keyref>
</xs:element>



回答2:


In my case I also had to declare and use an explicit namespace for the selectors. Use the solution from Ian Roberts and adapt these attributes:

<xs:schema ...
        xmlns:mc="http://mycompany.com"
...
>
...    
    <xs:selector xpath="mc:user" />      
  ...      
    <xs:selector xpath="mc:authorization" />
  ...
 </xs:element>

See also here https://stackoverflow.com/a/22353694/1909531



来源:https://stackoverflow.com/questions/20662664/how-to-use-unique-and-keyref-properly-in-xml-schema

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!