SAX, skrót dla Simple API for XML, jest parserem API. Po raz pierwszy SAX został szeroko zadoptowany w API dla XML w Javie i później został zaimplementowany w kilku innych środowiskach programowania. Wraz z Firefoksem 2, parser SAX jest dostępny w aplikacjach XUL i rozszerzeniach. Aby zdobyć dodatkowe informacje, odwiedź stronę domową SAX.
Szybki start
Funkcjonalność parsera SAX jest dostępna poprzez interfejs XML reader component. Aby go utworzyć, zastosuj poniższy kod:
var xmlReader = Components.classes["@mozilla.org/saxparser/xmlreader;1"] .createInstance(Components.interfaces.nsISAXXMLReader);
Po utworzeniu parsera SAX, będzie potrzebne ustawienie podprogramów obsługi dla zdarzeń, którymi jesteśmy zainteresowani and fire off the parsing process. Cała funkcjonalnośc jest dostępna poprzez interfejs nsISAXXMLReader.
Ustawienie obiektów obsługi
Obiekty obsługi (określone przez użytkownika) są zdefiniowanymi obiektami zaimplementowanymi w programie obsługi interfejsu SAX, które są zależne od rodzaju informacji, jaki chcemy otrzymać z parsera. Po rozpoczęciu procesu parsowania, obiekty obsługi przyjmują szereg wywołań zwrotnych dla treści XML, która jest parsowana. Dostępne są następujące obiekty obsługi:
Interfejs | Zastosowanie |
---|---|
nsISAXContentHandler | Pakiet obiektu obsługuje zawartość logiczną dokumentu (np. elementy, atrybuty, białe znaki oraz instrukcje przetwarzania). |
nsISAXDTDHandler | Pakiet obiektu obsługuje proste podobne do DTD zdarzenia. |
nsISAXErrorHandler | Pakiet obsługi błędów strumienia wejściowego. |
nsISAXLexicalHandler | Rozszerzenie obiektu SAX2 dla zdarzeń struktur leksykalnych (np. komentarzy i sekcji CDATA, deklaracji DTD oraz encji). |
Przykład implementacji najczęściej stosowanych obiektów obsługi:
function print(s) { dump(s + "\n"); } xmlReader.contentHandler = { // nsISAXContentHandler startDocument: function() { print("startDocument"); }, endDocument: function() { print("endDocument"); }, startElement: function(uri, localName, qName, /*nsISAXAttributes*/ attributes) { var attrs = []; for(var i=0; i<attributes.length; i++) { attrs.push(attributes.getQName(i) + "='" + attributes.getValue(i) + "'"); } print("startElement: namespace='" + uri + "', localName='" + localName + "', qName='" + qName + "', attributes={" + attrs.join(",") + "}"); }, endElement: function(uri, localName, qName) { print("endElement: namespace='" + uri + "', localName='" + localName + "', qName='" + qName + "'"); }, characters: function(value) { print("characters: " + value); }, processingInstruction: function(target, data) { print("processingInstruction: target='" + target + "', data='" + data + "'"); }, ignorableWhitespace: function(whitespace) { // don't care }, startPrefixMapping: function(prefix, uri) { // don't care }, endPrefixMapping: function(prefix) { // don't care }, // nsISupports QueryInterface: function(iid) { if(!iid.equals(Components.interfaces.nsISupports) && !iid.equals(Components.interfaces.nsISAXContentHandler)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; } };
Rozpoczęcie parsowania
XML Reader component potrafi parsować XML z łańcucha znakowego, nsIInputStream lub asynchronicznie przez interfejs nsIStreamListener. Poniżej znajduje się przykład parsowania z łańcucha znakowego:
xmlReader.parseFromString("<f:a xmlns:f='g' d='1'><BBQ/></f:a>", "text/xml");
Wywoła to następującym rezultat na wyjściu (biorąc na siebie zawartość obiektu obsługi stosując przykład powyżej):
startDocument startElement: namespace='g', localName='a', qName='f:a', attributes={d='1'} startElement: namespace='', localName='BBQ', qName='BBQ', attributes={} endElement: namespace='', localName='BBQ', qName='BBQ' endElement: namespace='g', localName='a', qName='f:a' endDocument