DOM og SAX
DOM
Rent intuitivt kan elementene i et dokument fra vårt olympiade eksempel, se modulen Noen datasett , beskrives slik:
![Olympiske sprintresultater dom](odom.gif)
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:
![Olympiske sprintresultater med attributter dom2](fulldom.gif)
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](domhtmlclasshierarchy.gif)
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](saxstream.gif)
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.