XML
Namespace
CDATA
Entities
XML
Børre Stenseth

Terminologi

Hva

Noen sentrale begreper i XML

Velformet XML

Følgende er en velformet XML-fil:

<?xml version="1.0" encoding="utf-8"?>
<kunde>
<etternavn/>
<fornavn/>
<adresse/>
</kunde>
Se den i nettleseren https://borres.hiof.no/wep/xml/term/dok1.xml

Du ser sannsynligvis ikke så mye dersom du kjører en nettleser som ikke tolker XML og som ignorerer elementer som ikke er HTML.

Vi ser at den første linja angir at dette er en XML-fil slik at programvare, f.eks. en nettleser, som leser fila vet hva den kan forvente. Det angis dessuten hva slags koding som er benyttet. I dette tilfellet er det UTF-8 som er en ISO-standard (International Standard Organisation) som ivaretar lagring og presentasjon av alle tegnsett som brukes internasjonalt. Hvis vi skulle brukt bare norske tegn kunne vi skrevet ISO-8859-1. Vi går ikke mer inn på dette her. De neste linjene er elementer som er ordnet i en trestruktur.

xml11

Betingelsen for velformethet i dette eksempelet er at elementene lukkes før neste begynner. Merk at elementer kan skrives på en to former.

  • Vi kan skrive <fornavn/> for et komplett element uten innhold. Slik som det står her har det ikke mye mening siden det ikke har hverken attributter, underelementer eller innhold.
  • Vi kan skrive <kunde> innhold </kunde>, altså en åpningsdel og en lukkedel med innhold i mellom.

Denne er ikke velformet:

<?xml version="1.0" encoding="utf-8"?>
<kunde>
  <etternavn>
  </etternavn>
  <fornavn>
  <adresse>
  </fornavn>
  </adresse>
</kunde>
Se den i nettleseren https://borres.hiof.no/wep/xml/term/dokfeil.xml

Vi ser at fila ovenfor (den velformede versjonen) ikke inneholder informasjon om noen spesiell person. Den bærer ikke semantisk informasjon. Vi kan skrive den om slik:

<?xml version="1.0" encoding="utf-8"?>
<kunde>
<etternavn>
 Nordmann
</etternavn>
<fornavn>
Ola
</fornavn>
<adresse>
Trollheimen
</adresse>
</kunde>
Se den i nettleseren https://borres.hiof.no/wep/xml/term/dok2.xml

Vi har innført text-elementer og det komplette treet blir nå:

xml12

Tekstelementer kan ikke ha barn.

Merk at det er flere regler for velformethet enn den elementregelen vi har demonstrert ovenfor. Dette kommer vi tilbake til.

Validerbar XML

En ting er at et dokument er velformet i forhold til de generelle reglene for hvordan et hvilket som helst XML-dokument skal utformes. Noe annet er å avgjøre om et dokument er lovlig i forhold til kravene til en bestemt type dokument. Eller om vi vil: i forhold til et bestemt XML-språk. En slik sjekk kaller vi validering av dokumentet.

For å kunne validere et dokument må vi altså sjekke det mot en definisjon av en type dokumenter. Vi må lage en DTD (Document Type Definition) som beskriver regler for hvordan alle dokumenter av denne type skal lages. Skjemaer er et alternativ til DTD'er. Både DTD'er og skjemaer er beskrevet i egne moduler: DTD og Schema. Her ser vi bare noen svært enkle eksempler som kan forstås intuitivt.

Vi tar fatt i vårt enkle eksempel for å beskrive kunder ved fornavn, etternavn og adresse. En DTD som beskriver dokumenter av denne type kan se slik ut:

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT adresse (#PCDATA)>
<!ELEMENT etternavn (#PCDATA)>
<!ELEMENT fornavn (#PCDATA)>
<!ELEMENT kunde (etternavn, fornavn, adresse)>

Vi ser at fila beskriver de fire aktuelle elementene: adresse, etternavn, fornavn og kunde. For de tre første er det angitt at innholdet skal våre PCDATA (Parsed Character Data). Det vil i vår foreløpige analyse si tekst. For elementet kunde ser vi at et kunde-element skal inneholde en forekomst av de tre andre elementene og ikke noe "løs" tekst.

Vi kopler dokumenttypen til selve dokumentet på følgende måte:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE kunde SYSTEM "dok2.dtd">
<kunde>
<etternavn>
Nordmann
</etternavn>
<fornavn>
Ola
</fornavn>
<adresse>
Trollheimen
</adresse>
</kunde>
Se den i nettleseren https://borres.hiof.no/wep/xml/term/dok22.xml

Der den andre linja angir dokumenttypen, kunde, og en referanse, URL, til en fil som inneholder DTD'en. Dokumenttypen, kunde, er det samme som navnet på rotelementet i XML-fila. Slik dokumentet nå er formulert kan programvare sjekke det både med tanke på velformethet og med tanke på validitet.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE kunde SYSTEM "dok2.dtd">
<kunde>
<fornavn>
Ola
</fornavn>
<hårfarge>
Grønn
</hårfarge>
<adresse>
Trollheimen
</adresse>
</kunde>

Nettleserne sjekker ikke validitet. (etternavnet er erstattet med hårfarge)

Prøv i nettleseren https://borres.hiof.no/wep/xml/term/dok22feil.xml

Det finnes andre verktøy for å validere XML-dokumenter. Noen kan du laste ned og kjøre offline og noen ligger som en tjeneste på nettet. XMLSpy kan validere og er et greitt laboratorium for å eksperimentere med XML. Du finner referanse til noen nettbaserte validatorer under referanser på denne siden.

Attributter

I eksempelet ovenfor har vi konsentrert oss om elementer og tekstinnhold. I XML kan elementer ha attributter. Vi kan kople egenskaper til elementene. F.eks. kan vi skrive:

<?xml version="1.0" encoding="utf-8"?>
<kunde kundeid="a123">
<etternavn>
 Nordmann
</etternavn>
<fornavn>
Ola
</fornavn>
<adresse>
Trollheimen
</adresse>
</kunde>

Her har vi sagt at en kunde har egenskapen, attributtet, kundeid. Denne måten å uttrykke seg på er kjent fra HTML, der vi f.eks. skriver:

   <img src="bilde.gif" alt="oversikt" width="40" height="20"/>

Reglene for velformethet i XML krever at det skal være en blank mellom navn-verdi parene i attributtlista og at alle verdier skal skrives i "". Vi vet at tidligere versjoner av HTML, som er SGML-basert, tolererer at vi utelater "". Slik er det ikke i XML, eller i nye HTML varianter som er definert som et XML-språk. Merk forøvrig at HTML5 aksepterer at vi har attributt-angivelser uten verdi.

En dokumenttype definisjon må også kunne spesifisere hvilke attributter som er lovlige og hvor de skal kunne forekomme. En utvidet DTD for vårt superenkle eksempel ser slik ut:

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT adresse (#PCDATA)>
<!ELEMENT etternavn (#PCDATA)>
<!ELEMENT fornavn (#PCDATA)>
<!ELEMENT kunde (etternavn, fornavn, adresse)>
<!ATTLIST kunde
    kundeid CDATA #REQUIRED
>

Når vi har plassert kundeid som en attributt til kundelementet har vi truffet et valg. Vi kunne like gjerne innført kundeid som et nytt element på linje med etternavn, fornavn og adresse. Det er ofte en avveining hvorvidt opplysninger skal plasseres som attributter eller elementer. Mange forfattere drøfter dette uten at det er etablert noen entydige gode regler for hvordan en DTD bør designes med tanke på denne avveiningen. En tommeregel er kanskje å anvende samme type resonnement og vurdering som når vi definererer klasser når vi programmerer. Attributter er kanskje sammenlignbare med attributter i et objekt, mens elementer er selvstendige objekter. Analogien halter nok på noen punkter, men som utgangspunkt for resonneringen er den kanskje brukbar? Vi vil møte igjen denne problemstillingen når vi skal skrive transformasjoner. Det er dessuten ført noen resonnementer om dette i modulen Struktur .

xml13
Struktur med attributt.

CDATA

Det er et problem i behandlingen av XML-filer at vi av og til ønsker at dokumentet skal innholde tekst som ikke skal tolkes av det programmet som leser dokumentet. F.eks.:

<?xml version="1.0" encoding="UTF-8"?>
<eksamen>
<kandidat>
 ole
</kandidat>
<besvarelse>
<html>
<h1>Flott</h1>
<p>webside</p>
</html>
</besvarelse>
</eksamen>

Vi ser at innholdet i elementet besvarelse, som er elevens besvarelse består av elementer som vil bli tolket og som vil føre til at dokumentet i sin helhet misforstås.

Vi kan løse dette ved å angi at en tekst ikke skal parses. Vi innfører en CDATA-seksjon. CDATA står for Character Data, i motsetning til PCDATA som står for Parsed Character Data. Meldinga til det programmet som leser fila er altså: Ikke bry deg om innholdet i denne teksten.

<?xml version="1.0" encoding="UTF-8"?>
<eksamen>
<kandidat>
 ole
</kandidat>
<besvarelse>
<![CDATA[
   <html>
   <h1>Flott</h1>
   <p>webside</p>
   </html>
]]>
</besvarelse>
</eksamen>
Se den i nettleseren https://borres.hiof.no/wep/xml/term/dok41.xml

Namespace

Det er mulig at namespace burde oversettes med navnerom på norsk, men jeg beholder det engelske ordet for ikke å skape mer forvirring enn nødvendig.

Namespaces er et fenomen som er konstruert for å løse opp i noen problemer som dukker opp ganske raskt når vi resonnerer litt omkring XML og hensikten med XML.

Det er viktig å ha klart for seg at:

  • namespace er helt uavhengig av DTD. Et dokument kan ha en DTD og ikke noe (eksplisitt) namespace og omvendt.
  • namespace ble opprinnelig ikke definert som en del av XML, men er tilpasset på et senere tidspunkt.

En av hensiktene med XML er jo at vi skal kunne utveksle og tolke data innen ulike organisasjoner og mellom systemer. Det er en umulig tanke at noen skulle kunne så og si ta patent på elementnavn. Det er grunn til å tro at elementer som f.eks. employee, address, customer, article, book finnes i noen tusen systemer rundt i verden og at de er definert forskjellig, med forskjellig betydning, forskjellige attributter og forskjellige underelementer. Vi må altså ha en måte å angi hvilken definisjon som gjelder i et konkret dokument eller datasett. Denne informasjonen er selvsagt oftest implisitt gitt ved at et program vet hvor datasettet det arbeider med kommer fra. Verre blir det når vi får datasett eller dokumenter som består av fragmenter fra flere dokumenttyper. Selv om vi implisitt vet hvor dataene kommer fra, må vi ha en måte å løse opp i navnekonflikter i datasettet. Vi må da ha en mulighet for å angi, i selve dokumentet, hvilket namespace, navnerom, et element hører til.

Anta følgende, ganske sære, eksempel:

<?xml version="1.0"?>
<bok>
   <markedsføring>
      <tittel>
      Verdens beste bok
      </tittel>
      <innhold>
      Solgt i uttallige eksemplarer
            </innhold>
   </markedsføring>
   
   <tittel>Ole Brum</tittel>
   <ingress>
   Om en teddybjørn og vennene hans
   </ingress>
   <innhold>
   En dag Kristoffer Robin...
   </innhold>
</bok>

Vi ser at elementene tittel og innhold inngår både i selve bokbeskrivelsen og i den informasjonen som skal brukes i markedsføring. De tilhører forskjellige namespaces. Vi må markere denne forskjellen på en eller annen måte. XML har syntaksregler for å angi namespace. Vi kan f.eks. skrive:

<?xml version="1.0"?>
<bok>
   <markedsføring>
      <marked:tittel>
      Verdens beste bok
      </marked:tittel>
      <marked:innhold>
      Solgt i uttallige eksemplarer
      </marked:innhold>
   </markedsføring>
   <tittel>
   Ole Brum
   </tittel>
   <ingress>
   Om en teddybjørn og vennene hans
   </ingress>
   <innhold>
   En dag Kristoffer Robin...
   </innhold>
</bok>

Fila overfor er velformet, men vi ser at angivelsen av namespace marked er av tvilsom verdi. Det kan være mange som har kommet på denne ideen. Vanligvis ønsker vi derfor å forsøke å gi et namespace et unikt navn. En måte å gjøre dette på er å angi en URN (Uniform Resource Name). Feks. kan vi skrive om fila slik:

<?xml version="1.0"?>
<bok>
   <markedsføring>
      <marked:tittel  xmlns:marked="http://www.forlaget.no/std/marketing.html">
      Verdens beste bok
      </marked:tittel>
      <marked:innhold  xmlns:marked="http://www.forlaget.no/std/marketing.html">
      Solgt i uttallige eksemplarer
      </marked:innhold>
   </markedsføring>
   
   <tittel>
   Ole Brum
   </tittel>
   <ingress>
   Om en teddybjørn og vennene hans
   </ingress>
   <innhold>
   En dag Kristoffer Robin...
   </innhold>
</bok>

Nå ser vi at for selve boka er det ikke angitt noe namespace. Vi kan godt gjøre dette ved å definere en default namespace, og samtidig definerer marked:

<?xml version="1.0"?>
<bok  xmlns="http://www.forlaget.no/std/boker.html"
      xmlns:marked="http://www.forlaget.no/std/marketing.html">
   <markedsføring>
      <marked:tittel>
      Verdens beste bok
      </marked:tittel>
      <marked:innhold>
      Solgt i uttallige eksemplarer
      </marked:innhold>
   </markedsføring>
   
   <tittel>
   Ole Brum
   </tittel>
   <ingress>
   Om en teddybjørn og vennene hans
   </ingress>
   <innhold>
   En dag Kristoffer Robin...
   </innhold>
</bok>

De bibliotekene som vi som programmerere benytter for å analysere XML-dokumenter har funksjoner for å identifisere elementer med angitte namespaces.

Entity

De tegnene som inngår i formateringen av XML er vanskelige å bruke dersom vi skriver dem rett fram. F.eks. vil det være problematisk å skrive <. Programmet som skal tolke XML-fila vil oppfatte dette som betynnelsen på et element. For å unngå dette er det definert et sett med såkalte entities. En entity er en slags definisjon som vi kan bruke, og få det tolket som et spesielt tegn. Vi skriver &navn; dersom vi vil framstille tegnet som har navnet navn.

I XML er følgende entities predefinerte:

  • < som &lt;
  • > som &gt;
  • & som &amp;
  • " som &quot;
  • ' som &apos;

I tillegg til dette kan vi definere våre egne entiteter som en del av DTD. Vi kan skrive:

<?xml version="1.0"?>
<!DOCTYPE bok [<!ENTITY skribent "Børre Stenseth, HIØ">]>
<bok>
  <tittel>
    XML på alle fat
  </tittel>
  <forfatter>
    &skribent;
  </forfatter>
</bok>

Hvis vi ser på spesielle XML-språk, vil vi se at disse ofte har predefinert langt flere entities enn de 5 standard tegnene. F.eks. XHTML har definert entities som angitt i refreransene nedenfor.

Vi kan f.eks. skrive ♣ ♦ ♥ ♠ som &#9827; &#9830; &#9829; &#9824; og vi kan skrive som &#8364;

[1] [2]
Referanser
  1. Namespaces W3C www.w3.org/TR/REC-xml-names/ 14-03-2010
  1. List of character entities Wikipedia en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references 14-03-2014