Med betoning på ID, IDREF och IDREFS
Tag en titt på nedanstående lilla XML fil:
xml11_1.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (name*)>
<!ELEMENT name (#PCDATA)>
]>
<in_the_beginning >
<name>Kain</name>
<name>Abel</name>
<name>Eva</name>
<name>Adam</name>
</in_the_beginning >
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Inga problem att tolka, eller hur. Problemet är att det fattas en hel
del information...
Vi kan enkelt härleda följande information om personerna
- Kain och Abel är bröder
- Eva och Adam är föräldrar till Kain och Abel
- Kain och Abel är söner till Adam och Eva.
- Eva är fru till Adam
- Adam är man till Eva
Problemet är att få in den informationen i XML filen. En möjlighet
skulle kunna vara:
xml11_2.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (person*)>
<!ELEMENT person ( name,
father?,
mother?,
brother*,
sister*,
son*,
daughter*,
wife?,
husband? )>
<!ELEMENT name (#PCDATA)>
<!ELEMENT father (#PCDATA)>
<!ELEMENT mother (#PCDATA)>
<!ELEMENT brother (#PCDATA)>
<!ELEMENT sister (#PCDATA)>
<!ELEMENT son (#PCDATA)>
<!ELEMENT daughter (#PCDATA)>
<!ELEMENT wife (#PCDATA)>
<!ELEMENT husband (#PCDATA)>
]>
<in_the_beginning>
<person>
<name>Kain</name>
<father>Adam</father>
<mother>Eva</mother>
<brother>Abel</brother>
</person>
<person>
<name>Abel</name>
<father>Adam</father>
<mother>Eva</mother>
<brother>Kain</brother>
</person>
<person>
<name>Eva</name>
<son>Kain</son>
<son>Abel</son>
<husband>Adam</husband>
</person>
<person>
<name>Adam</name>
<son>Kain</son>
<son>Abel</son>
<wife>Eva</wife>
</person>
</in_the_beginning>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Detta metod fungerar och är visserligen valid XML, men verkar det vettigt?
En hel del data kommer flera gånger i olika sammanhang. Vi har fått
det som databasplanerare hatar: redundans.
Tag istället en titt på följande variant, där datat lagras
utan redundans och där relationerna mellan personerna istället anges
som attribut.
xml11_3.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (name*)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name id ID #REQUIRED
mother IDREF #IMPLIED
father IDREF #IMPLIED
siblings IDREFS #IMPLIED
children IDREFS #IMPLIED >
]>
<!-- id får inte börja på en siffra -->
<in_the_beginning>
<name id="id_1" mother="id_3" father="id_4" siblings="id_2">
Kain
</name>
<name id="id_2" mother="id_3" father="id_4" siblings="id_1">
Abel
</name>
<name id="id_3" children="id_1 id_2">
Eva
</name>
<name id="id_4" children="id_1 id_2">
Adam
</name>
</in_the_beginning>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Detta skall inte förväxlas med "vanliga" attribut. Följande
fil är helt valid XML men attributen har ingen inbyggd, "större",
betydelse i XML, utan är bara vanliga attribut som vi får göra
vad vi vill med.
xml11_4.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (name*)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name id CDATA #REQUIRED
mother CDATA #IMPLIED
father CDATA #IMPLIED
siblings CDATA #IMPLIED
children CDATA #IMPLIED >
]>
<!-- id får inte börja på en siffra -->
<in_the_beginning>
<name id="id_1" mother="id_3" father="id_4" siblings="id_2">
Kain
</name>
<name id="id_2" mother="id_3" father="id_4" siblings="id_1">
Abel
</name>
<name id="id_3" children="id_1 id_2">
Eva
</name>
<name id="id_4" children="id_1 id_2">
Adam
</name>
</in_the_beginning>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Skillnaden mellan attribut och ID
Ett attribut är "bara" extra information som vi vill ha i noden.
Ett ID betyder en relation mellan noderna.
Detta märks tydligt om vi jämför följande varianter:
Denna är valid XML - med attribut
xml11_5.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (name*)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name id CDATA #REQUIRED
mother CDATA #IMPLIED
father CDATA #IMPLIED
siblings CDATA #IMPLIED
children CDATA #IMPLIED >
]>
<!-- id får inte börja på en siffra -->
<in_the_beginning>
<name id="id_1" mother="id_3" father="id_4" siblings="id_2">
Kain
</name>
</in_the_beginning>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Medan denna inte är valid - med ID
xml11_6.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE in_the_beginning [
<!ELEMENT in_the_beginning (name*)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name id ID #REQUIRED
mother IDREF #IMPLIED
father IDREF #IMPLIED
siblings IDREFS #IMPLIED
children IDREFS #IMPLIED >
]>
<!-- id får inte börja på en siffra -->
<in_the_beginning>
<name id="id_1" mother="id_3" father="id_4" siblings="id_2">
Kain
</name>
</in_the_beginning>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Den senare är inte valid eftersom vi hänvisar till en IDREF (referens)
som inte finns i filen.
Varför... Jo
ID, IDREF och IDREFS används för att beteckna relationer mellan noder.
ID
Ingenting hindrar oss från att döpa ett "vanligt" attribut
till id, och använda det i vår XML fil. Vi kan då använda
detta attribut till vad vi vill.
Om vi däremot definierar ett id på följande sätt så
är den uttryckligen ett ID, det räcker inte med att den heter id:
<!ATTLIST nodens_namn id ID #REQUIRED>
Den måste inte ens ha namnet id, den måste vara ett ID.
Följande är helt möjligt:
<!ATTLIST nodens_namn personid ID #REQUIRED>
Id måste, självklart, vara unika. Gämför gärna med
nyckelfält (primary keys) i databaser.
IDREF
IDREF betyder en hänvisning till ett ID. Jämför gärna med
databasbegreppet foreign key (sorry vet inte vad det heter på svenska)
i en EN-TILL-EN relation. En person har EN mor och EN far, åtminstone
var det så när jag var liten. Personen har då en IDREF till
moderns ID och en IDREF till faderns ID.
IDREFS
En IDREF betyder en till många relation. Den fungerar som en vanlig IDREF
mend kan innehålla flera ID. En person kanske bara har en mor och en far,
men kan ha många syskon. Syskonen (siblings) ger då en en till många
relation inom filen.
Ett till exempel på ID, IDREF och IDREFS
Länder och städer:
xml11_7.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE geography [
<!ELEMENT geography (country|city)*>
<!ELEMENT country (country_name, capital, cities)>
<!ELEMENT country_name (#PCDATA)>
<!ELEMENT capital EMPTY>
<!ELEMENT cities EMPTY>
<!ELEMENT city (city_name,location)>
<!ELEMENT city_name (#PCDATA)>
<!ELEMENT location EMPTY>
<!ATTLIST country id ID #REQUIRED>
<!ATTLIST capital idref IDREF #REQUIRED>
<!ATTLIST cities idrefs IDREFS #IMPLIED>
<!ATTLIST city id ID #REQUIRED >
<!ATTLIST location idref IDREF #REQUIRED>
]>
<geography>
<!-- ett land med ID="FIN" -->
<country id="FIN">
<!-- namnet på landet -->
<country_name>Finland</country_name>
<!-- huvudstaden - referens till en city nod -->
<capital idref="HEL" />
<!-- övriga städer -referenser till city noder -->
<cities idrefs="VORA VASA" />
</country>
<country id="SVE">
<country_name>Sverige</country_name>
<capital idref="STO" />
<cities idrefs="MAL UME" />
</country>
<!-- en stad med ID="HEL" -->
<city id="HEL">
<!-- stadens namn -->
<city_name>Helsingfors</city_name>
<!-- var finns staden - referens till ett land -->
<location idref="FIN" />
</city>
<city id="VORA">
<!-- kanske inte en stad, men... -->
<city_name>Vörå</city_name>
<location idref="FIN" />
</city>
<city id="VASA">
<city_name></city_name>
<location idref="FIN" />
</city>
<city id="STO">
<city_name>Stockholm</city_name>
<location idref="SVE" />
</city>
<city id="MAL">
<city_name>Malmö</city_name>
<location idref="SVE" />
</city>
<city id="UME">
<city_name>Umeå</city_name>
<location idref="SVE" />
</city>
</geography>
Om du har IE 5.0 eller nyare kan du klicka här för att se filen i praktiken
Se även xml_ex2.asp där jag visar hur
man kan formatera data med XSL