How to control references between elements in XML -
in previous question (how create references between elements in xml) asked how create, in xml schema, references between elements.
ok, noticed something. example, defining these 3 types of vehicles:
<car id="car1"> <plate>aaa</plate> <mark>peugeot</mark> <model>206</model> </car> <truck id="truck1"> <plate>bbb</plate> <mark>scania</mark> <model>x1</model> </truck> <trailer id="trailer1"> <plate>ccc</plate> <mark>scania</mark> <model>t1</model> </trailer>
... can define complex vehicle, example:
<trailertruck id="tt1"> <car refid="car1"/> <trailer refid="trailer1"/> </trailertruck> <trailertruck id="tt2"> <truck refid="truck1"/> <trailer refid="trailer1"/> </trailertruck>
okay, works, noticed - unfortunately - allowed such thing:
<trailertruck id="tt3_wrong"> <truck refid="trailer1"/> <!-- element "truck" should not refer trailer!! should able refer truck1 --> <trailer refid="car1"/> <!-- before, element trailer should able refer trailer1 --> </trailertruck> <trailertruck id="tt4_wrong"> <car refid="truck1"/> <!-- element **car** should not refer truck !! --> <trailer refid="trailer1"/> </trailertruck>
so, if put incorrect references, not shown error. instead, notified. want insert kind of restriction or control. how?
now show current implementation.
vehiclexmlschema.xsd:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:element name="fleet" type="fleettype"/> <xs:complextype name="fleettype"> <xs:choice maxoccurs="unbounded"> <xs:element ref="car" /> <xs:element ref="truck" /> <xs:element ref="trailer" /> <xs:element ref="trailertruck" /> </xs:choice> </xs:complextype> <xs:complextype name="vehicletype" abstract="true"> <xs:sequence minoccurs="0"> <xs:element name="plate" type="xs:string" minoccurs="1" /> <xs:element name="mark" type="xs:string" minoccurs="1" /> <xs:element name="model" type="xs:string" minoccurs="1" /> </xs:sequence> </xs:complextype> <!-- simplevehicle , complexvehicle --> <xs:complextype name="simplevehicle"> <xs:complexcontent> <xs:extension base="vehicletype"> <xs:attribute name="id" type="xs:id"/> </xs:extension> </xs:complexcontent> </xs:complextype> <xs:complextype name="complexvehicle"> <xs:complexcontent> <xs:extension base="vehicletype"> <xs:attribute name="refid" type="xs:idref"/> </xs:extension> </xs:complexcontent> </xs:complextype> <!-- car, truck, trailer --> <xs:element name="car" type="simplevehicle" /> <xs:element name="truck" type="simplevehicle"/> <xs:element name="trailer" type="simplevehicle"/> <!-- trailertruck --> <xs:group name="drivingpart"> <xs:choice> <xs:element name="car" type="complexvehicle" /> <xs:element name="van" type="complexvehicle"/> <xs:element name="truck" type="complexvehicle"/> </xs:choice> </xs:group> <xs:element name="trailertruck"> <xs:complextype> <xs:sequence> <xs:group ref="drivingpart" minoccurs="1" maxoccurs="1"/> <xs:element name="trailer" type="complexvehicle" minoccurs="1" maxoccurs="1"/> </xs:sequence> <xs:attribute name="id" type="xs:id"/> </xs:complextype> </xs:element> </xs:schema>
shipper1.xml:
<fleet shippername="shipper1" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:nonamespaceschemalocation="vehiclexmlschema.xsd"> <car id="car1"> <plate>aaa</plate> <mark>peugeot</mark> <model>206</model> </car> <truck id="truck1"> <plate>ddd</plate> <mark>scania</mark> <model></model> </truck> <trailer id="trailer1"> <plate>eee</plate> <mark>scania</mark> <model></model> </trailer> <trailertruck id="trailertruck1"> <car refid="car1" /> <trailer refid="trailer1" /> </trailertruck> <trailertruck id="trailertruck2_wrong"> <truck refid="car1" /> <trailer refid="trailer1" /> </trailertruck> <trailertruck id="trailertruck3_wrong"> <truck refid="truck1" /> <trailer refid="car1" /> </trailertruck> </fleet>
i think you're looking referential integrity; need xsd:key/xsd:keyref. id/idref in xsd spec backward compatibility dtds; wouldn't use them in xsds.
this modified xsd:
<?xml version="1.0" encoding="utf-8" ?> <!-- xml schema generated qtassistant/xsd module (http://www.paschidev.com) --> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/xmlschema"> <xs:element name="fleet" type="fleettype"> <xs:key name="pk_cars"> <xs:selector xpath="car"/> <xs:field xpath="@id"/> </xs:key> <xs:key name="pk_trucks"> <xs:selector xpath="truck"/> <xs:field xpath="@id"/> </xs:key> <xs:key name="pk_trailers"> <xs:selector xpath="trailer"/> <xs:field xpath="@id"/> </xs:key> <xs:key name="pk_trailertruck"> <xs:selector xpath="trailertruck"/> <xs:field xpath="@id"/> </xs:key> <xs:keyref name="fk_trailertruck2trailers" refer="pk_trailers"> <xs:selector xpath="trailertruck/trailer"/> <xs:field xpath="@refid"/> </xs:keyref> <xs:keyref name="fk_trailertruck2cars" refer="pk_cars"> <xs:selector xpath="trailertruck/car"/> <xs:field xpath="@refid"/> </xs:keyref> <xs:keyref name="fk_trailertruck2trucks" refer="pk_trucks"> <xs:selector xpath="trailertruck/truck"/> <xs:field xpath="@refid"/> </xs:keyref> </xs:element> <xs:complextype name="fleettype"> <xs:choice maxoccurs="unbounded"> <xs:element ref="car"/> <xs:element ref="truck"/> <xs:element ref="trailer"/> <xs:element ref="trailertruck"/> </xs:choice> <xs:attribute name="shippername" type="xs:string"/> </xs:complextype> <xs:complextype name="vehicletype" abstract="true"> <xs:sequence minoccurs="0"> <xs:element name="plate" type="xs:string" minoccurs="1"/> <xs:element name="mark" type="xs:string" minoccurs="1"/> <xs:element name="model" type="xs:string" minoccurs="1"/> </xs:sequence> </xs:complextype> <!-- simplevehicle , complexvehicle --> <xs:complextype name="simplevehicle"> <xs:complexcontent> <xs:extension base="vehicletype"> <xs:attribute name="id" type="xs:id"/> </xs:extension> </xs:complexcontent> </xs:complextype> <xs:complextype name="complexvehicle"> <xs:complexcontent> <xs:extension base="vehicletype"> <xs:attribute name="refid" type="xs:idref"/> </xs:extension> </xs:complexcontent> </xs:complextype> <!-- car, truck, trailer --> <xs:element name="car" type="simplevehicle"/> <xs:element name="truck" type="simplevehicle"/> <xs:element name="trailer" type="simplevehicle"/> <!-- trailertruck --> <xs:group name="drivingpart"> <xs:choice> <xs:element name="car" type="complexvehicle"/> <!-- <xs:element name="van" type="complexvehicle"/>--> <xs:element name="truck" type="complexvehicle"/> </xs:choice> </xs:group> <xs:element name="trailertruck"> <xs:complextype> <xs:sequence> <xs:group ref="drivingpart" minoccurs="1" maxoccurs="1"/> <xs:element name="trailer" type="complexvehicle" minoccurs="1" maxoccurs="1"/> </xs:sequence> <xs:attribute name="id" type="xs:id"/> </xs:complextype> </xs:element> </xs:schema>
with key/keyref, control cross checks. diagram below shows content expanded demonstrate:
- cars , trailers pk
- how link trailer trucks trailers
- how link driving part (a car in case) associated counterpart (a car in top section of xml).
it consistent referential integrity in "traditional" database design: got primary keys, foreign keys. posted xml invalid; 1 below valid version of it.
<fleet shippername="shipper1" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:nonamespaceschemalocation="vehiclexmlschema.xsd"> <car id="car1"> <plate>aaa</plate> <mark>peugeot</mark> <model>206</model> </car> <truck id="truck1"> <plate>ddd</plate> <mark>scania</mark> <model></model> </truck> <trailer id="trailer1"> <plate>eee</plate> <mark>scania</mark> <model></model> </trailer> <trailertruck id="trailertruck1"> <car refid="car1"/> <trailer refid="trailer1"/> </trailertruck> <trailertruck id="trailertruck2_wrong"> <truck refid="truck1"/> <trailer refid="trailer1"/> </trailertruck> <trailertruck id="trailertruck3_wrong"> <truck refid="truck1"/> <trailer refid="trailer1"/> </trailertruck> </fleet>
Comments
Post a Comment