Skip Headers
Oracle® Fusion Middleware Programming XML for Oracle WebLogic Server
12c Release 1 (12.1.1)

Part Number E24993-01
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

4 Using the Streaming API for XML (StAX)

This chapter describes how to use the Streaming API for XML (StAX) to parse and generate XML documents.

The chapter includes the following sections:

Overview of the Streaming API for XML

The Streaming API for XML (StAX), specified by JSR-173 at http://www.jcp.org/en/jsr/detail?id=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, at http://www.jcp.org/en/jsr/detail?id=173, 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 http://www.jcp.org/en/jsr/detail?id=173.

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

Table 4-1 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 writeXXX() 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:

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.

Note:

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.

Note:

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. See 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:

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.writeXXX() 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

Table 4-2 lists the standard properties you can set when using the XMLInputFactory to generate an XMLStreamReader or XMLEventReader object.

All properties in Table 4-2 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

Table 4-3 lists the standard properties you can set when using the XMLOutputFactory to generate an XMLStreamWriter or XMLEventWriter object.

All properties in Table 4-3 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 at http://www.jcp.org/en/jsr/detail?id=173.

Boolean

False