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
PDF · Mobi · ePub

B Using the WebLogic XML Streaming API (Deprecated)

Note:

The WebLogic XML Streaming API has been deprecated as of release 9.0 of WebLogic Server. You should instead use the Streaming API for XML (StAX), a standard specification from the Java Community Process. For details, see Chapter 4, "Using the Streaming API for XML (StAX)."

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

Overview of the WebLogic XML Streaming API

The WebLogic XML Streaming API provides an easy and intuitive way to parse and generate 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, the streaming API gives you more control over parsing than the SAX API.

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 the streaming API, 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 streaming API is often referred to as pull parsing.

You can parse many types of XML documents with the streaming API, such as XML files on the operating system, DOM trees, and sets of SAX events. You convert these XML documents into a stream of events, or an XMLInputStream, and then step through the stream, pulling events such as the start of an element, the end of the document, and so on, off the stack as needed.

The WebLogic Streaming API uses the WebLogic FastParser as its default parser.

For a complete example of parsing an XML document using the streaming API, see the WL_HOME\samples\server\examples\src\examples\xml\orderParser directory, where WL_HOME refers to the top-level WebLogic Server directory.

Table B-1 describes the main interfaces and classes of the WebLogic Streaming API.

Table B-1 Interfaces and Classes of the XML Streaming API

Interface or Class Description
XMLInputStreamFactory

Factory used to create XMLInputStream objects for parsing XML documents.

XMLInputStream

Interface used to contain the input stream of events.

BufferedXMLInputStream

Extension of the XMLInputStream interface to allow marking and resetting of the stream.

XMLOutputStreamFactory

Factory used to create XMLOutputStream objects for generating XML documents.

XMLOutputStream

Interface used write events.

ElementFactory

Utility to create instances of the interfaces used in this API.

XMLEvent

Base interface for all types of events in an XML document, such as the start of an element, the end of an element, and so on.

StartElement

Most important of the XMLEvent sub-interfaces. Used to get information about a start element in an XML document.

AttributeIterator

Object used to iterate over the set of attributes of an element.

Attribute

Object that describes a particular attribute of an element.


Javadocs for the WebLogic XML Streaming API

The following Javadocs provide reference material for the WebLogic XML Streaming API features described in this chapter as well as additional features not explicitly documented:

Parsing an XML Document: Typical Steps

The following procedure describes the typical steps for using the WebLogic XML Streaming API to parse and manipulate an XML document.

The first two steps are required. The next steps you take depend on how you want to process the XML file.

  1. Import the weblogic.xml.stream.* classes.

  2. Get an XML stream of events from an XML file, a DOM tree, or a set of SAX events. You can also filter the XML stream to get only certain types of events, names of specific elements, and so on. See Getting an XML Input Stream.

  3. Iterate over the stream, returning generic XMLEvent types. See Iterating Over the Stream.

  4. For each generic XMLEvent type, determine the specific event type. Event types include the start of an XML document, the end of an element, an entity reference, and so on. See Determining the Specific XMLEvent Type.

  5. Get the attributes of an element. See Getting the Attributes of an Element.

  6. Position the stream by skipping over event, skipping to a particular event, and so on. See Positioning the Stream.

  7. Get the children of an element. See Getting a Substream.

  8. Close the stream. See Closing the Input Stream.

Example of Parsing an XML Document

The following program shows an example of using the XML Streaming API to parse an XML document.

The program takes a single parameter, an XML file, that it converts into an XML input stream. It then iterates over the stream, determining the type of each event, such as the start of an XML element, the end of the XML document, and so on. The program prints out information for three types of events: start elements, end elements, and the character data that forms the body of an element. The program does nothing when it encounters the other types of events, such as comments or start of the XML document.

Note:

The code in bold font is described in detail in the sections following the example.
package examples.xml.stream;
import weblogic.xml.stream.Attribute;
import weblogic.xml.stream.AttributeIterator;
import weblogic.xml.stream.ChangePrefixMapping;
import weblogic.xml.stream.CharacterData;
import weblogic.xml.stream.Comment;
import weblogic.xml.stream.XMLEvent;
import weblogic.xml.stream.EndDocument;
import weblogic.xml.stream.EndElement;
import weblogic.xml.stream.EntityReference;
import weblogic.xml.stream.ProcessingInstruction;
import weblogic.xml.stream.Space;
import weblogic.xml.stream.StartDocument;
import weblogic.xml.stream.StartPrefixMapping;
import weblogic.xml.stream.StartElement;
import weblogic.xml.stream.EndPrefixMapping;
import weblogic.xml.stream.XMLInputStream;
import weblogic.xml.stream.XMLInputStreamFactory;
import weblogic.xml.stream.XMLName;
import weblogic.xml.stream.XMLStreamException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ComplexParse {
  /**
   * Helper method to get a handle on a stream.
   * Takes in a name and returns a stream.  This
   * method usese the InputStreamFactory to create an
   * instance of an XMLInputStream
   * @param name The file to parse
   * @return XMLInputStream the stream to parse
   */
  public XMLInputStream getStream(String name)
    throws XMLStreamException, FileNotFoundException
  {
    XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); 
    XMLInputStream stream = factory.newInputStream(new FileInputStream(name)); 
    return stream;
  }
  /**
   *  Determines the type of event, such as the start
   *  of an element, end of a document, and so on.  If the
   *  event is of type START_ELEMENT, END_ELEMENT, or
   *  CHARACTER_DATA, the method prints out appropriate info;
   *  otherwise, it does nothing.
   *  @param event The XML event that has been parsed
   */
  public void parse(XMLEvent event)
    throws XMLStreamException
  { 
    switch(event.getType()) { 
    case XMLEvent.START_ELEMENT: 
      StartElement startElement = (StartElement) event; 
      System.out.print("<" + startElement.getName().getQualifiedName() ); 
      AttributeIterator attributes = startElement.getAttributesAndNamespaces(); 
      while(attributes.hasNext()){ 
        Attribute attribute = attributes.next(); 
        System.out.print(" " + attribute.getName().getQualifiedName() +  
                          "='" + attribute.getValue() + "'"); 
      } 
      System.out.print(">"); 
      break; 
    case XMLEvent.END_ELEMENT: 
      System.out.print("</" + event.getName().getQualifiedName() +">"); 
      break; 
    case XMLEvent.SPACE: 
    case XMLEvent.CHARACTER_DATA: 
      CharacterData characterData = (CharacterData) event; 
      System.out.print(characterData.getContent()); 
      break; 
    case XMLEvent.COMMENT: 
      // Print comment 
      break; 
    case XMLEvent.PROCESSING_INSTRUCTION: 
      // Print ProcessingInstruction 
      break; 
    case XMLEvent.START_DOCUMENT: 
      // Print StartDocument 
      break; 
    case XMLEvent.END_DOCUMENT: 
      // Print EndDocument 
      break; 
    case XMLEvent.START_PREFIX_MAPPING: 
      // Print StartPrefixMapping 
      break; 
    case XMLEvent.END_PREFIX_MAPPING: 
      // Print EndPrefixMapping 
      break; 
    case XMLEvent.CHANGE_PREFIX_MAPPING: 
      // Print ChangePrefixMapping 
      break; 
    case XMLEvent.ENTITY_REFERENCE: 
      // Print EntityReference 
      break; 
    case XMLEvent.NULL_ELEMENT: 
      throw new XMLStreamException("Attempt to write a null event."); 
    default: 
      throw new XMLStreamException("Attempt to write unknown event 
                                    ["+event.getType()+"]"); 
    } 
  }
  /**
   * Helper method to iterate over a stream
   * @param name The file to parse
   */
  public void parse(XMLInputStream stream)
    throws XMLStreamException
  {
    while(stream.hasNext()) { 
      XMLEvent event = stream.next(); 
      parse(event); 
    }
    stream.close();
  }
  /** Main method.   Takes a single argument: an XML file
   *  that will be converted into an XML input stream.
   */
  public static void main(String args[])
    throws Exception
  {
    ComplexParse complexParse= new ComplexParse();
    complexParse.parse(complexParse.getStream(args[0]));
  }
}

Getting an XML Input Stream

You can use the XML Streaming API to convert a variety of objects, such as XML files, DOM trees, or SAX events, into a stream of events.

The following example shows how to create a stream of events from an XML file:

XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
XMLInputStream stream = factory.newInputStream(new FileInputStream(name));

First you create a new instance of the XMLInputStreamFactory, then use the factory to create a new XMLInputStream from the XML file referred to in the name variable.

The following example shows how to create a stream from a DOM tree:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new java.io.File(file));
XMLInputStream stream = XMLInputStreamFactory.newInstance().newInputStream(doc);

Getting a Buffered XML Input Stream

After you finish iterating over an XMLInputStream object, you cannot access the stream again. If, however, you need to process the stream again, such as send it to another application or iterate over it again in some other way, use a BufferedXMLInputStream object rather than a plain XMlInputStream object.

Use the newBufferedInputStream() method of the XMLInputStreamFactory class to create a buffered XML input stream, as shown in the following example:

XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
BufferedXMLInputStream bufstream =
    factory.newBufferedInputStream(factory.newInputStream(new 
    FileInputStream(name)));

You can use the mark() and reset() methods of the BufferedXMLInputStream object to mark a particular spot in the stream, continue processing the stream, then reset the stream back to the marked spot. See Marking and Resetting a Buffered XML Input Stream for more information.

Filtering the XML Stream

Filtering an XML stream refers to creating a stream that contains only specified types of events. For example, you can create a stream that contains only start elements, end elements, and the character data that make up the body of an XML element. Another example is filtering an XML stream so that only elements with a specified name appear in the stream.

To filter an XML stream, you specify a filter class as the second parameter to the XMLInputStreamFactory.newInputStream() method. You specify the events that you want in the XML stream as parameters to the filter class. The following example shows how to use the TypeFilter class to specify that you want only start and end XML elements and character data in the resulting XML stream:

import weblogic.xml.stream.util.TypeFilter;
XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
XMLInputStream stream = factory.newInputStream(new FileInputStream(name), 
                        new TypeFilter(XMLEvent.START_ELEMENT |
                                       XMLEvent.END_ELEMENT |
                                       XMLEvent.CHARACTER_DATA));

Table B-2 describes the filters provided by the WebLogic XML Streaming API. They are part of the weblogic.xml.stream.util package.

Table B-2 Filters Provided by WebLogic XML Streaming API

Name of Filter Description Sample Usage
TypeFilter

Filter an XML stream based on specified event types, such as XMLEvent.START_ELEMENT, XMLEvent.END_ELEMENT, and so on. See Determining the Specific XMLEvent Type for a full list of event types.

TypeFilter takes an integer bitmask as input; you OR the values to create this bitmask, as shown in the sample.

new TypeFilter (XMLEvent.START_ELEMENT |
 XMLEvent.END_ELEMENT |
 XMLEvent.CHARACTER_DATA)
NameFilter

Filter an XML stream based on the name of an element in the XML document.

new NameFilter ("Book")
NameSpaceFilter

Filter an XML stream based on the specified namespace URI.

new NameSpaceFilter ("http://namespace.org")
NamespaceTypeFilter

Filter an XML stream based on specified event types and namespace URI. This filter combines the functionality of TypeFilter and NameSpaceFilter.

new NamespaceFilter ("http://namespace.org", XMLEvent.START_ELEMENT)

The example returns a stream where all start elements have the specified namespace.


Creating a Custom Filter

You can also create your own filter if the ones included in the API do not meet your needs.

  1. Create a class that implements the ElementFilter interface and contains a method called accept(XMLEvent). This method tells the XMLInputStreamFactory.newInputStream() method whether to add a particular event to the stream or not, as shown in the following example:

    package my.filters;
    
    import weblogic.xml.stream.XMLName;
    import weblogic.xml.stream.ElementFilter;
    import weblogic.xml.stream.events.NullEvent;
    
    public class SuperDooperFilter implements ElementFilter {
    
      protected String name;
    
      public SuperDooperFilter(String name)
      {
        this.name = name;
      }
    
      public boolean accept(XMLEvent e) {
        if (name.equals(e.getName().getLocalName()))
          return true;
        return false;
      }
    }
    
  2. In your XML application, be sure to import the new filter class:

    import my.filters.SuperDooperFilter
    
  3. Specify the filter as the second parameter to the newInputStream() method, passing to the filter class the types of events you want to appear in the XML stream in whatever format required by your filter class:

    XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
    XMLInputStream stream = factory.newInputStream(new FileInputStream(name), 
                            new SuperDooperFilter(param));
    

Iterating Over the Stream

Once you have a stream of events, the next step is to methodically step through it using the XMLInputStream.next() and XMLInputStream.hasNext() methods, as shown in the following example:

while(stream.hasNext()) {
  XMLEvent event = stream.next();
  System.out.print(event);
}

Determining the Specific XMLEvent Type

The XMLInputStream.next() method returns an object of type XMLEvent. XMLEvent has subinterfaces that further classify what this event might be, such as the start of the XML document, the end of an element, an entity reference, and so on. The XMLEvent interface also contains corresponding fields, or constants, as well as a set of methods that you can use to identify the actual event. Figure B-1 shows the hierarchy of the XMLEvent interface and its subinterfaces.

Figure B-1 Hierarchy of the XMLEvent Interface and Its SubInterfaces

Description of Figure B-1 follows
Description of "Figure B-1 Hierarchy of the XMLEvent Interface and Its SubInterfaces"

Table B-3 lists the subclasses and fields of the XMLEvent class that you can use to identify a particular event while parsing the XML stream

Table B-3 Subclasses and Fields of the XMLEvent Class

XMLEvent Subclass Field of the XMLEvent Class used to Identify Subclass Method used to Identify Subclass Description of the Subclass Event

ChangePrefixMapping

CHANGE_PREFIX_MAPPING

isChangePrefixMapping

Signals that a prefix mapping has changed from an old namespace to a new namespace.

CharacterData

CHARACTER_DATA

isCharacterData

Signals that the returned XMLEvent object contains the character data from the body of the element.

Comment

COMMENT

isComment

Signals that the returned XMLEvent object contains an XML comment.

EndDocument

END_DOCUMENT

isEndDocument

Signals the end of the XML document.

EndElement

END_ELEMENT

isEndElement

Signals the end of an element in the XML document.

EndPrefixMapping

END_PREFIX_MAPPING

isEndPrefixMapping

Signals that a prefix mapping has gone out of scope.

EntityReference

ENTITY_REFERENCE

isEntityReference

Signals that the returned XMLEvent object contains an entity reference.

ProcessingInstruction

PROCESSING_INSTRUCTION

isProcessingInstruction

Signals that the returned XMLEvent object contains a processing instruction.

Space

SPACE

isSpace

Signals that the returned XMLEvent object contains whitespace.

StartDocument

START_DOCUMENT

isStartDocument

Signals the start of an XML document.

StartElement

START_ELEMENT

isStartElement

Signals the start of a element in the XML document.

StartPrefixMapping

START_PREFIX_MAPPING

isStartPrefixMapping

Signals that a prefix mapping has started its scope.


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

switch(event.getType()) {
    case XMLEvent.START_ELEMENT:
      // Start of an element
      System.out.println ("Start Element\n");
      break;

    case XMLEvent.END_ELEMENT:
      // End of an element
      System.out.println ("End Element\n");
      break;

    case XMLEvent.PROCESSING_INSTRUCTION:
      // Processing Instruction
      System.out.println ("Processing instruction\n");
      break;

    case XMLEvent.SPACE:
      // Whitespace
      System.out.println ("White space\n");
      break;

    case XMLEvent.CHARACTER_DATA:
      // Character data
      System.out.println ("Character data\n");
      break;

    case XMLEvent.COMMENT:
      // Comment
      System.out.println ("Comment\n");
      break;

    case XMLEvent.START_DOCUMENT:
      // Start of the XML document
      System.out.println ("Start Document\n");
      break;

    case XMLEvent.END_DOCUMENT:
      // End of the XML Document
      System.out.println ("End Document\n");
      break;

    case XMLEvent.START_PREFIX_MAPPING:
      // The start of a prefix mapping scope
      System.out.println ("Start prefix mapping\n");
      break;

    case XMLEvent.END_PREFIX_MAPPING:
      // The end of a prefix mapping scope
      System.out.println ("End prefix mapping\n");
      break;

    case XMLEvent.CHANGE_PREFIX_MAPPING:
      // Prefix mapping has changed namespaces
      System.out.println ("Change prefix mapping\n");
      break;

    case XMLEvent.ENTITY_REFERENCE:
      // An entity reference
      System.out.println ("Entity reference\n");
      break;
    default:

      throw new XMLStreamException("Attempt to parse unknown event 
                                    [" + event.getType() + "]");
    }

Getting the Attributes of an Element

To get the attributes of an element in an XML document, you must first cast the XMLEvent object that was returned by the XMLInputStream.next() method to a StartElement object.

Because you do not know how many attributes an element might have, you must first create an AttributeIterator object to contain the entire list of attributes, and then iterate over the list until there are no more attributes. The following example describes how to do this as part of the START_ELEMENT case of the switch statement shown in Iterating Over the Stream:

case XMLEvent.START_ELEMENT:

    StartElement startElement = (StartElement) event;
    System.out.print("<" + startElement.getName().getQualifiedName() );
    AttributeIterator attributes = startElement.getAttributesAndNamespaces();
    while(attributes.hasNext()){
      Attribute attribute = attributes.next();
      System.out.print(" " + attribute.getName().getQualifiedName() + 
                        "='" + attribute.getValue() + "'");
    }
    System.out.print(">");
    break;

The example first creates a StartElement object by casting the returned XMLEvent to StartElement. It then creates an AttributeIterator object using the method StartElement.getAttributesAndNamespaces(), and iterates over the attributes using the AttributeIterator.hasNext() method. For each Attribute, it uses the Attributes.getName().getQualifiedName() and Attribute.getValue() methods to return the name and value of the attribute.

You can also use the getNamespace() and getAttributes() methods to return just the namespaces or attributes on their own.

Positioning the Stream

Table B-4 describes the methods of the XMLInputStream interface that you can use to skip ahead to specific locations in the stream.

Table B-4 Methods Used to Position the Input Stream

Method of XMLInputStream Description
skip()

Positions the input stream to the next stream event.

Note: The next event might not necessarily be an actual element in the XML file; for example, it could be a comment or white space.

skip(int)

Positions the input stream to the next event of this type.

Examples of event types are XMLEvent.START_ELEMENT and XMLEvent.END_DOCUMENT. Refer to Table B-3 for the full list of event types.

skip(XMLName)

Positions the input stream to the next event of this name.

skip(XMLName, int)

Positions the input stream to the next event of this name and type.

skipElement()

Skips to the next element (does not skip to the sub-elements of the current element).

peek()

Checks the next event without actually reading it from the stream.


The following example shows how you can modify the basic code for iterating over an input stream to skip over the character data in the body of an XML element:

while(stream.hasNext()) {
      XMLEvent peek = stream.peek();
      if (peek.getType() == XMLEvent.CHARACTER_DATA ) {
        stream.skip();
        continue;
      }
      XMLEvent event = stream.next();
      parse(event);
    }

The example shows how to use the XMLInputStream.peek() method to determine the next event on the stream. If the type of event is XMLEvent.CHARACTER_DATA, then skip the event and go to the next one.

Getting a Substream

Use the XMLInputStream.getSubStream() method to get a copy of the next element, including all its subelements. The getSubstream() method returns an XMLInputStream object. Your position in the parent stream (or the stream from which you called getSubStream()) does not move. In the parent stream, if you want to skip the element you just got with getSubStream(), use the skipElement() method.

The getSubStream() method keeps a count of the START_ELEMENT and END_ELEMENT events it encounters, and as soon as the number is equal (or in other words, as soon as it finds the complete next element) it stops and returns the resulting substream as an XMLInputStream object.

For example, assume that you are using the XML Streaming API to parse the following XML document, but you are only interested in the substream delineated by the <content> and </content> tags:

<book>
  <title>The History of the World</title>
  <author>Juliet Shackell</author>
  <publisher>CrazyDays Publishing</publisher>
  <content>
      <chapter title='Just a Speck of Dust'>
        <synopsis>The world as a speck of dust</synopsis>
        <para>Once the world was just a speck of dust...</para>
      </chapter>
      <chapter title='Life Appears'>
        <synopsis>Move over dust, here comes life.</synopsis>
        <para>Happily, the dust got a companion: life...</para>
      </chapter>
   </content>
</book>

The following code fragment shows how you can skip to the <content> start element tag, get the substream, and parse it using a separate ComplexParse object:

if (stream.skip( ElementFactory.createXMLName("content")))
       {
          ComplexParse complexParse = new ComplexParse();
          complexParse.parse(stream.getSubStream());
       }

When you call this method on the previous XML document, you get the following output:

<content>
      <chapter title='Just a Speck of Dust'>
        <synopsis>The world as a speck of dust</synopsis>
        <para>Once the world was just a speck of dust...</para>
      </chapter>
      <chapter title='Life Appears'>
        <synopsis>Move over dust, here comes life.</synopsis>
        <para>Happily, the dust got a companion: life...</para>
      </chapter>
</content>

Marking and Resetting a Buffered XML Input Stream

If you are using a BufferedXMLInputStream object, you can use the mark() and reset() methods to mark the stream at a particular spot, process the stream, and then subsequently reset the stream back to the marked spot. These methods are useful if you want to further manipulate the stream after initially iterating over it.

Note:

If you read a buffered stream without marking it, you cannot access what you've just read. In other words, just because the stream is buffered, it does not automatically mean you can reread it. You must mark it first.

The following example shows a typical use of the BufferedXMLInputStream object:

XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
    BufferedXMLInputStream bufstream =
    factory.newBufferedInputStream(factory.newInputStream(new 
                FileInputStream(name)));

    // mark the start of the stream
    bufstream.mark();

    // process it locally
    bufferedParse.parse(bufstream);

    // reset the stream to the mark
    bufstream.reset();

    // send stream off to another application
    ComplexParse complexParse =  new ComplexParse();
    complexParse.parse(bufstream);

Closing the Input Stream

It is good programming practice to explicitly close the XML input stream when you are finished with it. To close an input stream, use the XMLInputStream.close() method, as shown in the following example:

// close the input stream
input.close();

Generating a New XML Document: Typical Steps

The following procedure describes the typical steps for using the WebLogic XML Streaming API to generate a new XML document.

The first two steps are required. The next steps you take depend on how you want to generate the XML file.

  1. Import the weblogic.xml.stream.* classes.

  2. Create an XML output stream to which to write the XML document. See Creating an XML Output Stream.

  3. Add events to the XML output stream. See Adding Elements to the Output Stream.

  4. Add attributes to the XML output stream. See Adding Attributes to an Element on the Output Stream.

  5. Add an input stream to the output stream. See Adding an Input Stream to an Output Stream.

  6. Print the output stream. See Printing an Output Stream.

  7. Close the output stream. See Closing the Output Stream.

Example of Generating an XML Document

The following program shows an example of using the XML Streaming API to generate an XML document.

The program first creates an output stream based on a PrintWriter object, then adds elements to the output stream to create a simple XML purchase order, described in the comments of the program. The program also shows how to add an input stream based on a separate XML file to the output stream.

Note:

The topics following the example describe it in more detail.
package examples.xml.stream;

import weblogic.xml.stream.XMLInputStream;
import weblogic.xml.stream.XMLOutputStream;
import weblogic.xml.stream.XMLInputStreamFactory;
import weblogic.xml.stream.XMLName;
import weblogic.xml.stream.XMLEvent;
import weblogic.xml.stream.StartElement;
import weblogic.xml.stream.EndElement;
import weblogic.xml.stream.Attribute;
import weblogic.xml.stream.ElementFactory;
import weblogic.xml.stream.XMLStreamException;
import weblogic.xml.stream.XMLOutputStreamFactory;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

/**
 * Program that prints out a very simple purchase order that looks
 * like the following:
 *
 * <purchase_order>
 *  <name>Juliet Shackell</name>
 *  <item id="1234" quantity="2">Fabulous Chair</item>
 *  <!-- this is a comment-->
 *  <another_file>
 *    This comes from another file called "another_file.xml"
 *  </another_file>
 * </purchase_order>
 *
 * In the preceding XML file, the <another_file> element is actually another
 * XML file that is passed as an argument to the program, converted into an
 * XMLInputStream, then added to the output stream.
 */
public class PrintPurchaseOrder {

  /**
   * Helper method to get a handle on a stream.
   * Takes in a name and returns a stream.  This
   * method uses the InputStreamFactory to create an
   * instance of an XMLInputStream
   * @param name The file to parse
   * @return XMLInputStream the stream to parse
   */
  public XMLInputStream getInputStream(String name)
    throws XMLStreamException, FileNotFoundException
  {
    XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
    XMLInputStream stream = factory.newInputStream(new FileInputStream(name));
    return stream;
  }
  public static void main(String args[])
    throws Exception
  {
    PrintPurchaseOrder printer = new PrintPurchaseOrder();
    //
    // Create an output stream.
    //
    XMLOutputStreamFactory factory = XMLOutputStreamFactory.newInstance();
    XMLOutputStream output = factory.newOutputStream(new           
                                        PrintWriter(System.out,true));
   // add the <purchase_order> root element
   output.add(ElementFactory.createStartElement("purchase_order"));
   output.add(ElementFactory.createCharacterData("\n"));

   // add the <name> element
   output.add(ElementFactory.createStartElement("name"));
   output.add(ElementFactory.createCharacterData("Juliet Shackell"));
   output.add(ElementFactory.createEndElement("name"));
   output.add(ElementFactory.createCharacterData("\n"));

   // add the <item> element along with the id and quantity attributes
   output.add(ElementFactory.createStartElement("item"));
   output.add(ElementFactory.createAttribute("id","1234"));
   output.add(ElementFactory.createAttribute("quantity","2"));
   output.add(ElementFactory.createCharacterData("Fabulous Chair"));
   output.add(ElementFactory.createEndElement("item"));
   output.add(ElementFactory.createCharacterData("\n"));

    // add a comment
   output.add("<!-- this is a comment-->");
   output.add(ElementFactory.createCharacterData("\n"));

   // create an input stream from each XML file argument then add it to the output
   for (int i=0; i < args.length; i++)
   //
   // Get an input stream and add it to the output stream
   //
   output.add(printer.getInputStream(args[i]));

    // Finally, end the root "purchase_order" element
   output.add(ElementFactory.createEndElement("purchase_order"));
   output.add(ElementFactory.createCharacterData("\n")); 

    //
    // Print the results to the screen
    //
    output.flush();

   // Close the output streams
   output.close();
  }
}

The preceding program produces the following output:

<purchase_order>
  <name>Juliet Shackell</name>
  <item id="1234" quantity="2">Fabulous Chair</item>
  <!-- this is a comment-->
  <another_file>
     This is from another file.
  </another_file>
</purchase_order>

Creating an XML Output Stream

One of the first steps in generating an XML document using the Weblogic XML Streaming API is to create an output stream which holds the document as it is being built. Creating an XML output stream is similar to creating an input stream: you first create an instance of the XMLOutputStreamFactory and then create an output stream with the XMLOutputStreamFactory.newOutputStream() method, as shown in the following example:

XMLOutputStreamFactory factory = XMLOutputStreamFactory.newInstance();
    XMLOutputStream output = factory.newOutputStream(new
                              PrintWriter(System.out,true));

The following example shows how to create an XMLOutputStream based on a DOM tree:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(false);
    dbf.setNamespaceAware(true);
    Document doc = dbf.newDocumentBuilder().newDocument();
    XMLOutputStream out =
         XMLOutputStreamFactory.newInstance().newOutputStream(doc);

You can use the XMLOutputStreamFactory.newOutputStream() method to create an output stream based on the following four Java objects, depending on what the final form of the XML document will be (such as a file on the operating system, a DOM tree, and so on):

  • java.io.OutputStream

  • java.io.Writer

  • org.xml.sax.ContentHandler

  • org.w3c.dom.Document

Adding Elements to the Output Stream

Use the XMLOutputStream.add(XMLEvent) method to add elements to the output stream. Use the ElementFactory to create the particular element.

The ElementFactory interface includes methods to create each type of element; the general format is ElementFactory.createXXX() where XXX refers to the particular element, such as createStartElement(), createCharacterData(), and so on. You can create most elements by passing the name as a String or as an XMLName.

Tip:

The XMLOutputStream does not validate your XML.

Note:

Each time you create a start element, you must explicitly also create an end element at some point. The same rule applies to creating a start document.

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

<name>Juliet Shackell</name>

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

output.add(ElementFactory.createStartElement("name"));
   output.add(ElementFactory.createCharacterData("Juliet Shackell"));
   output.add(ElementFactory.createEndElement("name"));
   output.add(ElementFactory.createCharacterData("\n"));

The final createCharacterData() method adds a newline character to the output stream. This is optional, but useful if you want to create human-readable XML.

Adding Attributes to an Element on the Output Stream

Use the XMLOutputStream.add(Attribute) to add attributes to an element you have just created. Use the ElementFactory.createAttribute() method to create a particular attribute.

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

<item id="1234" quantity="2">Fabulous Chair</item>

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

output.add(ElementFactory.createStartElement("item"));
   output.add(ElementFactory.createAttribute("id","1234"));
   output.add(ElementFactory.createAttribute("quantity","2"));
   output.add(ElementFactory.createCharacterData("Fabulous Chair"));
   output.add(ElementFactory.createEndElement("item"));
   output.add(ElementFactory.createCharacterData("\n"));

Note:

Be sure you add attributes to an element after you create the start element but before you create the corresponding end element. Otherwise, although your code will compile successfully, you will get a runtime error when you try to run the program. For example, the following code returns an error because the attributes are added to the <item> element after the element has been explicitly ended:
output.add(ElementFactory.createStartElement("item"));
output.add(ElementFactory.createEndElement("item"));
output.add(ElementFactory.createAttribute("id","1234"));
output.add(ElementFactory.createAttribute("quantity","2"));
output.add(ElementFactory.createCharacterData("Fabulous Chair"));
output.add(ElementFactory.createCharacterData("\n"));

Adding an Input Stream to an Output Stream

When creating an XML output stream, you might want to add an existing XML document, such as an XML file or a DOM tree, to the output stream. To do this, you must first convert the XML document to an XML input stream, then use XMLOutputStream.add(XMLInputStream) method to add the input stream to the output stream.

The following example first shows a method called getInputStream() that creates an XML input stream from an XML file and then how to use the method to add the created input stream to an output stream:

/**
   * Helper method to get a handle on a stream.
   * Takes in a name and returns a stream.  This
   * method uses the InputStreamFactory to create an
   * instance of an XMLInputStream
   * @param name The file to parse
   * @return XMLInputStream the stream to parse
   */

  public XMLInputStream getInputStream(String name)
    throws XMLStreamException, FileNotFoundException
  {
    XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance();
    XMLInputStream stream = factory.newInputStream(new FileInputStream(name));
    return stream;
  }

....

   // create an input stream from each XML file argument then add it to the output
   for (int i=0; i < args.length; i++)
   //
   // Get an input stream and add it to the output stream
   //
   output.add(printer.getInputStream(args[i]));

Printing an Output Stream

Use the XMLOutputStream.flush() method to print out the XML output stream to whatever object you created it from. For example, if you created an XML output stream from a PrintWriter object, then the flush() method prints the stream to the standard output.

Note:

If you are writing to an XMLOutputStream based on a DOM tree, you must execute the flush() method before you can manipulate the DOM.

The following example shows how to print an output stream:

//
    // Print the results to the screen
    //
    output.flush();

Closing the Output Stream

It is good programming practice to explicitly close the XML output stream when you are finished with it. To close an output stream, use the XMLOutputStream.close() method, as shown in the following example:

// close the output stream
output.close();