Kaining xin
Kaining xin

Reputation: 160

Is it possible to associate an attribute to another one in XSD?

Could I make c_id refer to <customers> and ac_id refer to <accounts>, which means limit the scope of c_id to id of <savings_account> and ac_id to id of <checking_account>?

<?xml version="1.0" encoding="UTF-8"?>
<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>

Upvotes: 0

Views: 34

Answers (1)

zx485
zx485

Reputation: 29022

This is only possible in XSD-1.1. You can use an XSD-1.1 file like below. It uses three xsd:asserts to realize the restrictions desired (or somewhat close to your requirements):

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="bank">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="accounts" />          
                <xs:element ref="customers" />          
                <xs:element ref="customer_accounts" />    
            </xs:sequence>
            <xs:assert test="every $c in customers/customer satisfies $c/@id = customer_accounts/customer_account/@c_id" />
            <xs:assert test="every $a in accounts/savings_accounts/savings_account  satisfies $a/@id = customer_accounts/customer_account/@ac_id" /> 
            <xs:assert test="every $a2 in accounts/checking_accounts/checking_account  satisfies $a2/@id = customer_accounts/customer_account/@ac_id" />
        </xs:complexType>
    </xs:element>
          
    <xs:element name="accounts">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="savings_accounts" />          
                <xs:element ref="checking_accounts" />          
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="savings_accounts">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="savings_account">
                <xs:complexType>
                    <xs:sequence>
                    <xs:element name="balance" type="xs:unsignedShort" />
                    </xs:sequence>
                    <xs:attribute name="id" type="xs:string" use="required" />
                    <xs:attribute name="interest" type="xs:decimal" use="required" />
                </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
        
    <xs:element name="checking_accounts">
        <xs:complexType>
            <xs:sequence>
            <xs:element maxOccurs="unbounded" name="checking_account">
                <xs:complexType>
                <xs:sequence>
                    <xs:element name="balance" type="xs:short" />
                </xs:sequence>
                <xs:attribute name="id" type="xs:string" use="required" />
                </xs:complexType>
            </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
                            
    <xs:element name="customers">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="customer">
                    <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:element>
    
    <xs:element name="customer_accounts">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="customer_account">
                    <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:schema>

The first one

every $c in customers/customer satisfies $c/@id = customer_accounts/customer_account/@c_id

asserts that every <customer>'s id attribute is contained as a <customer_account's c_id attribute.

The second one

every $a in accounts/savings_accounts/savings_account satisfies $a/@id = customer_accounts/customer_account/@ac_id

asserts that every <savings_account>'s id attribute is contained as a <customer_account's ac_id attribute.

The third one

every $a2 in accounts/checking_accounts/checking_account  satisfies $a2/@id = customer_accounts/customer_account/@ac_id

asserts that every <checking_account>'s id attribute is contained as a <customer_account's ac_id attribute.

So yes, it is possible to

associate an attribute to another one in XSD

Upvotes: 1

Related Questions