gnu.xml.pipeline

Class ValidationConsumer

Implemented Interfaces:
ContentHandler, DeclHandler, DTDHandler, EventConsumer, LexicalHandler

public final class ValidationConsumer
extends EventFilter

This class checks SAX2 events to report validity errors; it works as both a filter and a terminus on an event pipeline. It relies on the producer of SAX events to:
  1. Conform to the specification of a non-validating XML parser that reads all external entities, reported using SAX2 events.
  2. Report ignorable whitespace as such (through the ContentHandler interface). This is, strictly speaking, optional for nonvalidating XML processors.
  3. Make SAX2 DeclHandler callbacks, with default attribute values already normalized (and without "<").
  4. Make SAX2 LexicalHandler startDTD() and endDTD () callbacks.
  5. Act as if the (URI)/namespace-prefixes property were set to true, by providing XML 1.0 names and all xmlns* attributes (rather than omitting either or both).

At this writing, the major SAX2 parsers (such as Ælfred2, Crimson, and Xerces) meet these requirements, and this validation module is used by the optional Ælfred2 validation support.

Note that because this is a layered validator, it has to duplicate some work that the parser is doing; there are also other cost to layering. However, because of layering it doesn't need a parser in order to work! You can use it with anything that generates SAX events, such as an application component that wants to detect invalid content in a changed area without validating an entire document, or which wants to ensure that it doesn't write invalid data to a communications partner.

Also, note that because this is a layered validator, the line numbers reported for some errors may seem strange. For example, if an element does not permit character content, the validator will use the locator provided to it. That might reflect the last character of a characters event callback, rather than the first non-whitespace character.


<!--

Of interest is the fact that unlike most currently known XML validators, this one can report some cases of non-determinism in element content models. It is a compile-time option, enabled by default. This will only report such XML errors if they relate to content actually appearing in a document; content models aren't aggressively scanned for non-deterministic structure. Documents which trigger such non-deterministic transitions may be handled differently by different validating parsers, without losing conformance to the XML specification. -->

Current limitations of the validation performed are in roughly three categories.

The first category represents constraints which demand violations of software layering: exposing lexical details, one of the first things that application programming interfaces (APIs) hide. These invariably relate to XML entity handling, and to historical oddities of the XML validation semantics. Curiously, recent (Autumn 1999) conformance testing showed that these constraints are among those handled worst by existing XML validating parsers. Arguments have been made that each of these VCs should be turned into WFCs (most of them) or discarded (popular for the standalone declaration); in short, that these are bugs in the XML specification (not all via SGML):

The second category of limitations on this validation represent constraints associated with information that is not guaranteed to be available (or in one case, is guaranteed not to be available, through the SAX2 API:

A third category relates to ease of implementation. (Think of this as "bugs".) The most notable issue here is character handling. Rather than attempting to implement the voluminous character tables in the XML specification (Appendix B), Unicode rules are used directly from the java.lang.Character class. Recent JVMs have begun to diverge from the original specification for that class (Unicode 2.0), meaning that different JVMs may handle that aspect of conformance differently.

Note that for some of the validity errors that SAX2 does not expose, a nonvalidating parser is permitted (by the XML specification) to report validity errors. When used with a parser that does so for the validity constraints mentioned above (or any other SAX2 event stream producer that does the same thing), overall conformance is substantially improved.

See Also:
SAXDriver, XmlReader

Field Summary

Fields inherited from class gnu.xml.pipeline.EventFilter

DECL_HANDLER, FEATURE_URI, LEXICAL_HANDLER, PROPERTY_URI

Constructor Summary

ValidationConsumer()
Creates a pipeline terminus which consumes all events passed to it; this will report validity errors as if they were fatal errors, unless an error handler is assigned.
ValidationConsumer(EventConsumer next)
Creates a pipeline filter which reports validity errors and then passes events on to the next consumer if they were not fatal.
ValidationConsumer(String rootName, String publicId, String systemId, String internalSubset, EntityResolver resolver, String minimalDocument)
Creates a validation consumer which is preloaded with the DTD provided.

Method Summary

void
attributeDecl(String eName, String aName, String type, String mode, String value)
DecllHandler Records attribute declaration for later use in validating document content, and checks validity constraints that are applicable to attribute declarations.
void
characters(ch[] , int start, int length)
ContentHandler Reports a validity error if the element's content model does not permit character data.
void
elementDecl(String name, String model)
DecllHandler Records the element declaration for later use when checking document content, and checks validity constraints that apply to element declarations.
void
endDTD()
LexicalHandler Verifies that all referenced notations and unparsed entities have been declared.
void
endDocument()
ContentHandler Checks whether all ID values that were referenced have been declared, and releases all resources.
void
endElement(String uri, String localName, String qName)
ContentHandler Reports a validity error if the element's content model does not permit end-of-element yet, or a well formedness error if there was no matching startElement call.
void
externalEntityDecl(String name, String publicId, String systemId)
DecllHandler passed to the next consumer, unless this one was preloaded with a particular DTD
void
internalEntityDecl(String name, String value)
DecllHandler passed to the next consumer, unless this one was preloaded with a particular DTD
void
notationDecl(String name, String publicId, String systemId)
DTDHandler Records the notation name, for checking NOTATIONS attribute values and declararations of unparsed entities.
void
skippedEntity(String name)
ContentHandler Reports a fatal exception.
void
startDTD(String name, String publicId, String systemId)
LexicalHandler Records the declaration of the root element, so it can be verified later.
void
startDocument()
ContentHandler Ensures that state from any previous parse has been deleted.
void
startElement(String uri, String localName, String qName, Attributes atts)
ContentHandler Performs validity checks against element (and document) content models, and attribute values.
void
unparsedEntityDecl(String name, String publicId, String systemId, String notationName)
DTDHandler Records the entity name, for checking ENTITY and ENTITIES attribute values; records the notation name if it hasn't yet been declared.

Methods inherited from class gnu.xml.pipeline.EventFilter

attributeDecl, bind, chainTo, characters, comment, elementDecl, endCDATA, endDTD, endDocument, endElement, endEntity, endPrefixMapping, externalEntityDecl, getContentHandler, getDTDHandler, getDocumentLocator, getErrorHandler, getNext, getProperty, ignorableWhitespace, internalEntityDecl, notationDecl, processingInstruction, setContentHandler, setDTDHandler, setDocumentLocator, setErrorHandler, setProperty, skippedEntity, startCDATA, startDTD, startDocument, startElement, startEntity, startPrefixMapping, unparsedEntityDecl

Methods inherited from class java.lang.Object

clone, equals, extends Object> getClass, finalize, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructor Details

ValidationConsumer

public ValidationConsumer()
Creates a pipeline terminus which consumes all events passed to it; this will report validity errors as if they were fatal errors, unless an error handler is assigned.
See Also:
ValidationConsumer

ValidationConsumer

public ValidationConsumer(EventConsumer next)
Creates a pipeline filter which reports validity errors and then passes events on to the next consumer if they were not fatal.
See Also:
ValidationConsumer

ValidationConsumer

public ValidationConsumer(String rootName,
                          String publicId,
                          String systemId,
                          String internalSubset,
                          EntityResolver resolver,
                          String minimalDocument)
            throws SAXException,
                   IOException
Creates a validation consumer which is preloaded with the DTD provided. It does this by constructing a document with that DTD, then parsing that document and recording its DTD declarations. Then it arranges not to modify that information.

The resulting validation consumer will only validate against the specified DTD, regardless of whether some other DTD is found in a document being parsed.

Parameters:
rootName - The name of the required root element; if this is null, any root element name will be accepted.
publicId - If non-null and there is a non-null systemId, this identifier provides an alternate access identifier for the DTD's external subset.
systemId - If non-null, this is a URI (normally URL) that may be used to access the DTD's external subset.
internalSubset - If non-null, holds literal markup declarations comprising the DTD's internal subset.
resolver - If non-null, this will be provided to the parser for use when resolving parameter entities (including any external subset).
Throws:
IOException - If the specified DTD can't be read for some reason

Method Details

attributeDecl

public void attributeDecl(String eName,
                          String aName,
                          String type,
                          String mode,
                          String value)
            throws SAXException
DecllHandler Records attribute declaration for later use in validating document content, and checks validity constraints that are applicable to attribute declarations. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
attributeDecl in interface DeclHandler
Overrides:
attributeDecl in interface EventFilter

characters

public void characters(ch[] ,
                       int start,
                       int length)
            throws SAXException
ContentHandler Reports a validity error if the element's content model does not permit character data. Passed to the next consumer.
Specified by:
characters in interface ContentHandler
Overrides:
characters in interface EventFilter

elementDecl

public void elementDecl(String name,
                        String model)
            throws SAXException
DecllHandler Records the element declaration for later use when checking document content, and checks validity constraints that apply to element declarations. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
elementDecl in interface DeclHandler
Overrides:
elementDecl in interface EventFilter

endDTD

public void endDTD()
            throws SAXException
LexicalHandler Verifies that all referenced notations and unparsed entities have been declared. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
endDTD in interface LexicalHandler
Overrides:
endDTD in interface EventFilter

endDocument

public void endDocument()
            throws SAXException
ContentHandler Checks whether all ID values that were referenced have been declared, and releases all resources. Passed to the next consumer.
Specified by:
endDocument in interface ContentHandler
Overrides:
endDocument in interface EventFilter
See Also:
ValidationConsumer

endElement

public void endElement(String uri,
                       String localName,
                       String qName)
            throws SAXException
ContentHandler Reports a validity error if the element's content model does not permit end-of-element yet, or a well formedness error if there was no matching startElement call. Passed to the next consumer.
Specified by:
endElement in interface ContentHandler
Overrides:
endElement in interface EventFilter

externalEntityDecl

public void externalEntityDecl(String name,
                               String publicId,
                               String systemId)
            throws SAXException
DecllHandler passed to the next consumer, unless this one was preloaded with a particular DTD
Specified by:
externalEntityDecl in interface DeclHandler
Overrides:
externalEntityDecl in interface EventFilter

internalEntityDecl

public void internalEntityDecl(String name,
                               String value)
            throws SAXException
DecllHandler passed to the next consumer, unless this one was preloaded with a particular DTD
Specified by:
internalEntityDecl in interface DeclHandler
Overrides:
internalEntityDecl in interface EventFilter

notationDecl

public void notationDecl(String name,
                         String publicId,
                         String systemId)
            throws SAXException
DTDHandler Records the notation name, for checking NOTATIONS attribute values and declararations of unparsed entities. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
notationDecl in interface DTDHandler
Overrides:
notationDecl in interface EventFilter

skippedEntity

public void skippedEntity(String name)
            throws SAXException
ContentHandler Reports a fatal exception. Validating XML processors may not skip any entities.
Specified by:
skippedEntity in interface ContentHandler
Overrides:
skippedEntity in interface EventFilter

startDTD

public void startDTD(String name,
                     String publicId,
                     String systemId)
            throws SAXException
LexicalHandler Records the declaration of the root element, so it can be verified later. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
startDTD in interface LexicalHandler
Overrides:
startDTD in interface EventFilter

startDocument

public void startDocument()
            throws SAXException
ContentHandler Ensures that state from any previous parse has been deleted. Passed to the next consumer.
Specified by:
startDocument in interface ContentHandler
Overrides:
startDocument in interface EventFilter

startElement

public void startElement(String uri,
                         String localName,
                         String qName,
                         Attributes atts)
            throws SAXException
ContentHandler Performs validity checks against element (and document) content models, and attribute values. Passed to the next consumer.
Specified by:
startElement in interface ContentHandler
Overrides:
startElement in interface EventFilter

unparsedEntityDecl

public void unparsedEntityDecl(String name,
                               String publicId,
                               String systemId,
                               String notationName)
            throws SAXException
DTDHandler Records the entity name, for checking ENTITY and ENTITIES attribute values; records the notation name if it hasn't yet been declared. Passed to the next consumer, unless this one was preloaded with a particular DTD.
Specified by:
unparsedEntityDecl in interface DTDHandler
Overrides:
unparsedEntityDecl in interface EventFilter

ValidationConsumer.java -- Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.