!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

DOM
SAX
Børre Stenseth
XML >DOM og SAX

DOM og SAX

Hva
Introduksjon av DOM, Document Object Model.

Velformede XML-dokumenter lar seg beskrive i en trestruktur. 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

Rent intuitivt kan elementene i et dokument fra vårt olympiade eksempel, se modulen Noen datasett , 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.

SAX

Det er for de fleste formål hensiktsmessig å betrakte et XML-dokument som en trestruktur. DOM (Document Object Model) er en trestruktur. Trær er enkle å forstå rent konseptuelt og det er relativt enkelt å programmere mot trestrukturer. Det finnes standardiserte måter å bearbeide trær på, i tillegg til den API'en som er beskrevet for DOM. Det kan imidlertid virke litt overdrevet å etablere en trestruktur når vi skal gjøre enkle søk eller utdrag fra dokumenter. Det er ønsket om en forenklet analysemekanisme som er bakgrunnen for SAX. SAX er ikke definert av W3C. Det er resultat av uformelt samarbeid mellom en del programvareleverandører, se referanse nedenfor.

SAX er basert på en sekvensiell gjennomgang av den aktuelle xml-fila. SAX-biblioteker er bygget slik at de gir en melding tilbake til det kallende programmet når et element "intreffer" i strømmen. Det er opp til oss som programmerere å finne ut hva vi skal foreta oss når en begivenhet intreffer og hvor mye vi ønsker å "huske" av tidligere begivenheter.

SAX betraktet som eventhandler

Og det er opp til oss å skrive en StartEventHandler (som på figuren over), og andre events som SAX-parseren genererer og som vi er interesserte i.

Ulempen med SAX er at vi ikke har noe hjelp i å analysere kontekst. Vi vet ikke noe om omgivelsene til den begivenheten vi får melding om. Vi kan selvsagt huske tidligere meldinger og på den måte danne oss et bilde av xml-strukturen, men dette blir fort ganske komplisert. I ytterste konsekvens kan vi ende opp med å implementere DOM.

Fordelen med SAX er at det er enkelt for enkle oppgaver, og det er lite hukommelseskrevende.

Modulen: SAX i Python viser noen eksempler på bruk av SAX i Python.

Referanser
  1. DOM (Document Object Model) W3C www.w3.org/TR/REC-DOM-Level-1/ 14-03-2010
  1. SAX saxproject.org www.saxproject.org/ 14-03-2010
Vedlikehold
Børre Stenseth, revidert juli 2009
( Velkommen ) XML >DOM og SAX ( Noen XML-språk )