Skip navigation.
Downloads | Product Documentation | Support

Programming WebLogic XML

# Using the Streaming API for XML (StAX)

The following sections describe how to use the Streaming API for XML to parse and generate XML documents:

- Overview of the Streaming API for XML
- Parsing XML With the XMLStreamReader Interface: Typical Steps
- Generating XML Using the XMLStreamWriter Interface: Typical Steps
- Properties Defined for the XMLInputFactory Interface
- Properties Defined for the XMLOutputFactory Interface

# Overview of the Streaming API for XML

The Streaming API for XML (StAX), specified by JSR-173 of Java Community Process, provides an easy and intuitive means of parsing and generating XML documents. It is similar to the SAX API, but enables a procedural, stream-based handling of XML documents rather than requiring you to write SAX event handlers, which can get complicated when you work with complex XML documents. In other words, StAX gives you more control over parsing than the SAX.

When a program parses an XML document using SAX, the program must create event listeners that listen to parsing events as they occur; the program must react to events rather than ask for a specific event. By contrast, when you use StAX, you can methodically step through an XML document, ask for certain types of events (such as the start of an element), iterate over the attributes of an element, skip ahead in the document, stop processing at any time, get sub-elements of a particular element, and filter out elements as desired. Because you are asking for events rather than reacting to them, using the StAX is often referred to as pull parsing.

StAX includes two APIs, the cursor API and the event-iterator API, either of which can be used for reading and writing XML. The following sections describe each API and their particular strengths.

## Description of the Cursor API

The basic function of the cursor API is to allow programmers to parse and generate XML as easily and efficiently as possible. Of the two APIs in StAX, this is the one that most programmers would use.

The cursor API iterates over a set of events, such as start elements, comments, and attributes, although the events may be unrealized. The cursor API has two main interfaces: `XMLStreamReader` for parsing XML and `XMLStreamWriter` for generating XML.

### The XMLStreamReader Interface

The cursor API uses the `XMLStreamReader` interface to move a virtual cursor over an XML document and allow access to the data and underlying state through method calls such as `hasNext()`, `next()`, `getEventType()`, and `getText()`. The `XMLStreamReader` interface allows only forward, read-only access to the XML.

Use the `XMLInputFactory` class to create a new instance of the `XMLStreamReader`. You can set a variety of properties when you get a new reader; for details, see Properties Defined for the XMLInputFactory Interface.

When you use the `next()` method of the `XMLStreamReader` interface to parse XML, the reader gets the next parsing event and returns an integer that identifies the type of event just read. Parsing events correspond to sections of an XML document, such as the XML declaration, start and end element tags, character data, white space, comments, and processing instructions. The `XMLStreamConstant` interface specifies the event to which the integer returned by the `next()` method corresponds. You can also use the `getEventType()` method of `XMLStreamReader` to determine the event type.

The `XMLStreamReader` interface has numerous methods for getting at the specific data in the XML document. Some of these methods include:

- `getLocalName()`—Returns the local name of the current event.
- `getPrefix()`—Returns the prefix of the current event.
- `getAttributeXXX()`—Set of methods that return information about the current attribute event.
- `getNamespaceXXX()`—Set of methods that return information about the current namespace event.
- `getTextXXX()`—Set of methods that return information about the current text event.
- `getPIData()`—Returns the data section of the current processing instruction event.

Only certain methods are valid for each event type; the StAX processor throws a `java.lang.IllegalStateException` if you try to call a method on an invalid event type. For example, it is an error to try to call the `getAttributeXXX()` methods on a namespace event. See the StAX specification for the complete list of events and their valid `XMLStreamReader` methods.

### The XMLStreamWriter Interface

The cursor API uses the `XMLStreamWriter` interface to specify how to generate XML.

Use the `XMLOutputFactory` class to create a new instance of the `XMLStreamWriter`. You can set a property for repairing namespaces and prefixes when you get a new writer; for details, see Properties Defined for the XMLOutputFactory Interface.

The `XMLStreamWriter` interface defines a set of `writeXXX()` methods for writing standard parts of an XML document, such as:

- `writeStartElement()`
- `writeEndDocument()`
- `writeAttribute()`
- writeNamespace()
- `writeCData()`

Each part of an XML document, including the attributes and the namespaces, must be explicitly written using these methods.

Use the `flush()` method to write any cached data to the output and the `close()` method to close the writer and free up any resources.

The `XMLStreamWriter`, when generating XML, does not check that the generated document is well-formed; it is the programmer's responsibility to create a well-formed XML document. To print the special characters `&`, `<`, and `>`, use the `writeCharacters()` method.

## Description of the Event Iterator API

The event iterator API is a layer on top of the cursor API. It is easy to extend and facilitates pipelining. Pipelining refers to multiple XML-to-XML transformations. By using the event iterator API, programmers do not have to deserialize and serialize the XML at each stage of the pipeline; rather, only at each end of the pipeline and use the API methods such as `nextEvent()` to communicate at the middle stages. The event iterator API has two main interfaces: `XMLEventReader` for parsing XML and `XMLEventWriter` for generating XML.

Because the cursor API is the most commonly used API in StAX, this section does not describe in detail how to use the event iterator API, other than showing an example. For details about using this API, see the StAX specification.

The following example shows a simple program that uses the `XMLEventReader` interface of StAX to parse an XML document. The program takes a single parameter, an XML file, and uses it to create an `XMLEventReader` object. The program then uses the reader to iterate over and print the stream of events.

>     package examples.event;

>     import java.io.FileReader;
>     import javax.xml.stream.*;
>     import javax.xml.stream.events.*;
>     import javax.xml.stream.util.*;
>     import javax.xml.namespace.QName;

>     /**
>      * A simple example to iterate over events
>      *
>      * @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
>      */

>     public class Parse {
>       private static String filename = null;

>       private static void printUsage() {
>         System.out.println("usage: java examples.event.Parse <xmlfile>");
>       }

>       public static void main(String[] args) throws Exception {
>         try {
>           filename = args[0];
>         } catch (ArrayIndexOutOfBoundsException aioobe){
>           printUsage();
>           System.exit(0);
>         }

>         XMLInputFactory factory = XMLInputFactory.newInstance();
>         XMLEventReader r =
>           factory.createXMLEventReader(new FileReader(filename));
>         while(r.hasNext()) {
>           XMLEvent e = r.nextEvent();
>           System.out.println("ID:"+e.hashCode()+"["+e+"]");
>         }
>       }
>     }

## Main Interfaces and Classes of StAX

The following table describes the main interfaces and classes of the Streaming API for XML.

Table 4-1 Main Interfaces and Classes of the Streaming API for XML

Interface or Class | Used in Cursor or Event Iterator API? | Description
--- | --- | ---
`XMLInputFactory class` | Both | Factory class used to create an `XMLStreamReader` or `XMLEventReader` instance.
`XMLOutputFactory class` | Both | Factory class used to create an `XMLStreamWriter` or `XMLEventWriter` instance.
`XMLEventFactory class` | Event Iterator | Factory class used to create an `XMLEvent` instance.
`XMLStreamReader interface` | Cursor | Interface used to parse an XML document. Enables you to peek at the next event, get the next event, and check for more events.
`XMLStreamWriter interface` | Cursor | Interface used to generate an XML document. It provides a set of `write` `XXX``()` methods for generating specific parts of an XML document, such as start elements, attributes, and so on.
`XMLEventReader interface` | Event Iterator | Interface used to parse XML events. It enables you to peek at the next event, get the next event, and check for more events.
`XMLEventWriter interface` | Event Iterator | Interface used to generate XML. It uses the `add()` method to add XMLEvents to the output stream.
XMLEvent | Event Iterator | Base interface for handling events. All specific XML events extend from `XMLEvent`, such as `StartElement`, `Attribute`, and so on.
`XMLStreamException exception` | Both | Base exception for unexpected processing errors, such as lack of well-formed XML document structure.

# Parsing XML With the XMLStreamReader Interface: Typical Steps

The following procedure describes the typical steps for using the `XMLStreamReader` interface of the StAX cursor API to parse an XML document. The procedure uses the example from Example of Parsing XML Using StAX in its description.

1. Import the `javax.xml.stream.*` classes.
2. Use the `XMLInputFactory.newInstance()` method to instantiate an `XMLInputFactory`, as shown in the following code excerpt:

>     XMLInputFactory xmlif = XMLInputFactory.newInstance();

See Properties Defined for the XMLInputFactory Interface for the list of properties you can set.

3. Use the `XMLInputFactory.createXMLStreamReader()` method to instantiate an `XMLStreamReader` object based on an XML document.

See Getting the XMLStreamReader Object for more details.

4. Parse the XML document, using the `hasNext()` and `next()` methods to step through the XML events, as shown in the following code excerpt:

>     while(xmlr.hasNext()){
>           printEvent(xmlr);
>           xmlr.next();

In the example, `xmlr` is the `XMLStreamReader` instance and the local `printEvent()` method (not part of the StAX API) determines the specific event type, as described in the next step.

5. While parsing the XML document, determine the current specific event type and take appropriate action. Event types include the start and end of an XML document, the start and end of an XML element, comments, entity references, and so on.

See Determining the Specific XML Event Type.

6. If the current event type is a start element or end element, optionally get its attributes.

See Getting the Attributes of an Element.

7. If the current event type is a start or end element, optionally get its namespaces.

See Getting the Namespaces of an Element.

8. If the current event type includes text data, such as a CDATA or comment, optionally get the actual data.

See Getting Text Data.

9. Optionally, get location information, such as the line number or column number, of the current event.

See Getting Location Information.

10. Close the stream.

See Closing the Input Stream.

## Example of Parsing XML Using StAX

The following example shows a simple program that uses the `XMLStreamReader` interface of StAX to parse an XML document.

The program takes a single parameter, an XML file, and uses it to create an XMLStreamReader object. The program then uses the reader to iterate over the stream of events, determining the type of each event, such as the start of an XML element, the list of attributes of an element, a processing instruction, and so on. The program prints out information about these events, using internal methods to print out the list of attributes and namespaces when appropriate.

The code in bold is described in later sections.

>     package examples.basic;

>     import java.io.FileReader;
>     import java.util.Iterator;
>     import javax.xml.stream.*;
>     import javax.xml.namespace.QName;

>     /**
>      * This is a simple parsing example that illustrates
>      * the XMLStreamReader class.
>      *
>      * @author Copyright (c) 2003 by BEA Systems. All Rights Reserved.
>      */

>     public class Parse {
>       private static String filename = null;

>       private static void printUsage() {
>         System.out.println("usage: java examples.basic.Parse <xmlfile>");
>       }

>       public static void main(String[] args) throws Exception {
>         try {
>           filename = args[0];
>         } catch (ArrayIndexOutOfBoundsException aioobe){
>           printUsage();
>           System.exit(0);
>         }

>         //
>         // Get an input factory
>         //
>         XMLInputFactory xmlif = XMLInputFactory.newInstance();
>         System.out.println("FACTORY: " + xmlif);

>         //
>         // Instantiate a reader
>         //
>         XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename));
>         System.out.println("READER:  " + xmlr + "\n");

>         //
>         // Parse the XML
>         //
>         while(xmlr.hasNext()){
>           printEvent(xmlr);
>           xmlr.next();
>         }

>         //
>         // Close the reader
>         //
>         xmlr.close();

>       }

>       private static void printEvent(XMLStreamReader xmlr) {

>         System.out.print("EVENT:["+xmlr.getLocation().getLineNumber()+"]["+
>                          xmlr.getLocation().getColumnNumber()+"] ");

>         System.out.print(" [");

>         switch (xmlr.getEventType()) {

>         case XMLStreamConstants.START_ELEMENT:
>           System.out.print("<");
>           printName(xmlr);
>           printNamespaces(xmlr);
>           printAttributes(xmlr);
>           System.out.print(">");
>           break;

>         case XMLStreamConstants.END_ELEMENT:
>           System.out.print("</");
>           printName(xmlr);
>           System.out.print(">");
>           break;

>         case XMLStreamConstants.SPACE:

>         case XMLStreamConstants.CHARACTERS:
>           int start = xmlr.getTextStart();
>           int length = xmlr.getTextLength();
>           System.out.print(new String(xmlr.getTextCharacters(),
>                                       start,
>                                       length));
>           break;

>         case XMLStreamConstants.PROCESSING_INSTRUCTION:
>           System.out.print("<?");
>           if (xmlr.hasText())
>             System.out.print(xmlr.getText());
>           System.out.print("?>");
>           break;

>         case XMLStreamConstants.CDATA:
>           System.out.print("<![CDATA[");
>           start = xmlr.getTextStart();
>           length = xmlr.getTextLength();
>           System.out.print(new String(xmlr.getTextCharacters(),
>                                       start,
>                                       length));
>           System.out.print("]]>");
>           break;

>         case XMLStreamConstants.COMMENT:
>           System.out.print("<!--");
>           if (xmlr.hasText())
>             System.out.print(xmlr.getText());
>           System.out.print("-->");
>           break;

>         case XMLStreamConstants.ENTITY_REFERENCE:
>           System.out.print(xmlr.getLocalName()+"=");
>           if (xmlr.hasText())
>             System.out.print("["+xmlr.getText()+"]");
>           break;

>         case XMLStreamConstants.START_DOCUMENT:
>           System.out.print("<?xml");
>           System.out.print(" version='"+xmlr.getVersion()+"'");
>           System.out.print(" encoding='"+xmlr.getCharacterEncodingScheme()+"'");
>           if (xmlr.isStandalone())
>             System.out.print(" standalone='yes'");
>           else
>             System.out.print(" standalone='no'");
>           System.out.print("?>");
>           break;

>         }
>         System.out.println("]");
>       }

>       private static void printName(XMLStreamReader xmlr){
>         if(xmlr.hasName()){
>           String prefix = xmlr.getPrefix();
>           String uri = xmlr.getNamespaceURI();
>           String localName = xmlr.getLocalName();
>           printName(prefix,uri,localName);
>         }
>       }

>       private static void printName(String prefix,
>                                     String uri,
>                                     String localName) {
>         if (uri != null && !("".equals(uri)) ) System.out.print("['"+uri+"']:");
>         if (prefix != null) System.out.print(prefix+":");
>         if (localName != null) System.out.print(localName);
>       }

>       private static void printAttributes(XMLStreamReader xmlr){
>         for (int i=0; i < xmlr.getAttributeCount(); i++) {
>           printAttribute(xmlr,i);
>         }
>       }

>       private static void printAttribute(XMLStreamReader xmlr, int index) {
>         String prefix = xmlr.getAttributePrefix(index);
>         String namespace = xmlr.getAttributeNamespace(index);
>         String localName = xmlr.getAttributeLocalName(index);
>         String value = xmlr.getAttributeValue(index);
>         System.out.print(" ");
>         printName(prefix,namespace,localName);
>         System.out.print("='"+value+"'");
>       }

>       private static void printNamespaces(XMLStreamReader xmlr){
>         for (int i=0; i < xmlr.getNamespaceCount(); i++) {
>           printNamespace(xmlr,i);
>         }
>       }

>       private static void printNamespace(XMLStreamReader xmlr, int index) {
>         String prefix = xmlr.getNamespacePrefix(index);
>         String uri = xmlr.getNamespaceURI(index);
>         System.out.print(" ");
>         if (prefix == null)
>           System.out.print("xmlns='"+uri+"'");
>         else
>           System.out.print("xmlns:"+prefix+"='"+uri+"'");
>       }
>     }

## Getting the XMLStreamReader Object

Use the `XMLInputFactory.createXMLStreamReader()` method to instantiate an `XMLStreamReader` object based on an XML document, as shown in the following code excerpt:

>     XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename));

In the example, `xmlif` is the `XMLInputFactory` instance.

The various signatures of the `createXMLStreamReader()` method allow for the following XML document formats as parameters:

- `java.io.InputStream`
- `java.io.Reader` (shown in the example)
- `javax.xml.transform.Source` (specified in the JAXP API)

## Determining the Specific XML Event Type

To determine the specific event type while parsing an XML document, use either the `XMLStreamReader.next()` or `XMLStreamReader.getEventType()` methods. The `next()` method reads the next event and returns an integer which identifies the read event type; the `getEventType()` method simply returns the integer identifying the current event type. The `XMLStreamConstants` superinterface of `XMLStreamReader` defines the event type constants, shown in the following list:

- `XMLStreamConstants.ATTRIBUTE`
- `XMLStreamConstants.CDATA`
- `XMLStreamConstants.CHARACTERS`
- `XMLStreamConstants.COMMENT`
- `XMLStreamConstants.DTD`
- `XMLStreamConstants.END_DOCUMENT`
- `XMLStreamConstants.END_ELEMENT`
- `XMLStreamConstants.ENTITY_DECLARATION`
- `XMLStreamConstants.ENTITY_REFERENCE`
- `XMLStreamConstants.NAMESPACE`
- `XMLStreamConstants.NOTATION_DECLARATION`
- `XMLStreamConstants.PROCESSING_INSTRUCTION`
- `XMLStreamConstants.SPACE`
- `XMLStreamConstants.START_DOCUMENT`
- `XMLStreamConstants.START_ELEMENT`

The following example shows how to use the Java `case` statement to determine the particular type of event that was returned by the `XMLStreamReader.next()` method. The example uses the `XMLStreamReader.getEventType()` method to determine the integer event type of the current event returned by the `next()` method. For simplicity, the example simply prints that an event has been found; later sections show further processing of the event.

>     switch (xmlr.getEventType()) {

>     case XMLStreamConstants.START_ELEMENT:
>       System.out.print("Start Element\n");
>       break;

>     case XMLStreamConstants.END_ELEMENT:
>       System.out.print("End Element\n");
>       break;

>     case XMLStreamConstants.SPACE:
>       System.out.print("Space\n");
>       break;

>     case XMLStreamConstants.CHARACTERS:
>       System.out.print("Characters\n");
>       break;

>     case XMLStreamConstants.PROCESSING_INSTRUCTION:
>       System.out.print("Processing Instrcutions\n");
>       break;

>     case XMLStreamConstants.CDATA:
>       System.out.print("CDATA\n");
>       break;

>     case XMLStreamConstants.COMMENT:
>       System.out.print("Comment\n");
>       break;

>     case XMLStreamConstants.DTD:
>       System.out.print("DTD\n");
>       break;

>     case XMLStreamConstants.ENTITY_REFERENCE:
>       System.out.print("Entity Reference\n");
>       break;

>     case XMLStreamConstants.ENTITY_DECLARATION:
>       System.out.print("Entity Declaration\n");
>       break;

>     case XMLStreamConstants.START_DOCUMENT:
>       System.out.print("Start Document\n");
>       break;

>     case XMLStreamConstants.END_DOCUMENT:
>       System.out.print("End Document\n");
>       break;

>     }

## Getting the Full Name of an Element

The full name of an element includes its prefix, namespace URI, and local name; use the `getPrefix()`, `getNamespaceURI()`, and `getLocalName()` methods of the `XMLStreamReader` interface, respectively, to get this information once you determine that the current event is a start or end element.

For example, assume the `case` statement for a start element event in the sample program looks like the following:

>     case XMLStreamConstants.START_ELEMENT:

>       System.out.print("<");
>       printName(xmlr);
>       printNamespaces(xmlr);
>       printAttributes(xmlr);
>       System.out.print(">");
>       break;

Note: The `printNamespaces()` and `printAttributes()` methods are discussed in other sections.

The two local `printName()` methods can use the `getXXX()` methods as follows:

>     private static void printName(XMLStreamReader xmlr){
>       if(xmlr.hasName()){
>         String prefix = xmlr.getPrefix();
>         String uri = xmlr.getNamespaceURI();
>         String localName = xmlr.getLocalName();
>         printName(prefix,uri,localName);
>       }
>     }

>     private static void printName(String prefix,
>                                   String uri,
>                                   String localName) {
>       if (uri != null && !("".equals(uri)) ) System.out.print("['"+uri+"']:");
>       if (prefix != null) System.out.print(prefix+":");
>       if (localName != null) System.out.print(localName);
>     }

## Getting the Attributes of an Element

Once you determine that the current event is a start element, end element, or attribute, use the `getAttributeXXX()` methods of the `XMLStreamReader` interface to get the list of attributes and their values.

Caution: You can use the `getAttributeXXX()` methods only on start element, end element, and attribute events; a `java.lang.IllegalStateException` is thrown if you try to execute the methods on any other type of event.

Use the `getAttributeCount()` method to return the number of attributes of the current element and use the count in a loop that iterates over the list of attributes. The method does not include namespaces in the count. Additional `getAttributeXXX()` methods return the prefix, namespace URI, local name, and value for a particular attribute.

For example, assume the `case` statement for a start element event in our sample program looks like the following:

>     case XMLStreamConstants.START_ELEMENT:

>       System.out.print("<");
>       printName(xmlr);
>       printNamespaces(xmlr);
>       printAttributes(xmlr);
>       System.out.print(">");
>       break;

Note: The `printName()` and `printNamespaces()` methods are discussed in other sections.

The following local `printAttributes()` method shows one way of iterating through the list of attributes; because attribute indices are zero-based, the `for` loop starts at 0:

>     private static void printAttributes(XMLStreamReader xmlr){

>       for (int i=0; i < xmlr.getAttributeCount(); i++) {
>         printAttribute(xmlr,i);
>       }
>     }

The following local `printAttribute()` method shows how to print out all the information for a particular attribute:

>     private static void printAttribute(XMLStreamReader xmlr, int index) {
>       String prefix = xmlr.getAttributePrefix(index);
>       String namespace = xmlr.getAttributeNamespace(index);
>       String localName = xmlr.getAttributeLocalName(index);
>       String value = xmlr.getAttributeValue(index);
>       System.out.print(" ");
>       printName(prefix,namespace,localName);
>       System.out.print("='"+value+"'");
>     }

The `printName()` method is described in Getting the Full Name of an Element.

## Getting the Namespaces of an Element

Once you determine that the current event is a start element, end element, or namespace, use the `getNamespaceXXX()` methods of the `XMLStreamReader` interface to get the list of namespaces declared for the event.

Caution: You can use the `getNamespaceXXX()` methods only on start element, end element, and namespace events; a `java.lang.IllegalStateException` is thrown if you try to execute the methods on any other type of event.

Use the `getNamespaceCount()` method to return the number of namespaces declared for the current event, and use the count in a loop that iterates over the list. If the current event is an end element, the count refers to the number of namespaces that are about to go out of scope. Additional `getNamespaceXXX()` methods return the prefix and namespace URI for a particular namespace.

For example, assume the `case` statement for a start element event in our sample program looks like the following:

>     case XMLStreamConstants.START_ELEMENT:

>       System.out.print("<");
>       printName(xmlr);
>       printNamespaces(xmlr);
>       printAttributes(xmlr);
>       System.out.print(">");
>       break;

Note: The `printName()` and `printAttributes()` methods are discussed in other sections.

The following local `printNamespaces()` method shows one way of iterating through the list of namespaces for the start element; because namespace indices are zero-based, the `for` loop starts at 0:

>     private static void printNamespaces(XMLStreamReader xmlr){
>       for (int i=0; i < xmlr.getNamespaceCount(); i++) {
>         printNamespace(xmlr,i);
>       }
>     }

The following local `printNamespace()` method shows how to print out all the information for a particular namespace:

>     private static void printNamespace(XMLStreamReader xmlr, int index) {
>       String prefix = xmlr.getNamespacePrefix(index);
>       String uri = xmlr.getNamespaceURI(index);
>       System.out.print(" ");
>       if (prefix == null)
>         System.out.print("xmlns='"+uri+"'");
>       else
>         System.out.print("xmlns:"+prefix+"='"+uri+"'");
>     }

The `getNamespacePrefix()` method returns null for the default namespace declaration.

## Getting Text Data

The `XMLStreamReader` interface includes various `getTextXXX()` methods for getting text data from events such as comments and CDATA.

Use the `getTextStart()` method to get the offset into the text character array where the first character of the current text event is stored. Use the `getTextLength()` method to get the length of the sequence of characters within the text character array. Finally, use the `getTextCharacters()` method to return this character array for the current event. The character array contains text information about only the current event; as soon as you call the `next()` method to read the next event on the input stream, the character array is filled with new information.

The following example shows how to print out text data for the CDATA event:

>     case XMLStreamConstants.CDATA:
>       System.out.print("<![CDATA[");
>       start = xmlr.getTextStart();
>       length = xmlr.getTextLength();
>       System.out.print(new String(xmlr.getTextCharacters(),
>                                   start,
>                                   length));
>       System.out.print("]]>");
>       break;

If you want to first check that the character event actually has text, use the `hasText()` method, as shown in the following example:

>     case XMLStreamConstants.COMMENT:
>       System.out.print("<!--");
>       if (xmlr.hasText())
>         System.out.print(xmlr.getText());
>       System.out.print("-->");
>       break;

## Getting Location Information

The `Location` interface of the StAX API provides methods for getting location information about an event, such as the line number or column number, as well as the public ID and system ID of the XML being parsed. Use the `getLocation()` method of the `XMLStreamReader` interface to return a `Location` object for the current event, as shown in the following example:

>     System.out.print("EVENT:["+xmlr.getLocation().getLineNumber()+"]["+
>                          xmlr.getLocation().getColumnNumber()+"] ");

## Closing the Input Stream

It is good programming practice to close the `XMLStreamReader` explicitly when you are finished with it, to free up resources. To close the reader, use the `XMLStreamReader.close()` method, as shown in the following example:

>     //
>     // Close the reader
>     //
>     xmlr.close();

# Generating XML Using the XMLStreamWriter Interface: Typical Steps

The following procedure describes the typical steps for using the `XMLStreamWriter` interface of the StAX cursor API to generate a new XML document.

1. Import the `javax.xml.stream.*` classes.
2. Use the `XMLOutputFactory.newInstance()` method to instantiate an `XMLOutputFactory`, as shown in the following code excerpt:

>     XMLOutputFactory xmlof = XMLOutputFactory.newInstance();

See Properties Defined for the XMLOutputFactory Interface for the list of properties you can set.

3. Use the `XMLOutputFactory.createXMLStreamWriter()` method to instantiate an `XMLStreamWriter` object, passing it the name of the file or object that will contain the XML.

See Getting the XMLStreamWriter Object for more details.

4. Add the XML declaration to the output. Adding the XML Declaration to the Output Stream.
5. Add standard XML objects, such as start elements, comments, and characters, to the output. See Adding Standard XML Events to the Output Stream.
6. Add attributes and namespace declarations to a start element. See Adding Attributes and Namespace Declarations to a Start Element.
7. Close the output stream. See Closing the Output Stream.

## Example of Generating XML Using StAX

The following example shows a simple program that uses the `XMLStreamWriter` interface of StAX to generate an XML document.

The program first creates an instance of an `XMLStreamWriter`, specifying that the output be written to the file `outFile.xml` in the current directory. Then, using various `writeXXX()` methods, it builds an XML file that looks like the following:

>     <?xml version='1.0' encoding='utf-8'?>

>     <!--this is a comment-->
>     <person xmlns:one="http://namespaceOne" gender="f">
>         <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
>     </person>

The `XMLStreamWriter` interface does not check for that an XML document is well-formed; it is the programmer's responsibility to ensure that, for example, each start element has a corresponding end element, and so on. The example also shows how to use the `writeCharacters("\n")` method to add new lines to the output to make the XML more readable when writing to a text file.

The code in bold is described in later sections.

>     package examples.basic;

>     import java.io.FileOutputStream;
>     import java.util.Iterator;
>     import javax.xml.stream.*;
>     import javax.xml.namespace.QName;

>     /**
>      * This is a simple example that illustrates how to use the
>      * the XMLStreamWriter class to generate XML.
>      *
>      * The generated XML file looks like this:
>      *
>      *   <?xml version='1.0' encoding='utf-8'?>
>      *
>      *   <!--this is a comment-->
>      *   <person xmlns:one="http://namespaceOne" gender="f">
>      *       <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
>      *   </person>
>      *
>      *
>      * @author Copyright (c) 2003 by BEA Systems. All Rights Reserved.
>      */

>     public class Generate {

>       public static void main(String args[]) throws Exception {

>         //
>         // Get an output factory
>         //
>         XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
>         System.out.println("FACTORY: " + xmlof);

>         //
>         // Instantiate a writer
>         //
>         XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml"));
>         System.out.println("READER:  " + xmlw + "\n");

>         //
>         // Generate the XML
>         //

>         // Write the default XML declaration
>         xmlw.writeStartDocument();
>         xmlw.writeCharacters("\n");
>         xmlw.writeCharacters("\n");

>         // Write a comment
>         xmlw.writeComment("this is a comment");
>         xmlw.writeCharacters("\n");

>         // Write the root element "person" with a single attribute "gender"
>         xmlw.writeStartElement("person");
>         xmlw.writeNamespace("one", "http://namespaceOne");
>         xmlw.writeAttribute("gender","f");
>         xmlw.writeCharacters("\n");

>         // Write the "name" element with some content and two attributes
>         xmlw.writeCharacters("    ");
>         xmlw.writeStartElement("one", "name", "http://namespaceOne");
>         xmlw.writeAttribute("hair","pigtails");
>         xmlw.writeAttribute("freckles","yes");
>         xmlw.writeCharacters("Pippi Longstocking");

>         // End the "name" element
>         xmlw.writeEndElement();
>         xmlw.writeCharacters("\n");

>         // End the "person" element
>         xmlw.writeEndElement();

>         // End the XML document
>         xmlw.writeEndDocument();

>         // Close the XMLStreamWriter to free up resources
>         xmlw.close();

>       }

>     }

## Getting the XMLStreamWriter Object

Use the `XMLOutputFactory.createXMLStreamWriter()` method to instantiate an `XMLStreamWriter` object based on an XML document, as shown in the following code excerpt:

>     XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml"));

In the example, `xmlof` is the `XMLOutputFactory` instance.

The various signatures of the `createXMLStreamWriter()` method allow for the following XML document formats as parameters:

- `java.io.OutputStream` (shown in the example)
- `java.io.Writer`
- `javax.xml.transform.Result` (specified in the JAXP API)

## Adding the XML Declaration to the Output Stream

Use the `XMLStreamWriter.writeStartDocument()` method to add the XML declaration as the first line of the XML document, as shown in the following code excerpt:

>     xmlw.writeStartDocument();

With no arguments, the method writes the default XML declaration:

>     <?xml version='1.0' encoding='utf-8'?>

If you want to specify a different encoding or XML version, use the following flavors of the `writeStartDocument()` method:

- `writeStartDocument(java.lang.String version)`
- `writeStartDocument(java.lang.String encoding, java.lang.String version)`

Setting the encoding with the `writeStartDocument()` method does not set the actual encoding of the underlying output; it simply specifies what value is written for the `encoding` attribute of the XML declaration. To actually set the encoding of the output, you must specify the `encoding` parameter when creating the instance of the `XMLStreamWriter` with the appropriate `XMLOutputFactory.createXMLStreamWriter()` method.

## Adding Standard XML Events to the Output Stream

Use the `XMLStreamWriter.write` `XXX``()` methods to add standard XML events, such as start elements, end elements, comments, CDATA, entity references, and so on to the output stream.The `XXX` refers to the particular event, such as `writeStartElement()`, `writeEndElement()`, `writeComment()`, `writeCData()`, and so on. You can create most elements by passing the name or text data as a `String`.

The `XMLStreamWriter` interface does not validate your data, nor does it check that the document is well-formed; it is the programmer's responsibility to ensure that, for example, each start element has a corresponding end element, and so on. It is also up to the programmer to ensure that the start and end element events are correctly nested. To make the output XML more human-readable when writing to a text file, use the `writeCharacters("\n")` method to add new lines in appropriate places.

For example, assume you want to create the following snippet of XML:

>     <!-- This is a comment -->
>     <name>Jane Doe</name>

The Java code to add this element to an output stream is as follows:

>     xmlw.writeComment("This is a comment");
>     xmlw.writeCharacters("\n");

>     xmlw.writeStartElement("name");
>     xmlw.writeCharacters("Jane Doe");
>     xmlw.writeEndElement();
>     xmlw.writeCharacters("\n");

## Adding Attributes and Namespace Declarations to a Start Element

Use the `writeAttribute()` method right after a start element event to add attributes to the element. You can specify a prefix for the attribute, as well as the URI it is bound to, or specify no prefix at all.

For example, assume you want to create the following snippet of XML:

>     <person gender="f">

The Java code to produce this XML is as follows:

>     xmlw.writeStartElement("person");
>     xmlw.writeAttribute("gender","f");
>     xmlw.writeCharacters("\n");

Use the `writeNamespace()` method to write a namespace to the output stream. It is up to the programmer to ensure that the current event allows namespace writing, such as start element; if the current event does not allow namespace writing, a `javax.xml.stream.XMLStreamException` is thrown. Use appropriate flavors of other `writeXXX()` methods to specify a prefix for an event and the URI to which it is bound.

For example, the following XML output shows a namespace declaration for the `<person>` element, and the `one` prefix specified for the `<one>` child element:

>     <person xmlns:one="http://namespaceOne" gender="f">
>         <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
>     </person>

The Java code to produce this XML is as follows:

>         // Write the root element "person" with a single attribute "gender"
>         xmlw.writeStartElement("person");
>         xmlw.writeNamespace("one", "http://namespaceOne");
>         xmlw.writeAttribute("gender","f");
>         xmlw.writeCharacters("\n");

>         // Write the "name" element with some content and two attributes
>         xmlw.writeCharacters("    ");
>         xmlw.writeStartElement("one", "name", "http://namespaceOne");
>         xmlw.writeAttribute("hair","pigtails");
>         xmlw.writeAttribute("freckles","yes");
>         xmlw.writeCharacters("Pippi Longstocking");

>         // End the "name" element
>         xmlw.writeEndElement();
>         xmlw.writeCharacters("\n");

>         // End the "person" element
>         xmlw.writeEndElement();

## Closing the Output Stream

It is good programming practice to explicitly close the `XMLStreamWriter` when you are finished with it to free up resources. To close the writer, use the `XMLStreamWriter.close()` method, as shown in the following example:

>         // Close the XMLStreamWriter to free up resources
>         xmlw.close();

# Properties Defined for the XMLInputFactory Interface

The following table lists the standard properties you can set when using the `XMLInputFactory` to generate an `XMLStreamReader` or `XMLEventReader` object.

Note: All properties in the following table are preceded with `javax.xml.stream`, such as `javax.xml.stream.isValidating`.

Table 4-2 Standard XMLInputFactory Properties

Property | Description | Return Type | Default Value
--- | --- | --- | ---
isValidating | Specifies whether implementation-specific DTD validation is enabled or disabled. | Boolean | False
isNamespaceAware | Specifies whether namespace processing is enabled or disabled. Used for XML 1.0 support. | Boolean | True
isCoalescing | Specifies whether to coalesce adjacent adjacent character data. | Boolean | False
isReplacingEntityReferences | Specifies whether internal entity references should be replaced with their replacement text and reported as characters. | Boolean | True
isSupportingExternalEntities | Specifies whether to resolve external parsed entities. | Boolean | False
supportDTD | Specifies whether the processor used is one that supports or does not support DTDs. | Boolean | True
reporter | Specifies the implementation of javax.xml.stream.XMLReporter that should be used.Specifies the implementation of javax.xml.stream.XMLReporter that should be used. | XMLReporter | Null
resolver | Specifies the implementation of javax.xml.stream.XMLResolver that should be used. | XMLResolver | Null
allocator | Specifies the implementation of javax.xml.stream.util.XMLEventAllocator that should be used. | util.XMLEventAllocator | Null

# Properties Defined for the XMLOutputFactory Interface

The following table lists the standard properties you can set when using the `XMLOutputFactory` to generate an `XMLStreamWriter` or `XMLEventWriter` object.

Note: All properties in the following table are preceded with `javax.xml.stream`, such as `javax.xml.stream.isValidating`.

Table 4-3 Standard XMLOutputFactory Properties

Property | Description | Return Type | Default Value
--- | --- | --- | ---
isRepairingNamespaces | Specifies that the writer use default namespace prefix declarations. There are strict rules about how the StAX processor repairs namespaces and prefixes when generating XML. For details, see the StAX specification. | Boolean | False