DOM
SAX
XML
Børre Stenseth

DOM

Hva

Velformede XML-dokumenter lar seg beskrive i en trestruktur, Document Object Model. Hvert element kan ha høyst en forelder og ingen, en eller flere barn. Det som gjør et DOM-tre litt komplisert er at det finnes flere nodetyper enn de vi intuitivt assosierer med elementer. Vi må i tillegg ha en plass til attributtene i treet og til innholdet i elementene.

DOM

DOM-begrepet er interessant i forhold til HMTL på flere måter. W3C arbeidet lenge med å forsøke å få fram velformede HTML-formater (XHTML) for nettop å gjøre parsing og behandling enklere. De seneste åren er det HTML5 som har overtatt som en de facto standard. HTML5 er ikke nødvendigvis velformet. Vi kan ha tagger som ikke avsluttes (<img src="pic.png" alt="?">) og vi kan ha attributter som ikke har noen verdi (<p contenteditable>). Dette stiller større krav til parseren i nettleseren. Når vi bruker utviklerverktøy i nettleseren ser vi at elementene framstår som XML-korrekte når vi inspiserer HTML-strukturen. Heldigvis kan vi selvsagt skrive formelt korrekt-XML i HTML5, altså angi alle attributtverdier og avslutte tagger korrekt. Dette er en fordel for oss som ønsker å bearbeide våre vevsider via verktøy med enklere parsere enn de som er implemnterte i nettleserne.

Vi tar for oss en XML fil som beskriver sprintresultater fra de seneste olympiadene all_results.xml

Rent intuitivt kan elementene i et dokument beskrives slik:

dom

Dette gir oss en grov ide av hva en DOM er, men i praktisk bruk er det ikke nok å ha et tre som bare har elementene. Vi har flere nodetyper å holde styr på, og et DOM-tre blir fort ganske omfattende. Nedenfor er en oversikt over alle mulige nodetyper og hva slags barn de kan ha i et DOM-tre:

Nodetype Mulige barn
Document Element (maks 1), ProcessingInstruction, Comment, DocumentType
DocumentFragment Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
DocumentType ingen
EntityReference Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
Element Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference
Attr Text, EntityReference
ProcessingInstruction ingen
Comment ingen
Text ingen
CDATASection ingen
Entity Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference
Notation ingen

Merk at attributter ikke betraktes som barn av et element. DOM betrakter attributter som egenskaper ved et element. Et mer komplett DOM-tre vil således se slik ut:

dom2

Klassestruktur for DOM-noder

W3C definerer ikke bare strukturen i et DOM-tre. De har også definert en klassestruktur for å bearbeide DOM-trær. Hos W3C er denne klassestrukturen beskrevet i Java-syntaks. Grafisk kan klassestrukturen beskrives slik:

Klassehierarki for DOM-noder

De hvite boksene beskriver klasser som er generelle for XML-dokumenter, mens de gule er de tilleggene som er nødvendig for å beskrive HTML-dokumenter spesielt.

Dette gir grunnlaget for hvordan et klassebibliotek for handtering av DOM-strukturer skal implementeres i et objektorientert språk som Java, C++, Python.

Funksjonalitet

Nedenfor finner du en list over metoder som er definert for de enkelte objeckttypene. Oversikten er psedudo-Java. Parametrene er utelatt og det angis ikke hvilke metoder som fører til exceptions. Hensikten er bar å gi en oversikt. For detaljer kan du se referansen som er angitt nedenfor.

public interface DOMImplementation {
  public boolean hasFeature(..);
}
public interface DocumentFragment extends Node {
}
public interface Document extends Node {
  public DocumentType       getDoctype();
  public DOMImplementation  getImplementation();
  public Element            getDocumentElement();
  public Element            createElement(...)
  public DocumentFragment   createDocumentFragment();
  public Text               createTextNode(...);
  public Comment            createComment(...);
  public CDATASection       createCDATASection(..)
  public ProcessingInstruction createProcessingInstruction(...)
  public Attr               createAttribute(...)
  public EntityReference    createEntityReference(...)
  public NodeList           getElementsByTagName(...);
}
public interface Node {
  // NodeType
  public static final short           ELEMENT_NODE         = 1;
  public static final short           ATTRIBUTE_NODE       = 2;
  public static final short           TEXT_NODE            = 3;
  public static final short           CDATA_SECTION_NODE   = 4;
  public static final short           ENTITY_REFERENCE_NODE = 5;
  public static final short           ENTITY_NODE          = 6;
  public static final short           PROCESSING_INSTRUCTION_NODE = 7;
  public static final short           COMMENT_NODE         = 8;
  public static final short           DOCUMENT_NODE        = 9;
  public static final short           DOCUMENT_TYPE_NODE   = 10;
  public static final short           DOCUMENT_FRAGMENT_NODE = 11;
  public static final short           NOTATION_NODE        = 12;
  public String             getNodeName();
  public String             getNodeValue()
  public void               setNodeValue(...)
  public short              getNodeType();
  public Node               getParentNode();
  public NodeList           getChildNodes();
  public Node               getFirstChild();
  public Node               getLastChild();
  public Node               getPreviousSibling();
  public Node               getNextSibling();
  public NamedNodeMap       getAttributes();
  public Document           getOwnerDocument();
  public Node               insertBefore(...)
  public Node               replaceChild(...)
  public Node               removeChild(...)
  public Node               appendChild(...)
  public boolean            hasChildNodes();
  public Node               cloneNode(...);
}
public interface NodeList {
  public Node               item(...);
  public int                getLength();
}
public interface NamedNodeMap {
  public Node               getNamedItem(...);
  public Node               setNamedItem(...)
  public Node               removeNamedItem(...)
  public Node               item(...);
  public int                getLength();
}
public interface CharacterData extends Node {
  public String             getData()
  public void               setData(...)
  public int                getLength();
  public String             substringData(...)
  public void               appendData(...)
  public void               insertData(...)
  public void               deleteData(...)
  public void               replaceData(...)
}
public interface Attr extends Node {
  public String             getName();
  public boolean            getSpecified();
  public String             getValue();
  public void               setValue(String value);
}
public interface Element extends Node {
  public String             getTagName();
  public String             getAttribute(...);
  public void               setAttribute(...)
  public void               removeAttribute(...)
  public Attr               getAttributeNode(...);
  public Attr               setAttributeNode(...)
  public Attr               removeAttributeNode(...)
  public NodeList           getElementsByTagName(...);
  public void               normalize();
}
public interface Text extends CharacterData {
  public Text               splitText(...)
}
public interface Comment extends CharacterData {
}
public interface CDATASection extends Text {
}
public interface DocumentType extends Node {
  public String             getName();
  public NamedNodeMap       getEntities();
  public NamedNodeMap       getNotations();
}
public interface Notation extends Node {
  public String             getPublicId();
  public String             getSystemId();
}
public interface Entity extends Node {
  public String             getPublicId();
  public String             getSystemId();
  public String             getNotationName();
}
public interface EntityReference extends Node {
}
public interface ProcessingInstruction extends Node {
  public String             getTarget();
  public String             getData();
  public void               setData(...)
}

Alle moderne språk har biblioteker som handterer DOM. I dette materialet vil du finne eksempler for Python og for Jacascript. Bibliotekene for Java og for .Net-språkene (C# og VB) er bedre utbygd.

[1]
Referanser
  1. DOM (Document Object Model) W3C www.w3.org/DOM/ 14-03-2014