Gioce90
Gioce90

Reputation: 623

How create references between elements in XML

Is possible do reference to an existing element in xml file? I searched on Google but have not found the answers I was hoping for.

I start immediately explaining my goal:

    <Car id="car1">
        <plate>AAA</plate>
        <mark>Peugeot</mark>
    </Car>

    <Truck id="truck1">
        <plate>BBB</plate>
        <mark>Scania</mark>
    </Truck>

    <Trailer id="trailer1">
        <plate>CCC</plate>
        <mark>Menci</mark>
    </Trailer>

    <TrailerTruck>
        <Truck id="truck1"/>
        <Trailer id="trailer1">
    </TrailerTruck>

... in this way I don't duplicate nothing.

Can be possible do this kind of references? If so, how?


I show you my XML Schema:

<?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 name="Car" type="CarType"/>
            <xs:element name="Truck" type="TruckType"/>
            <xs:element name="Trailer" type="TrailerType"/>
            <xs:element name="TrailerTruck" type="TrailerTruckType"/>
        </xs:choice>
    </xs:complexType>


    <xs:complexType name="VehicleType" abstract="true">
        <xs:sequence>
            <xs:element name="plate" type="xs:string" minOccurs="1" />
            <xs:element name="mark" type="xs:string" minOccurs="0" />
            <xs:element name="model" type="xs:string" minOccurs="1" />
        </xs:sequence>
    </xs:complexType>



    <!-- Definitions: Car, Truck, Trailer -->

    <xs:complexType name="CarType">
        <xs:complexContent>
            <xs:extension base="VehicleType"/>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="TruckType">
        <xs:complexContent>
            <xs:extension base="VehicleType"/>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="TrailerType">
        <xs:complexContent>
            <xs:extension base="VehicleType"/>
        </xs:complexContent>
    </xs:complexType>



    <!-- Definition: TrailerTruck -->

    <xs:group name="DrivingPart">
        <xs:choice>
            <xs:element name="Car" type="CarType"/>
            <xs:element name="Truck" type="TruckType"/>
        </xs:choice>
    </xs:group>

    <xs:complexType name="TrailerTruckType">
        <xs:sequence>
            <xs:group ref="DrivingPart"/>
            <xs:element name="Trailer" type="TrailerType" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>

</xs:schema>

In this XSD, I have a Fleet of Vehicles. VehiclesType is abstract. Instead Car, Truck, etc are concrete. Pay attention on TrailerTruck.

An example of XML:

<?xml version="1.0" encoding="UTF-8"?>
<Fleet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="NewXMLSchema.xsd"> 

    <Car>
        <plate>AAA</plate>
        <mark>Peugeot</mark>
        <model>206</model>
    </Car>

    <Truck>
        <plate>BBB</plate>
        <mark>Scania</mark>
        <model>X1</model>
    </Truck>

    <Trailer>
        <plate>CCC</plate>
        <mark>Menci</mark>
        <model>m2</model>
    </Trailer>


    <TrailerTruck>
        <Truck> <!-- Here I'm OBBLIGATE to rewrite all :( --->
            <plate>BBB</plate>
            <mark>Scania</mark>
            <model></model>
        </Truck>
        <Trailer>
            <plate>CCC</plate>
            <mark>Menci</mark>
            <model>m2</model>
        </Trailer>
    </TrailerTruck>


</Fleet>

Upvotes: 3

Views: 5708

Answers (2)

potame
potame

Reputation: 7905

You can simply use the ID / IDREF feature of the schema. However, you need a specific attribute that will reference the ID value.

Thus I suggest you modify your schema like this:

<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="0" />
        <xs:element name="model" type="xs:string" minOccurs="1" />
    </xs:sequence>
    <xs:attribute name="id" type="xs:ID"></xs:attribute>
    <xs:attribute name="refid" type="xs:IDREF"></xs:attribute>
</xs:complexType>

along with an XML instance such as:

<?xml version="1.0" encoding="UTF-8"?>
<Fleet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd">
    <Car id="car1">
        <plate>AAA</plate>
        <mark>Peugeot</mark>
        <model>Model AAA</model>
    </Car>

    <Truck id="truck1">
        <plate>BBB</plate>
        <mark>Scania</mark>
        <model>Model BBB</model>
    </Truck>

    <Trailer id="trailer1">
        <plate>CCC</plate>
        <mark>Menci</mark>
        <model>Model CCC</model>
    </Trailer>

    <TrailerTruck>
        <Truck refid="truck1"/>
        <Trailer refid="trailer1" />
    </TrailerTruck>
</Fleet>

Comments:

  1. now the content of a Truck or Trailer can be empty. It will be up to you to know if you want to use a complete content or not (only a reference). This minimizes the modification of the schema.
  2. it is possible to locally define a Truck / Trailer element if in TrailerTruck which will only allow empty content, if you are sure you only need references within a <TrailerTruck>.
  3. however (IMHO) I think it is better to use specific tag for references, e.g. <TruckRef>, <TrailerRef>. Thus you need to define these tags and modify model content of <TrailerTruck>.

Upvotes: 4

Oliver Friedrich
Oliver Friedrich

Reputation: 9240

You can use XPointer to refer to other parts of an XML.

Upvotes: 0

Related Questions