Obsah
dovolují libovolně procházet ("traverse") vzniklý strom;
nejznámější je Document Object Model (DOM) konsorcia W3C, viz http://www.w3.org/DOM
pro Javu: JDOM - http://jdom.org
pro Javu: dom4j - http://dom4j.org
pro Python: 4Suite - http://4suite.org
technicky realizováno jako volání metod ("callback")
aplikace poskytuje handlery, které volání zachytávají a zpracovávají
událostmi řízená rozhraní jsou "nižší úrovně" než stromová, protože
pro aplikaci zůstává "více práce"
jsou však úspornější na paměť (většinou i čas), samotná analýza totiž nevytváří žádné „trvalé“ objekty
začátek a konec dokumentu (start document, end document)
začátek a konec elementu (start element, end element) - předá současně i atributy
instrukce pro zpracování (processing instruction)
komentář (comment)
odkaz na entitu (entity reference)
Nejznámějším takovým rozhraním je SAX http://www.saxproject.org
<?xml version="1.0"?>
<doc>
<para>Hello, world!</para>
</doc>
vyprodukuje při analýze (parsingu) sled událostí:
start document start element: doc {seznam atributů: prázdný} start element: para {seznam atributů: prázdný} characters: Hello, world! end element: para end element: doc end document
O co snazší pro autora parseru, o to náročnější pro aplikačního programátora...
Aplikace si musí (někdy složitě) pamatovat stav analýzy, nemá nikdy "celý dokument pohromadě".
Na úlohy, které lze řešit "lokálně", bez kontextu celého dokumentu, je to vhodné rozhraní.
Obvykle poskytuje nejrychlejší možné zpracování.
Aplikační nepříjemnosti lze obejít použitím nadstaveb, např. Streaming Transformations for XML (STX)
Chování parseru produkujícího SAX události je možné ovlivnit nastavením tzv. features a properties.
Vlastnosti (features) nastavitelné pro analýzu (parsing) http://www.saxproject.org/?selected=get-set
Blíže k jednotlivým properties a features v článku Use properties and features in SAX parsers (IBM DeveloperWorks/XML).
SAX rozhraní nabízí možnost napsat třídu jako tzv. SAX filtr (přesněji implementaci rozhraní org.xml.sax.XMLFilter).
Objekt takové třídy na jedné straně události přijímá, zpracuje je a posílá dále.
Další informace k filtrování událostí naleznete např. v článku Change the events output by a SAX stream (IBM DeveloperWorks/XML).
"Přímo od zdroje" http://www.saxproject.org
SAX Tutorial k JAXP - http://java.sun.com/webservices/docs/ea1/tutorial/doc/JAXPSAX.html
Aplikace "nečeká na události", ale "vytahuje si" příslušná data ze vstupního parsovaného souboru.
Využíváme tam, kde "víme, co ve zdroji očekávat" a "postupně si to bereme"
... vlastně opak API řízeného událostmi.
Z hlediska aplikačního programátora velmi pohodlné, ale implementace bývají o něco pomalejší než klasická "push" událostmi řízená rozhraní.
Pro Javu existuje XML-PULL parser API - viz Common API for XML Pull Parsing a také
nově vyvíjené rozhraní Streaming API for XML (StAX) vznikající "shora i zdola" jako produkt JCP (Java Community Process).
Příklad 1.1. StAX - přístup iterátorem
import java.io.*;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
public class ParseByEvent {
public static void main(String[] args)
throws FileNotFoundException, XMLStreamException {
// Use the reference implementation for the XML input factory
System.setProperty("javax.xml.stream.XMLInputFactory",
"com.bea.xml.stream.MXParserFactory");
// Create the XML input factory
XMLInputFactory factory = XMLInputFactory.newInstance();
// Create the XML event reader
FileReader reader = new FileReader("somefile.xml");
XMLEventReader r =
factory.createXMLEventReader(reader);
// Loop over XML input stream and process events
while(r.hasNext()) {
XMLEvent e = r.next();
processEvent(e);
}
}
/**
* Process a single XML event
* @param e - the event to be processed
*/
private static void processEvent(XMLEvent e) {
if (e.isStartElement()) {
QName qname = ((StartElement) e).getName();
String namespaceURI = qname.getNamespaceURI();
String localName = qname.getLocalPart();
Iterator iter = ((StartElement) e).getAttributes();
while (iter.hasNext()) {
Attribute attr = (Attribute) iter.next();
QName attributeName = attr.getName();
String attributeValue = attr.getValue();
}
}
if (e.isEndElement()) {
QName qname = ((EndElement) e).getName();
}
if (e.isCharacters()) {
String text = ((Characters) e).getData();
}
if (e.isStartDocument()) {
String version = ((StartDocument) e).getVersion();
String encoding = ((StartDocument) e).getCharacterEncodingScheme();
boolean isStandAlone = ((StartDocument) e).isStandalone();
}
}
}
Poznámka | |
---|---|
příklad převzat z Tip: Use XML streaming parsers (IBM DeveloperWorks, sekce XML). |
Příklad 1.2. StAX - přístup kurzorem
import java.io.*;
import javax.xml.stream.*;
public class ParseByIterator {
public static void main(String[] args)
throws FileNotFoundException, XMLStreamException {
// Use reference implementation
System.setProperty(
"javax.xml.stream.XMLInputFactory",
"com.bea.xml.stream.MXParserFactory");
// Create an input factory
XMLInputFactory xmlif = XMLInputFactory.newInstance();
// Create an XML stream reader
XMLStreamReader xmlr =
xmlif.createXMLStreamReader(new FileReader("somefile.xml"));
// Loop over XML input stream and process events
while (xmlr.hasNext()) {
processEvent(xmlr);
xmlr.next();
}
}
/**
* Process a single event
* @param xmlr - the XML stream reader
*/
private static void processEvent(XMLStreamReader xmlr) {
switch (xmlr.getEventType()) {
case XMLStreamConstants.START_ELEMENT :
processName(xmlr);
processAttributes(xmlr);
break;
case XMLStreamConstants.END_ELEMENT :
processName(xmlr);
break;
case XMLStreamConstants.SPACE :
case XMLStreamConstants.CHARACTERS :
int start = xmlr.getTextStart();
int length = xmlr.getTextLength();
String text =
new String(xmlr.getTextCharacters(), start, length);
break;
case XMLStreamConstants.COMMENT :
case XMLStreamConstants.PROCESSING_INSTRUCTION :
if (xmlr.hasText()) {
String piOrComment = xmlr.getText();
}
break;
}
}
private static void processName(XMLStreamReader xmlr) {
if (xmlr.hasName()) {
String prefix = xmlr.getPrefix();
String uri = xmlr.getNamespaceURI();
String localName = xmlr.getLocalName();
}
}
private static void processAttributes(XMLStreamReader xmlr) {
for (int i = 0; i < xmlr.getAttributeCount(); i++)
processAttribute(xmlr, i);
}
private static void processAttribute(XMLStreamReader xmlr, int index) {
String prefix = xmlr.getAttributePrefix(index);
String namespace = xmlr.getAttributeNamespace(index);
String localName = xmlr.getAttributeName(index);
String value = xmlr.getAttributeValue(index);
}
}
Poznámka | |
---|---|
příklad převzat z Tip: Use XML streaming parsers (IBM DeveloperWorks, sekce XML). |
Tutoriál k JAXP, část věnovaná DOMPart III: XML and the Document Object Model (DOM)
Portál věnovaný DOM http://www.oasis-open.org/cover/dom.html
Vizuální přehled DOM 1 rozhraní http://www.xml.com/pub/a/1999/07/dom/index.html
Tutoriál "Understanding DOM (Level 2)" na http://ibm.com/developer/xmlhttp://ibm.com/developer/xml
v mnoha parserech, např. Xerces
jako součást JAXP (Java API for XML Processing) - http://java.sun.com/xml/jaxp/index.html
i jako samostatné, nezávislé na parserech:
např. dom4j - http://dom4j.org
EXML (Electric XML) - http://www.themindelectric.net
XOM (XML Object Model) vznikl jako one-man-show projekt (autor Elliote Rusty Harold) rozhraní, které je "papežštější než papež" a striktně respektuje model XML dat.
Motivaci a specifikaci najdete na domovské stránce XOM.
Tam je též k získání open-source implementace XOM a
velmi malé (co do velikosti kódu) stromové rozhraní a parser v jednom
dostupné jako open-source na http://nanoxml.n3.net
adaptované též pro mobilní zařízení
z hlediska rychlosti a paměťové efektivity za běhu ale nejlepší není
pohodlné, rychlé a pamětově efektivní stromově-orientované rozhraní
psané pro Javu, optimalizované pro Javu...
dostupné jako open-source na http://dom4j.org
nabízí perfektní přehled díky "kuchařce"
dom4j je výkonný, viz srovnání efektivity jednotlivých stromových modelů
DOM model dokumentu není přítomen v paměti, je zprostředkováván "on demand" při přístupu k jednotlivým uzlům
spojuje výhody událostmi řízeného a stromového modelu zpracování (rychlost + komfort)
implementován např. u procesoru Sablotron (např. viz http://www.xml.com/pub/a/2002/03/13/sablotron.html nebo http://www.gingerall.org/charlie/ga/xml/p_sab.xml)