Elements that turn out to only be referenced by IDREF(S) need to be added as allowable element content to the root element of the DTD. Then, when creating the document, the orphaned elements are created within the root element and then pointed to, where appropriate.
Applying this rule to our example, we see that we are missing the <Customer> and <Part> elements. Adding these as allowable structural content to our root element gives us:
<!ELEMENT SalesData (Invoice*, Customer*, Part*, MonthlyTotal*)>
<!ATTLIST SalesData
Status (NewVersion | UpdatedVersion | CourtesyCopy) #REQUIRED>
<!ELEMENT Invoice (LineItem*)>
...
Rule 10: Add Missing Elements.
For any element that is only pointed to in the structure created so far, add that element as allowable element content of the root element. Set the cardinality suffix of the element being added to *.
Discard Unreferenced ID attributes
Finally, we need to discard those ID attributes that we created in Rule 5 that do not have IDREF(S) pointing to them. Since we created these attributes in the process of building the XML structures, discarding them if they are not used does not sacrifice information, and saves developers the trouble of generating unique values for the attributes.
Rule 11: Remove Unwanted ID Attributes.
Remove ID attributes that are not referenced by IDREF or IDREFS attributes elsewhere in the XML structures.
Applying Rule 11 to our example gives us our final structure. On review, the InvoiceID, LineItemID, MonthlyPartTotalID, MonthlyTotalID, and MonthlyCustomerTotalID attributes are not referenced by any IDREF or IDREFS attributes. Removing them, we arrive at our final structure, ch03_ex01.dtd:
<!ELEMENT SalesData (Invoice*, Customer*, Part*, MonthlyTotal*)>
<!ATTLIST SalesData
Status (NewVersion | UpdatedVersion | CourtesyCopy) #REQUIRED>
<!ELEMENT Invoice (LineItem*)>
<!ATTLIST Invoice
InvoiceNumber CDATA #REQUIRED
TrackingNumber CDATA #REQUIRED
OrderDate CDATA #REQUIRED
ShipDate CDATA #REQUIRED
ShipMethod (USPS | FedEx | UPS) #REQUIRED
CustomerIDREF IDREF #REQUIRED>
<!ELEMENT Customer EMPTY>
<!ATTLIST Customer
CustomerID ID #REQUIRED
Name CDATA #REQUIRED
Address CDATA #REQUIRED
City CDATA #REQUIRED
State CDATA #REQUIRED
PostalCode CDATA #REQUIRED>
<!ELEMENT Part EMPTY>
<!ATTLIST Part
PartID ID #REQUIRED
PartNumber CDATA #REQUIRED
Name CDATA #REQUIRED
Color CDATA #REQUIRED
Size CDATA #REQUIRED>
<!ELEMENT MonthlyTotal (MonthlyCustomerTotal*, MonthlyPartTotal*)>
<!ATTLIST MonthlyTotal
Month CDATA #REQUIRED
Year CDATA #REQUIRED
VolumeShipped CDATA #REQUIRED
PriceShipped CDATA #REQUIRED>
<!ELEMENT MonthlyCustomerTotal EMPTY>
<!ATTLIST MonthlyCustomerTotal
VolumeShipped CDATA #REQUIRED
PriceShipped CDATA #REQUIRED
CustomerIDREF IDREF #REQUIRED>
<!ELEMENT MonthlyPartTotal EMPTY>
<!ATTLIST MonthlyPartTotal
VolumeShipped CDATA #REQUIRED
PriceShipped CDATA #REQUIRED
PartIDREF IDREF #REQUIRED>
<!ELEMENT LineItem EMPTY>
<!ATTLIST LineItem
Quantity CDATA #REQUIRED
Price CDATA #REQUIRED
PartIDREF IDREF #REQUIRED>
An Example XML Document
Finally, here's an example of an XML document (ch03_ex01.xml) that would be valid for this DTD:
<?xml version="1.0"?>
<!DOCTYPE SalesData SYSTEM "http://myserver/xmldb/ch03_ex01.dtd" >
<SalesData Status="NewVersion">
<Invoice InvoiceNumber="1"
TrackingNumber="1"
OrderDate="01012000"
ShipDate="07012000"
ShipMethod="FedEx"
CustomerIDREF="Customer2">
<LineItem Quantity="2"
Price="5"
PartIDREF="Part2" />
</Invoice>
<Customer CustomerID="Customer2"
Name="BobSmith"
Address="2AnyStreet"
City="Anytown"
State="AS"
PostalCode="ANYCODE" />
<Part PartID="Part2"
PartNumber="13"
Name="Winkle"
Color="Red"
Size="10" />
<MonthlyTotal Month="January"
Year="2000"
VolumeShipped="2"
PriceShipped="10">
<MonthlyCustomerTotal VolumeShipped="5"
PriceShipped="25"
CustomerIDREF="Customer2" />
<MonthlyPartTotal VolumeShipped="8"
PriceShipped="40"
PartIDREF="Part2" />
</MonthlyTotal>
</SalesData>