Home > Articles

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

SAX Error Handling

Most SAX interface methods throw SAXException. SAXException extends java.lang.Exception and adds one fundamental feature, which is the ability to piggyback an arbitrary exception inside of a SAXException. This allows implementations to propagate non-SAX-related exceptions across SAX interface method boundaries. Consider the following implementation of ContentHandler.characters:

void characters(char[] ch, int offset, int length)
                    throws org.xml.sax.SAXException {
  try {
    this.out.write(ch, offset, length);
  }
  catch (java.io.IOException ex) {
    throw new org.xml.sax.SAXException(ex);
  }
}

This implementation embeds a java.io.IOException inside the SAXException that it is required to throw. Callers can then scrape out the exception by calling the SAXException.getException method as follows:

void emit11(org.xml.sax.ContentHandler handler) {
  try {
    char[] rgch = "Hello".toCharArray();
    handler.characters(rgch, 0, rgch.length);
  }
  catch(org.xml.sax.SAXException sex) {
    java.lang.Exception ex = sex.getException();
    if (ex == null) // no embedded exception
      logerror("SAXException thrown");
    else
      logerror(ex.getClass().getName() + "thrown");
  }
}

SAXException is functionally identical to java.lang.Exception beyond this feature of embedding a nested exception.

As shown in Figure 2.2, there are three extended exception types in SAX beyond SAXException. Of these three types, the most commonly used is SAXParseException. SAXParseException is used to indicate a processing error while deserializing an XML document. In addition to indicating that the exception was parse-related, SAXParseException exposes the four properties supported by Locator: system identifier, public identifier, line number, and column number.

Figure 2.2Figure 2.2. SAX2 exceptions.


Exceptions of type SAXException are generally thrown by Content Handler implementations and caught by ContentHandler consumers. For many scenarios, this is reasonable, as the ContentHandler implementation typically can perform application-specific validation and communicate constraint violations by throwing exceptions from startElement and friends. However, there are scenarios where the consumer of ContentHandler wishes to abort the stream of method invocations due to a caller-side error. The most common scenario is of course when an XML parser who is calling your ContentHandler implementation needs to report a parse error detected in the underlying serialized XML document. To support reporting error information in that direction, SAX defines the ErrorHandler interface, whose Java version is shown here:

package org.xml.sax;
public interface ErrorHandler {
  void warning (SAXParseException exception)
                     throws SAXException;
  void error (SAXParseException exception)
                    throws SAXException;
  void fatalError (SAXParseException exception)
                    throws SAXException;
}

This interface is typically implemented alongside ContentHandler when interfacing with an XML parser.

Section 1.2 of the XML 1.0 recommendation details two forms of processing errors: errors and fatal errors. The error and fatalError methods will be called in response to these two conditions, respectively. Fatal errors are either violations of XML's well-formedness rules (1.2), encountering an unrecognized character encoding (4.3.3), or certain illegal uses of entity or character references (4.4.4). Nonfatal errors are typically violations of validity constraints imposed by element and attribute list declarations (3.2.1) and XML version mismatches (2.8). Exceptional conditions that are less serious than error or fatal error are reported via the warning method. In all cases the parser will provide a SAXParseException that indicates where the parse error occurred. Provided the ErrorHandler implementation does not throw an exception, the parser will continue processing after a warning or error. A parser may continue processing after a fatalError, but any subsequent ContentHandler invocations are of questionable use.

  • + Share This
  • 🔖 Save To Your Account