如何在XML模式中正确使用unique和keyref?

时间:2013-12-18 15:55:00

标签: xml xsd unique keyref

我有这个XML架构,但我不知道如何完成它以实现我需要的东西。我在网上搜索了很多关于unique和keyref的用法,但我能找到的只是基本的例子。

这是我的架构:

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

我有两个问题:

  • 我不知道如何指定建筑物的id字段,门的id字段和门的id字段在同一范围内我不能有2个id等于(两个建筑物不能有相同的id,但也是一个门和一个建筑物不能共享相同的id)。
  • 我不知道如何正确使用keyref元素。
    1. 我希望授权元素的idu字段是其中一个用户元素中的id(参见下面的[*])。
    2. 我希望授权元素的idao字段是一个id,它存在于其中一个建筑元素或其中一个门元素中。

[*]我试着写这个,但它不起作用:

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

我知道这不是一个简短的问题,我提前感谢大家阅读。我希望我能得到一些帮助。谢谢!

2 个答案:

答案 0 :(得分:4)

唯一约束和键的范围是element级别 - 您需要将约束放在每个单独的元素内部,而不是放在access元素中,它们是所有元素的共同祖先。

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

答案 1 :(得分:0)

在我的情况下,我还必须为选择器声明并使用显式命名空间。使用Ian Roberts中的解决方案并调整这些属性:

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

另见https://stackoverflow.com/a/22353694/1909531