As with SAX and DOM, StAX readers and writers can be configured by changing both settings defined in the specification and any implementation-specific settings that a parser vendor may create for their implementation. In StAX, these settings are referred to as properties. Properties are set using the setProperty( ) method of XMLInputFactory and XMLOutputFactory. Values of properties, which may or may not have been set by your code, can be retrieved using the getProperty( ) method. This method can be invoked both on factories and the readers and writers they have created. Once set on a factory, properties affect all readers and writers subsequently created by the various create methods.

Java Tip

An interesting difference between SAX and StAX is that, where SAX uses features that get set to true or false as well as properties that get set to a java.lang.Object , StAX only has properties that are set to an Object. As a result, several of the properties defined by the StAX specification are set to a java.lang.Boolean. So where you might use true to set a feature in SAX, you would use Boolean.TRUE in StAX. If you're using Java 5, you can use the autoboxing language feature to eliminate this difference, as the Java compiler will create the same bytecode from these two method invocations:

// works with any version of Javafactory.setProperty("javax.xml.stream.isValidating", Boolean.TRUE);// only with Java 5 or higherfactory.setProperty("javax.xml.stream.isValidating", true);

Boolean Properties of XMLInputFactory

contains a list of the properties of XMLInputFactory that are set using java.lang.Boolean values. Most of these have their default values specified in the StAX specification. Support for some of these properties is optional. Like DOM, there is a separate mechanism to test if a property is supported by an implementation through the isPropertySupported( ) method. If you try to set a property that is not supported, setProperty( ) will throw a java.lang.IllegalArgumentException indicating that a property is not supported.

Table 8-5. Boolean properties of XMLInputFactory

Feature name Default Required?
javax.xml.stream.isValidating
False No
javax.xml.stream.isCoalescing
False Yes
javax.xml.stream.isNamespaceAware
True No
javax.xml.stream.isReplacingEntityReferences
True Yes
javax.xml.stream.isSupportingExternalEntities
None Yes


javax.xml.stream.isValidating

Enable or disable XML validation.


javax.xml.stream.isCoalescing

Force the parser to combine adjacent CHARACTERS and CDATA events into a single CHARACTERS event.


javax.xml.stream.isNamespaceAware

Enable or disable namespace support.


javax.xml.stream.isReplacingEntityReferences

If this property is set to true, internal entity references are replaced with their character representation. If it is set to false, these entities result in ENTITY_REFERENCE events. This does not apply to the five predefined XML entities (<, &, >, ", and '), which are always replaced by their character representation.


javax.xml.stream.isSupportingExternalEntities

Enable or disable resolution of external parsed entities.

Object Properties of XMLInputFactory

XMLInputFactory defines three interfaces that can be implemented to alter the behavior of XMLStreamReader and XMLEventReader instances. Implementations of these interfaces are set on an XMLInputFactory either through calling setProperty( ) with one of the property names from or by calling the specific setter for each interface.

Table 8-6. Interfaces for object properties of XMLInputFactory

Interface name Property name Setter
XMLResolver
javax.xml.stream.resolver
setResolver( )
XMLReporter
javax.xml.stream.reporter
setReporter( )
XMLEventAllocator
javax.xml.stream.allocator
setAllocator( )

XMLResolver

Implementing the javax.xml.stream.XMLResolver interface allows you to override the default resource resolution mechanism for resolving external resources while parsing a documenttypically an external DTD. The interface defines one method:

 public Object resolveEntity(String publicID, String systemID,
 String baseURI, String namespace) throws XMLStreamException;

The result of a call to resolveEntity( ) must be a javax.xml.stream.XMLStreamReader, a java.io.InputStream, or a javax.xml.stream.XMLEventReader.

XMLReporter

The java.xml.stream.XMLReporter interface allows you to capture warnings and nonfatal errors that arise while parsing the document. Without setting this property on XMLInputFactory, there is no reporting of warnings or nonfatal errors. The interface defines one method:

 public void report(String message, String errorType,
 Object relatedInformation, Location location)
 throws XMLStreamException;

XMLEventAllocator

An implementation of the javax.xml.stream.util.XMLEventAllocator interface is used inside implementations of XMLEventReader to create an XMLEvent object based on the current state of the underlying XMLStreamReader. By contract, an XMLEventAllocator should never modify the state of the XMLStreamReader. The interface defines three methods:

 public XMLEventAllocator newInstance( );
 public XMLEvent allocate(XMLStreamReader reader) throws XMLStreamException;
 public void allocate(XMLStreamReader reader, XMLEventConsumer consumer) throws XMLStreamException;

The newInstance( ) method should return a new instance of this XMLEventAllocator implementation. This allows XMLInputFactory instances to create a new allocator instance per reader. The two allocate methods should read the current state of the XMLStreamReader and create the appropriate XMLEvent objects. According to the specification, XMLEventAllocator instances are not required to use XMLEventFactory, but it is recommended. The first version of allocate should return one XMLEvent based on the state of the reader. The second passes in an instance of the XMLEventConsumer interface (which defines one methodadd( )that accepts an XMLEvent object) to which XMLEvent should be passed and, as a result, one call to allocate( ) can result in multiple method calls on the XMLEventConsumer object. However, since XMLEventReader implementations are free to call either allocate( ) method; you can't count on this multievent behavior. A significant problem with implementing this interface is that there's no way to obtain the default XMLEventAllocator implementation for a StAX implementation. This means there is no vendor-independent way to create an implementation of XMLEventAllocator that only overrides allocation of only some types of event. If you expect to use XMLEventAllocator extensively, you may be best served by standardizing on a StAX implementation so that you can extend its default implementation of XMLEventAllocator.

XMLOutputFactory

XMLOutputFactory has only one property defined in the StAX specification, javax.xml.stream.isRepairingNamespaces . This property allows you to avoid defining a prefix for each namespace URI in your document. Instead, the XMLStreamWriter or XMLEventWriter implementation will automatically assign a prefix. This can cut down on the amount of namespace handling code you need to write, but with the cost of some potentially very ugly namespace prefixes like zdef-1428660340. If your document is going to be read by humans that expect a particular (or short) namespace prefix, using this property may cause you some headaches.