The Xerces-J SAX parser supports validation with the W3C XML Schema Language. By default, it reads the schema with which to validate documents from the xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes in the instance document. However, you can override these with the http://apache.org/xml/properties/schema/external-schemaLocation and http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation SAX properties. In this example, the documents being validated have namespaces, so we'll set http://apache.org/xml/properties/schema/external-schemaLocation to http://www.example.com/tvprogram.xsd . Then, we'll turn on schema validation by setting the http://apache.org/xml/features/validation/schema feature to true.

 XMLReader parser = XMLReaderFactor.createXMLReader(  "org.apache.xerces.parsers.SAXParser"); parser.setProperty( "http://apache.org/xml/properties/schema/external-schemaLocation",   "http://namespaces.example.com/tvschedule"   + " http://www.example.com/tvprogram.xsd"); parser.setFeature(   "http://apache.org/xml/features/validation/schema",   true); 

We'll also have to register an ErrorHandler to receive any validation errors that are detected . Because validity errors aren't necessarily fatal unless we make them so, we'll rethrow the SAXParseException passed to the error() method. Example 37-3 shows an appropriate Error Handler class.

Example 37-3 A SAX ErrorHandler That Makes Validity Errors Fatal
 import org.xml.sax.*; public class ErrorsAreFatal implements ErrorHandler {   public void warning(SAXParseException exception) {     // Ignore warnings   }   public void error(SAXParseException exception)    throws SAXException {     // A validity error; rethrow the exception.     throw exception;   }   public void fatalError(SAXParseException exception)    throws SAXException {     // A well-formedness error     throw exception;   } } 

This ErrorHandler also needs to be installed with the parser.

 parser.setErrorHandler(new ErrorsAreFatal()); 

Finally, the document can be parsed. The parser checks it against the schema as it parses. At the same time, the ContentHandler methods accumulate the data into the fields. Since SAX parsing interleaves parser operation with client code, all the data collected should be stored until the complete document has been validated. Only then can you be sure the document is valid and the information should be committed. Example 37-4 demonstrates one way to build a TVProgram object that stores this data. The constructor is private, so the only way to build such an object is by passing an InputStream containing a TVProgram document to the readTVProgram() method. The TVProgram object is actually created before the parsing starts. However, it's not returned to anything outside this class until the input document has been parsed and any constraints verified . If a constraint is violated, then an exception is thrown.

Example 37-4 A Program That Validates against a Schema
 import java.util.*; import java.io.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class TVProgram extends DefaultHandler {   private String title;   private String description;   private Date   startTime; // includes both date and time   private int    duration;  // rounded to nearest second   private String station;   // rounded to nearest second   private TVProgram() {     // Data will be initialized in the readTVProgram() method   }   private static XMLReader parser;   // Initialization block. No need to load a new parser for   // each document.   static {     try {       parser = XMLReaderFactory.createXMLReader(        "org.apache.xerces.parsers.SAXParser");       parser.setProperty( "http://apache.org/xml/properties/schema/external-schemaLocation",        "http://namespaces.example.com/tvschedule"        + " http://www.example.com/tvprogram.xsd");       parser.setFeature(        "http://apache.org/xml/features/validation/schema",        true);       parser.setErrorHandler(new ErrorsAreFatal());     }     catch (SAXException e) {      throw new RuntimeException(        "Handling exceptions in static initializers is tricky");     }   }   public static TVProgram readTVProgram(String systemID)    throws SAXException, IOException {     TVProgram program = new TVProgram();     parser.setContentHandler(program);     parser.parse(systemID);     // If no exception has been thrown yet, then the document     // must be valid. However, we still have to check the     // constraints the schema couldn't:     checkDateInFuture(program.startTime);     checkStationExists(program.station);     // If we get here, everything's fine.     return program;   }   private static void checkDateInFuture(Date date)    throws SAXException {     // Java code to compare the date to the current time   }   private static void checkStationExists(String station)    throws SAXException {     // JDBC code to look up the station call letters in our     // database   }   // Various ContentHandler methods that will fill in the fields   // of this object. This could be a separate class instead...   // Various setter and getter and other methods... } 

Presumably, after such an object has been read, other code will store it in a database or otherwise work with it. And, of course, building an object that exactly matches the data in the document is far from the only way to model the data. All these details will depend on the business logic in the rest of the program. However, the input checking through validation will normally be similar to what's shown here.

Effective XML. 50 Specific Ways to Improve Your XML
Effective XML: 50 Specific Ways to Improve Your XML
ISBN: 0321150406
EAN: 2147483647
Year: 2002
Pages: 144

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net