XSD模式的属性,用于裁判其他元素属性的唯一标识

时间:2016-04-20 19:43:25

标签: xml xsd

我有以下XML代码:

<?xml version="1.0" encoding="UTF-8"?>
<!--<!DOCTYPE bank SYSTEM "bank.dtd">-->
<bank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="bank.xsd">

  <accounts>
    <savings_accounts>
      <savings_account id="a1" interest="0.03">
        <balance>2500</balance>
      </savings_account>

      <savings_account id="a2" interest="0.03">
        <balance>15075</balance>
      </savings_account>
    </savings_accounts>

    <checking_accounts>
      <checking_account id="a3">
        <balance>4025</balance>
      </checking_account>
      <checking_account id="a4">
        <balance>-125</balance>
      </checking_account>
      <checking_account id="a5">
        <balance>325</balance>
      </checking_account>  
    </checking_accounts>
  </accounts>

  <customers>
    <customer id="c1">
      <name>Ben Richerdson</name>
      <address>Park Drive 2</address>
    </customer>
    <customer id="c2">
      <name>Marc Wretcher</name>
      <address>Mill Drive 75</address>
    </customer>
    <customer id="c3">
      <name>Angel Steady</name>
      <address>Lake Sight 15</address>
    </customer>
  </customers>


  <customer_accounts>
    <customer_account c_id="c1" ac_id="a2"/>
    <customer_account c_id="c1" ac_id="a3"/>
    <customer_account c_id="c2" ac_id="a4"/>
    <customer_account c_id="c3" ac_id="a1"/>
    <customer_account c_id="c3" ac_id="a5"/>
  </customer_accounts>
</bank>

我还为XML编写了适当的XSD架构,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="bank">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="accounts">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="savings_accounts">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="savings_account" maxOccurs="unbounded">
                                            <xs:complexType>
                                                <xs:sequence>
                                                    <xs:element name="balance">
                                                        <xs:simpleType>
                                                            <xs:restriction base="xs:double">
                                                              <xs:minInclusive value="-5000"/>
                                                            </xs:restriction>
                                                        </xs:simpleType>
                                                    </xs:element>
                                                </xs:sequence>
                                                <xs:attribute name="id" type="xs:string" use="required"/>
                                                <xs:attribute name="interest" type="xs:double" use="required"/>
                                            </xs:complexType>
                                        </xs:element>
                                    </xs:sequence>
                                </xs:complexType>
                                <xs:unique name="onesavings_accountforEachid">
                                    <xs:selector xpath="xs:savings_account"/>
                                    <xs:field xpath="@id"/>
                                </xs:unique>
                            </xs:element>
                            <xs:element name="checking_accounts">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="checking_account" maxOccurs="unbounded">
                                            <xs:complexType>
                                                <xs:sequence>
                                                    <xs:element name="balance">
                                                        <xs:simpleType>
                                                            <xs:restriction base="xs:double">
                                                                <xs:minInclusive value="-5000"/>
                                                            </xs:restriction>
                                                        </xs:simpleType>
                                                    </xs:element>
                                                </xs:sequence>
                                                <xs:attribute name="id" type="xs:string" use="required"/>
                                            </xs:complexType>
                                        </xs:element>
                                    </xs:sequence>
                                </xs:complexType>
                                <xs:unique name="onechecking_accountforEachid">
                                    <xs:selector xpath="xs:checking_account"/>
                                    <xs:field xpath="@id"/>
                                </xs:unique>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="customers">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="customer" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="name" type="xs:string"/>
                                        <xs:element name="address" type="xs:string"/>
                                    </xs:sequence>
                                    <xs:attribute name="id" type="xs:string" use="required"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                    <xs:unique name="onecustomerforEachid">
                        <xs:selector xpath="xs:customer"/>
                        <xs:field xpath="@id"/>
                    </xs:unique>
                </xs:element>
                <xs:element name="customer_accounts">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="customer_account" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:attribute name="c_id" type="xs:string" use="required"/>
                                    <xs:attribute name="ac_id" type="xs:string" use="required"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

所以我的问题是,如何将customer_account的c_id =“c1”和ac_id =“a2”引用到帐户中定义的相应ID。 'c_id'表示客户,'ac_id'表示帐户。

我认为可以做同样的事情,但我必须添加id作为元素,并将它们定义为私钥和后来的外键。

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

我认为你正在寻找一种方法来确保

  • 对于属性customer_account/@c_id的每个值,只有一个客户将该值作为其@id属性的值。
  • 对于属性customer_account/@ac_id的每个值,只有一个帐户(支票或储蓄帐户),该值为其@id属性的值。
  • 没有两个客户拥有相同的@id值。
  • 没有两个储蓄账户具有相同的@id值。
  • 没有两个支票帐户具有相同的@id值。

最后三个约束已经包含在元素uniquesavings_accountschecking_accounts中的customers元素中。

如果这是对你想要达到的目标的正确理解,那么:

  • 如果您想确保customer_account/@ac_id的任何值只与一个帐户匹配,则需要确保没有支票帐户与任何储蓄帐户具有相同的ID。现在,您允许储蓄和支票帐户共享ID。您需要在unique上添加涵盖两种帐户形式的key(或accounts)约束。以下应该这样做:

    <xs:unique name="oneaccountforEachid">
      <xs:selector xpath="*/*"/>
      <xs:field xpath="@id"/>
    </xs:unique>
    
  • 您希望定义两个keyref元素,指定元素customer_account上的c_id和a_id属性成功引用客户和帐户的键。如果您愿意,可以使用customer_account元素:

    <xs:keyref refer="onecustomerforEachid" 
               name="ca_customer_pointer" >
      <xs:selector xpath="."/>
      <xs:field xpath="@c_id"/>
    </xs:keyref>
    <xs:keyref refer="oneaccountforEachid" 
               name="ca_account_pointer">
      <xs:selector xpath="."/>
      <xs:field xpath="@ac_id"/>
    </xs:keyref>
    

    对我自己说,如果所有身份约束都在bank元素上,我认为架构可能会更清晰:

    <xs:element name="bank" type="bank">
      <xs:unique name="account_id_unique">
        <xs:selector xpath="accounts/*/*"/>
        <xs:field xpath="@id"/>
      </xs:unique>
      <xs:unique name="customer_id_unique">
        <xs:selector xpath="customers/customer"/>
        <xs:field xpath="@id"/>
      </xs:unique>
      <xs:keyref name="ca_customer_id"
                 refer="customer_id_unique">
        <xs:selector 
          xpath="customer_accounts/customer_account"/>
        <xs:field xpath="@c_id"/>
      </xs:keyref>
      <xs:keyref name="ca_account_id" 
                 refer="account_id_unique">
        <xs:selector 
          xpath="customer_accounts/customer_account"/>
        <xs:field xpath="@ac_id"/>
      </xs:keyref>
    </xs:element>  
    

此外,您可能希望将现有的unique元素更改为key元素,以强调每个客户和帐户都需要具有@id。差异的一个简短描述是:您拥有的unique约束(或显示的那些)表示如果指定元素上出现@id属性,则其值必须在这些元素的@id值中唯一。 key约束需要相同的内容,并且还要求所有相关元素实际上具有 @id属性。由于您已经需要@id属性(通过其声明),因此在这种情况下两者具有相同的效果。