2010年11月7日 星期日

What are ID, IDREF, and IDREFS simple types in XSD? How is xs:unique used to constrain values?

The ID, IDRER and IDREFS are introduced in DTD (Document Type Definition) to implement the constraint for attribute in XML elements.
The type of ID is used to indentify an attribute that the value of the attribute in the element is unique in the XML document. And the duplicated values of attribute are not allowed. This insure that the unique property for XML language as similar to unique ID in database.
Whereas, the IDREF and IDREFS are typically used to define an attribute that the value of this attribute only be selected from the values of the existing attribute is identified by ID. Specially, the IDREFS, it can have more than one values can include in this attribute.
The following Table1 summarized the definitions of ID, IDRER and IDREFS,

Type
Description
ID
The value of attribute is a unique id
IDREF
The value of attribute is the id of another element
IDREFS
The values of attribute are a list of other ids

Table1 – ID/IDRER/IDRERS
The following example introduced how to use ID, IDREF and IDREFS within DTD in XML document (the inline DTD is used).

XML Document (company.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Company [
<!ELEMENT Company (staff|manager)* >
<!ELEMENT staff (name)>
<!ELEMENT manager (name)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST staff staff_id ID #REQUIRED>
<!ATTLIST staff leader IDREF #IMPLIED>
<!ATTLIST manager manage IDREFS #IMPLIED>
]>
<Company>
    <staff staff_id="s0001">
        <name>Longson</name>   
    </staff>
    <staff leader="s0001" staff_id="s0002">
        <name>Carson</name>
    </staff>
    <manager manage="s0001 s0002">
        <name>Samuel</name>   
    </manager>
</Company>

Table 2 – Inline DTD with ID, IDREF and IDREFS
The above example described in Table 2 shows the value of “leader” is referred to the staff_no. So the leader of staff “Carson” is “Longson”.  And the attribute of “manager” can have more than one value from staff_no. So the manager “Samuel” manage two staffs in the company.
But the disadvantage of using this DTD function is that only one attribute can be identified by ID.
In XML schema, using xs:unique and xs:key, xs:keyref to implement such task mentioned above. The xs:unique and xs:key using in XML schema to replace the function of ID in DTD.
Let’s give an example on how to using “xs:unique” in XML schema. In the Table 3, an XML document “Staff-select_field.xml” shows that the element of “staff-number” should be unique. The XML schema “Staff-select_field.xsd” that defines the XML document of “Staff-select_field.xml” in the same table.

XML Document (Staff-select_field.xml)
<?xml version="1.0" encoding="UTF-8"?>
<company
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Staff-select_field.xsd">
     <staff>
         <staff-number>001</staff-number>    
         <staff-name>Carson</staff-name>
     </staff>
     <staff>
          <staff-number>002</staff-number>
          <staff-name>Carson</staff-name>
     </staff>
</company>
XML Schema (Staff-select_field.xsd)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="company" type="companyType">
            <xs:unique name="staffNumberUnique">
                  <xs:selector xpath="staff"></xs:selector>
                  <xs:field xpath="staff-number"></xs:field>
         </xs:unique>
    </xs:element>
            <xs:complexType name="companyType">
                  <xs:sequence>
                      <xs:element name="staff" type="staffType" maxOccurs="unbounded"/>
                  </xs:sequence>
    </xs:complexType>
    <xs:complexType name="staffType">
            <xs:sequence>
                  <xs:element name="staff-number" type="xs:token"/>
                  <xs:element name="staff-name" type="xs:token"/>
            </xs:sequence>
    </xs:complexType>
</xs:schema>

Table 3 – xs:unique
There are two child elements “xs:selector” and “xs:field” within the parent element “xs:unique”. These two child elements help to constrain the scope of where the “xs:unique” should be adapted.
In this example, the “xs:selector” specified which element to should be selected for this constrain (here is the “staff” element), the “xs:field” is use to find out which element of attribute should be provide for “xs:selector” (here is the “staff-number” element).

The next step is going to introduce how to use the “xs:keyref” to implement the reference function in XML schema. The “xs:keyref” must use with “xs:unique” or “xs:key” together to setup the reference relationship between the XML data.
The following example as same as above but only the value of “manage” should be selected from the existing value of “student-number”.

XML Document (Staff-select_field_keyref.xml)
<?xml version="1.0" encoding="UTF-8"?>
<company
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Staff-select_field_keyref.xsd">
     <staff>
         <staff-number>001</staff-number>    
         <staff-name>Carson</staff-name>
     </staff>
     <staff manage="001">
          <staff-number>002</staff-number>
          <staff-name>Carson</staff-name>
     </staff>
</company>
XML Schema (Staff-select_field_keyref.xsd)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
            <xs:element name="company" type="companyType">
                 <xs:unique name="staffNumberUnique">
                        <xs:selector xpath="staff"></xs:selector>
                        <xs:field xpath="staff-number"></xs:field>
                </xs:unique>
                <xs:keyref refer="staffNumberUnique" name="manageKeyRef">
                        <xs:selector xpath="staff"></xs:selector>
                        <xs:field xpath="@manage"></xs:field>
                </xs:keyref>
            </xs:element>
            <xs:complexType name="companyType">
                  <xs:sequence>
                       <xs:element name="staff" type="staffType" maxOccurs="unbounded"/>
                  </xs:sequence>
            </xs:complexType>
            <xs:complexType name="staffType">
                 <xs:sequence>
                      <xs:element name="staff-number" type="xs:token"/>
                      <xs:element name="staff-name" type="xs:token"/>
                 </xs:sequence>
                 <xs:attribute name="manage" type="xs:token"/>
            </xs:complexType>
</xs:schema>

Table 3 – xs:keyref
In the case of “xs:keyref”, two attributes are included in this element, one is
refer” and another is “name”, the key is the “refer” attribute, it is refer to which “xs:unique”, it build the reference relationship between each other. And the “name” attribute just a name for this “xs:keyref”.
In this example, the structure of “xs:keyref” is the same as the “xs:unique” or “xs:key”. The “xs:selector” and “xs:field” are used to specify which element or attribute should be used for the reference relationship in XML schema.