Das Package org.xml.sax.helpers

(Auszug aus "XML in a Nutshell" von Elliotte Rusty Harold & W. Scott Means)

Das Package org.xml.sax.helpers enthält Hilfsklassen des SAX-Kerns. Dazu gehören zum Beispiel Factory-Klassen, die Instanzen der verschiedenen org.xml.sax-Interfaces erzeugen, und Standardimplementierungen der Interface-Klassen, von denen man eigene Implementierungen ableiten kann.

 


Die Klasse AttributesImpl

AttributesImpl ist eine Standardimplementierung des Interfaces Attributes für SAX-Parser. Neben den Methoden des Attributes-Interfaces bietet diese Klasse Möglichkeiten zur Manipulation oder zur Wiederverwendung einer Attributliste. Man kann also innerhalb von startElement() eine Attributliste für den späteren Gebrauch »einfrieren« oder ein komplett neues Attributes-Objekt aufbauen, das man in einem SAX-Filter weitergibt:

package org.xml.sax.helpers;

public class AttributesImpl implements Attributes {

    public AttributesImpl( );
    public AttributesImpl(Attributes atts);
    public int    getLength( );
    public String getURI(int index);
    public String getLocalName(int index);
    public String getQName(int index);
    public String getType(int index);
    public String getValue(int index);
    public int    getIndex(String uri,String localName);
    public int    getIndex(String qualifiedName);
    public String getType(String uri, String localName);
    public String getType(String qualifiedName);
    public String getValue(String uri, String localName);
    public String getValue(String qualifiedName);
    public void   clear( );
    public void   setAttributes(Attributes atts);
    public void   addAttribute(String uri, String localName,
     String qualifiedName, String type, String value);
    public void  setAttribute(int index, String uri, String localName,
     String qualifiedName, String type, String value);
    public void  removeAttribute(int index)
    public void  setURI(int index, String
 uri)  public void  setLocalName(int index, String localName)
    public void  setQName(int index, String qualifiedName);
    public void  setType(int index, String type);
    public void  setValue(int index, String value);

}

 


Die Klasse DefaultHandler

Ein DefaultHandler ist eine Hilfsklasse, die die Interfaces EntityResolver, DTDHandler, ContentHandler und ErrorHandler implementiert, allerdings mit Methoden, die meistens gar nichts bewirken. Der Sinn dieser Klasse ist, dass man davon bequem eigene Unterklassen ableiten kann, um nur ganz bestimmte gewünschte Methoden zu überschreiben. Wenn Sie die Klasse nicht benutzen wollen, können Sie sie problemlos ignorieren und das benötigte Interface direkt implementieren. Die Vorgehensweise entspricht den Adapterklassen aus AWT, z.B. MouseAdapter oder WindowAdapter:

package org.xml.sax.helpers;

public class DefaultHandler implements EntityResolver, DTDHandler,
 ContentHandler, ErrorHandler {

// Standardimplementierung des Interfaces EntityResolver public InputSource
 resolveEntity(String publicID, String systemID)
throws SAXException {
return null;
}

 // Standardimplementierung des Interfaces DTDHandler
public void notationDecl(String name,
 String publicID, String systemID)  throws SAXException {}
public void unparsedEntityDecl(String
 name, String publicID,  String
 systemID, String notationName) throws SAXException{}

// Standardimplementierung des Interfaces ContentHandler
public void setDocumentLocator(Locator locator) {}
 public void startDocument( ) throws SAXException {}
 public void endDocument( ) throws SAXException {}
 public void startPrefixMapping(String prefix, String uri)
 throws SAXException {}
 public void endPrefixMapping(String prefix) throws SAXException {}
 public void startElement(String uri, String localName,
 String qualifiedName, Attributes attributes) throws SAXException {}
 public void endElement(String uri, String localName,
String qualifiedName) throws SAXException {}
 public void characters(char[] text, int
 start, int length)  throws SAXException {}
 public void ignorableWhitespace(char[]
 whitespace, int start,  int length)
 throws SAXException {} public void processingInstruction(String
 target, String data)
throws SAXException {}
 public void skippedEntity(String name) throws SAXException {}

// Standardimplementierung des Interfaces ErrorHandler
 public void warning(SAXParseException ex) throws SAXException {}
 public void error(SAXParseException ex) throws SAXException {}
 public void fatalError(SAXParseException ex) throws SAXException {
   throw ex;
 }

}

 


Die Klasse LocatorImpl

Eine weitere Standardimplementierung ist LocatorImpl: Diese Klasse implementiert das Interface Locator und kann von Autoren eines Parsers benutzt werden. Sie wird eher selten direkt benutzt. Abgesehen vom Konstruktor definiert diese Klasse auch set-Methoden für den PUBLIC-Identifier, den SYSTEM-Identifier, die Zeilen- und Spaltennummer, die dann von den get-Methoden aus Locator gelesen werden:

package org.xml.sax.helpers;

public class LocatorImpl implements Locator {

    public LocatorImpl();
    public LocatorImpl(Locator locator);

    public String getPublicId();
    public String getSystemId();
    public int    getLineNumber();
    public int    getColumnNumber();
    public void   setPublicId(String publicID);
    public void   setSystemId(String systemID);
    public void   setLineNumber(int lineNumber);
    public void   setColumnNumber(int columnNumber);

}

 


Die Klasse NamespaceSupport

Die Klasse NamespaceSupport unterstützt die Autoren eines Parsers bei der Behandlung von Namensräumen. Wenn Sie diese Klasse verwenden, sollten Sie zu Beginn der Namensraum-Abbildungen jedes Elements einen neuen Kontext auf den Stack schieben, den Sie beim Ende des Elements dann wieder entfernen. Bei jedem Aufruf der startPrefixMapping()-Methode sollten Sie erneut declarePrefix() aufrufen, um dem NamespaceSupport-Objekt ein neues Präfix hinzuzufügen. Wenn Sie dann einem URI ein Präfix zuordnen wollen, brauchen Sie dazu nur noch die Methode getPrefix() aufzurufen. Der Leer-String steht für den Default-Namensraum. Wenn Sie so vorgegangen sind, können Sie anschließend an jeder Stelle im Dokument über die getter-Methoden herausfinden, welcher URI welchem Präfix zugeordnet ist und umgekehrt. Sollten Sie dasselbe NamespaceSupport-Objekt in mehreren Dokumenten verwenden, rufen Sie die Methode reset() auf, wenn Sie in ein anderes Dokument gewechselt sind.

package org.xml.sax.helpers;

public class NamespaceSupport {

 public final static String XMLNS="http://www.w3.org/XML/1998/namespace"

  public NamespaceSupport();

  public void        reset();
  public void        pushContext();
  public void        popContext();
  public boolean     declarePrefix(String prefix, String uri);
  public String[]    processName(String qualifiedName, String[] parts,
   boolean isAttribute);
  public String      getURI(String prefix);
  public Enumeration getPrefixes();
  public String      getPrefix(String uri);
  public Enumeration getPrefixes(String uri);
  public Enumeration getDeclaredPrefixes();

}

 


Die Klasse ParserAdapter

Die Klasse ParserAdapter benutzt das Designmuster eines Adapters, um einen SAX1-Parser, d.h. eine Instanz der Klasse org.xml.sax.Parser, in einen SAX2-Parser, d.h. in eine Instanz der Klasse org.xml.sax.XMLReader, umzuwandeln. Da mehr und mehr Parser SAX2 unterstützen, wird diese Klasse auf Dauer wohl überflüssig werden. Beachten Sie, dass einige Features von SAX2 natürlich nicht unterstützt werden, wenn man einen SAX1-Parser über den ParserAdapter benutzt. Zum Beispiel gibt ein Parser, der mit diesem Adapter erzeugt wurde, keine Informationen über übergangene Entities aus. Darüber hinaus unterstützt er die meisten Features und Properties nicht. Er unterstützt nicht einmal die Basis-Features und Properties, die sonst immer unterstützt werden.

package org.xml.sax.helpers;

public class ParserAdapter implements XMLReader, DocumentHandler {

  public ParserAdapter() throws SAXException;
  public ParserAdapter(Parser parser);
// Standardimplementierung von org.xml.sax.XMLReader
public void           setFeature(String name, boolean state)
 throws SAXNotRecognizedException, SAXNotSupportedException;
public boolean        getFeature(String name)
 throws SAXNotRecognizedException, SAXNotSupportedException;
public void           setProperty(String name, Object value)
 throws SAXNotRecognizedException, SAXNotSupportedException;
public Object         getProperty(String name)
 throws SAXNotRecognizedException, SAXNotSupportedException;
public void           setEntityResolver(EntityResolver resolver);
public EntityResolver getEntityResolver();
public void           setDTDHandler(DTDHandler handler);
public DTDHandler     getDTDHandler();
public void           setContentHandler(ContentHandler handler);
public ContentHandler getContentHandler();
public void           setErrorHandler(ErrorHandler handler);
public ErrorHandler   getErrorHandler();
public void           parse(String systemID) throws IOException, SAXException;
public void           parse(InputSource input) throws IOException, SAXException;

// Standardimplementierung von org.xml.sax.DocumentHandler
public void setDocumentLocator(Locator locator);
public void startDocument() throws SAXException;
public void endDocument() throws SAXException;
public void startElement(String qualifiedName,
 AttributeList qualifiedAttributes) throws SAXException;
public void endElement(String qualifiedName) throws SAXException;
public void characters(char[] text, int start, int length)
 throws SAXException;public void ignorableWhitespace(char[]
 text, int start, int length)
  throws SAXException;
public void processingInstruction(String target, String data)
  throws SAXException;
}

 


Die Klasse XMLFilterImpl

Die Klasse XMLFilterImpl ist sehr hilfreich bei der Implementierung eigener XML-Filter. Eine Instanz dieser Klasse kann man zwischen einen XMLReader und die EventHandler des Anwendungsprogramms setzen. Der Filter empfängt Events vom XMLReader und gibt sie unverändert an die Anwendung weiter. Die Idee ist, dass man eine Unterklasse ableiten und gezielt einige Methoden überschreiben kann, um so das gewünschte Ereignis zu erhalten. Sie verketten einen XMLReader mit einem Filter, indem Sie den XMLReader als Argument an den Konstruktor des Filters übergeben. Anschließend sollten Sie nicht die parse()-Methode des XMLReader, sondern die des Filters aufrufen:

package org.xml.sax.helpers;

public class XMLFilterImpl implements XMLFilter, EntityResolver,
 DTDHandler, ContentHandler, ErrorHandler {

  public XMLFilterImpl();
  public XMLFilterImpl(XMLReader parent);
// Implementierung von org.xml.sax.XMLFilter
  public voidsetParent(XMLReader parent);
  public XMLReader getParent();

  // Implementierung von org.xml.sax.XMLReader
  public void           setFeature(String name, boolean state)
   throws SAXNotRecognizedException, SAXNotSupportedException;
  public boolean        getFeature(String name)
   throws SAXNotRecognizedException, SAXNotSupportedException;
  public void           setProperty(String name, Object value)
   throws SAXNotRecognizedException, SAXNotSupportedException;
  public Object         getProperty(String name)
   throws SAXNotRecognizedException, SAXNotSupportedException;
  public void           setEntityResolver(EntityResolver resolver);
  public EntityResolver getEntityResolver();
  public void           setDTDHandler(DTDHandler handler);
  public DTDHandler     getDTDHandler();
  public void           setContentHandler(ContentHandler handler);
  public ContentHandler getContentHandler();
  public void           setErrorHandler(ErrorHandler handler);
  public ErrorHandler   getErrorHandler();
  public void parse(InputSource input) throws SAXException, IOException;
  public void parse(String systemID) throws SAXException, IOException

  // Implementierung von org.xml.sax.EntityResolver
  public InputSource resolveEntity(String publicID, String systemID)
   throws SAXException, IOException;

  // Implementierung von org.xml.sax.DTDHandler
  public void notationDecl(String name,
 String publicID, String systemID)    throws SAXException;
  public void unparsedEntityDecl(String name, String publicID,
   String systemID, String notationName) throws SAXException;
  // Implementierung von org.xml.sax.ContentHandler
  public void setDocumentLocator(Locator locator);
  public void startDocument() throws SAXException;
  public void endDocument() throws SAXException;
  public void startPrefixMapping(String prefix, String uri)
   throws SAXException;
  public void endPrefixMapping(String prefix) throws SAXException;
  public void startElement(String namespaceURI, String localName,
   String qualifiedName, Attributes atts) throws SAXException;
  public void endElement(String namespaceURI, String localName,
 String qualifiedName) throws SAXException;
  public void characters(char[] text, int start, int length)
   throws SAXException;
  public void ignorableWhitespace(char[] text, int start, int length)
   throws SAXException;
  public void processingInstruction(String target, String data)
   throws SAXException;public void skippedEntity(String name) throws SAXException;
// Implementierung von org.xml.sax.ErrorHandler
  public void warning(SAXParseException ex) throws SAXException;
  public void error(SAXParseException ex) throws SAXException;
  public void fatalError(SAXParseException ex) throws SAXException;

}

 


Die Klasse XMLReaderAdapter

Ein XMLReaderAdapter ist das Gegenstück eines ParserAdapter: Er benutzt das Designmuster eines Adapters, um einen XMLReader von SAX2 in einen Parser von SAX1 zu verwandeln. Man kann damit einen modernen SAX2-Parser in einer älteren Anwendung verwenden, die für SAX1-Parser geschrieben wurde:

package org.xml.sax.helpers;

public class XMLReaderAdapter implements Parser, ContentHandler {


public XMLReaderAdapter() throws SAXException;
public XMLReaderAdapter(XMLReader reader);

// Implementierung von org.xml.sax.Parser
public void setLocale(Locale locale) throws SAXException;
public void setEntityResolver(EntityResolver resolver);
public void setDTDHandler(DTDHandler handler);
public void setDocumentHandler(DocumentHandler handler);
public void setErrorHandler(ErrorHandler handler);
public void parse(String systemID) throws IOException, SAXException;
public void parse(InputSource input) throws IOException, SAXException

// Implementierung von org.xml.sax.ContentHandler
public void setDocumentLocator(Locator locator);
public void startDocument() throws SAXException;
public void endDocument() throws SAXException;
public void startPrefixMapping(String prefix, String uri) throws SAXException;
public void endPrefixMapping(String
 prefix) throws SAXException;public void
 startElement(String namespaceURI, String localName,
String qualifiedName, Attributes atts) throws SAXException;
public void endElement(String
 namespaceURI, String localName, String qualifiedName) throws SAXException;
public void characters(char[] text, int
 start, int length) throws SAXException;
public void ignorableWhitespace(char[]
 text, int start, int length) throws SAXException;
public void processingInstruction(String
 target, String data) throws SAXException;
public void skippedEntity(String name) throws SAXException;

}

 


Die Klasse XMLReaderFactory

Die Klasse XMLReaderFactory erzeugt eine XMLReader-Instanz in einer Art und Weise, die vom konkreten Parser unabhängig ist. Es gibt eine Methode createXMLReader() ohne Argumente, die ein System-Property org.xml.sax.driver liest: Dieses enthält den Namen einer Klasse, die XMLReader implementiert. Will man einen bestimmten Parser, übergibt man den Namen der XMLReader-Klasse an die andere createXMLReader()-Methode, die ein Argument erhält. Dabei sollte es sich um einen vollqualifizierten Namen wie org.apache.xerces.parsers.SAXParser handeln:

package org.xml.sax.helpers;

public final class XMLReaderFactory {

  public static XMLReader createXMLReader() throws SAXException;
  public static XMLReader createXMLReader(String className)
   throws SAXException;

}
Tipp der data2type-Redaktion:
Zum Thema XML bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

  


Copyright © 2005 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XML in a Nutshell" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de