XSD 模式的属性来引用其他元素属性的唯一性

Attributes of XSD schema to referee unique ides of other element attributes

我有以下 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>

所以我的问题是,如何将 c_id="c1" 和 customer_account 的 c_id="a2" 引用到适当的 ID 作为在帐户中定义。 'c_id' 指客户,'ac_id' 指帐户。

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

感谢您的帮助!

我想你是在寻求一种方法来确保

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

您在元素 savings_accountschecking_accountscustomers.

中包含的 unique 元素已强制执行最后三个约束

如果这是对您要实现的目标的正确理解,那么:

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

    <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 属性(通过其声明),因此在这种情况下两者具有相同的效果。