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.

Import the weblogic.xml.stream.* classes.

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.

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.

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.

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:

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:

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.

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:

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:

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.

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.

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:

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:

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:

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:

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.

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.

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

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.

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:

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();

Scripting on this page enhances content navigation, but does not change the content in any way.