Download PDF Home History |  | API Search Feedback FAQ

> ## Writing Out a DOM as an XML File

> After you have constructed a DOM--either by parsing an XML file or building it programmatically--you frequently want to save it as XML. This section shows you how to do that using the Xalan transform package.

> Using that package, you'll create a transformer object to wire a `DOMSource` to a `StreamResult`. You'll then invoke the transformer's `transform()` method to write out the DOM as XML data.

> ### Reading the XML

> The first step is to create a DOM in memory by parsing an XML file. By now, you should be getting comfortable with the process.

> Note: The code discussed in this section is in `TransformationApp01.java`.

> The following code provides a basic template to start from. (It should be familiar. It's basically the same code you wrote at the start of Chapter 6. If you saved it then, that version should be essentially equivalent to what you see here.)

>     import javax.xml.parsers.DocumentBuilder;
>     import javax.xml.parsers.DocumentBuilderFactory;
>     import javax.xml.parsers.FactoryConfigurationError;
>     import javax.xml.parsers.ParserConfigurationException;
>     import org.xml.sax.SAXException;
>     import org.xml.sax.SAXParseException;

>     import org.w3c.dom.Document;
>     import org.w3c.dom.DOMException;

>     import java.io.*;

>     public class TransformationApp
>     {
>       static Document document;

>       public static void main(String argv[])
>       {
>         if (argv.length != 1) {
>           System.err.println (
>             "Usage: java TransformationApp filename");
>           System.exit (1);
>         }

>         DocumentBuilderFactory factory =
>           DocumentBuilderFactory.newInstance();
>         //factory.setNamespaceAware(true);
>         //factory.setValidating(true);

>         try {
>           File f = new File(argv[0]);
>           DocumentBuilder builder =
>             factory.newDocumentBuilder();
>           document = builder.parse(f);

>         } catch (SAXParseException spe) {
>           // Error generated by the parser
>           System.out.println("\n** Parsing error"
>             + ", line " + spe.getLineNumber()
>             + ", uri " + spe.getSystemId());
>           System.out.println("  " + spe.getMessage() );

>           // Use the contained exception, if any
>           Exception x = spe;
>           if (spe.getException() != null)
>             x = spe.getException();
>           x.printStackTrace();

>         } catch (SAXException sxe) {
>           // Error generated by this application
>           // (or a parser-initialization error)
>           Exception x = sxe;
>           if (sxe.getException() != null)
>             x = sxe.getException();
>           x.printStackTrace();

>         } catch (ParserConfigurationException pce) {
>           // Parser with specified options can't be built
>           pce.printStackTrace();

>         } catch (IOException ioe) {
>           // I/O error
>           ioe.printStackTrace();
>         }
>       } // main
>     }

> ### Creating a Transformer

> The next step is to create a transformer you can use to transmit the XML to `System.out`.

> Note: The code discussed in this section is in `TransformationApp02.java`. The file it runs on is `slideSample01.xml`. The output is in `TransformationLog02.txt`. (The browsable versions are `slideSample01-xml.html` and `TransformationLog02.html`.)

> Start by adding the following highlighted import statements:

>     import javax.xml.transform.Transformer;
>     import javax.xml.transform.TransformerFactory;
>     import javax.xml.transform.TransformerException;
>     import javax.xml.transform.TransformerConfigurationException;

>     import javax.xml.transform.dom.DOMSource;

>     import javax.xml.transform.stream.StreamResult;

>     import java.io.*;

> Here, you add a series of classes that should now be forming a standard pattern: an entity (`Transformer`), the factory to create it (`TransformerFactory`), and the exceptions that can be generated by each. Because a transformation always has a source and a result, you then import the classes necessary to use a DOM as a source (`DOMSource`) and an output stream for the result (`StreamResult`).

> Next, add the code to carry out the transformation:

>     try {
>       File f = new File(argv[0]);
>       DocumentBuilder builder = factory.newDocumentBuilder();
>       document = builder.parse(f);

>        // Use a Transformer for output
>       TransformerFactory tFactory =
>         TransformerFactory.newInstance();
>       Transformer transformer = tFactory.newTransformer();

>       DOMSource source = new DOMSource(document);
>       StreamResult result = new StreamResult(System.out);
>       transformer.transform(source, result);

> Here, you create a transformer object, use the DOM to construct a source object, and use `System.out` to construct a result object. You then tell the transformer to operate on the source object and output to the result object.

> In this case, the "transformer" isn't actually changing anything. In XSLT terminology, you are using the identity transform, which means that the "transformation" generates a copy of the source, unchanged.

> Note: You can specify a variety of output properties for transformer objects, as defined in the W3C specification at `http://www.w3.org/TR/xslt#output`. For example, to get indented output, you can invoke
> `transformer.setOutputProperty(OutputKeys.INDENT, "yes");`

> Finally, add the following highlighted code to catch the new errors that can be generated:

>     } catch (TransformerConfigurationException tce) {
>       // Error generated by the parser
>       System.out.println ("* Transformer Factory error");
>       System.out.println("  " + tce.getMessage() );

>        // Use the contained exception, if any
>       Throwable x = tce;
>       if (tce.getException() != null)
>         x = tce.getException();
>       x.printStackTrace();
>     } catch (TransformerException te) {
>       // Error generated by the parser
>       System.out.println ("* Transformation error");
>       System.out.println("  " + te.getMessage() );

>       // Use the contained exception, if any
>       Throwable x = te;
>       if (te.getException() != null)
>         x = te.getException();
>       x.printStackTrace();

>     } catch (SAXParseException spe) {
>       ...

> Notes:

> - `TransformerException`s are thrown by the transformer object.
> - `TransformerConfigurationException`s are thrown by the factory.
> - To preserve the XML document's `DOCTYPE` setting, it is also necessary to add the following code:

> `import javax.xml.transform.OutputKeys;
> ...
> if (document.getDoctype() != null){
> String systemValue = (new
> File(document.getDoctype().getSystemId())).getName();
> transformer.setOutputProperty(
> OutputKeys.DOCTYPE_SYSTEM, systemValue
> );
> }`

> ### Writing the XML

> For instructions on how to compile and run the program, see Compiling and Running the Program from the SAX tutorial, Chapter 5. (If you're working along, substitute `TransformationApp` for `Echo` as the name of the program. If you are compiling the sample code, use `TransformationApp02`.) When you run the program on `slideSample01.xml`, this is the output you see:

>     <?xml version="1.0" encoding="UTF-8"?>
>     <!-- A SAMPLE set of slides -->
>     <slideshow author="Yours Truly" date="Date of publication"
>     title="Sample Slide Show">

>       <!-- TITLE SLIDE -->
>       <slide type="all">
>         <title>Wake up to WonderWidgets!</title>
>       </slide>

>       <!-- OVERVIEW -->
>       <slide type="all">
>         <title>Overview</title>
>         <item>Why <em>WonderWidgets</em> are great</item>
>         <item/>
>         <item>Who <em>buys</em> WonderWidgets</item>
>       </slide>

>     </slideshow>

> Note: The order of the attributes may vary, depending on which parser you are using.

> To find out more about configuring the factory and handling validation errors, see Reading XML Data into a DOM, and Additional Information.

> ### Writing Out a Subtree of the DOM

> It is also possible to operate on a subtree of a DOM. In this section, you'll experiment with that option.

> Note: The code discussed in this section is in `TransformationApp03.java`. The output is in `TransformationLog03.txt`. (The browsable version is `TransformationLog03.html`.)

> The only difference in the process is that now you will create a `DOMSource` using a node in the DOM, rather than the entire DOM. The first step is to import the classes you need to get the node you want. Add the following highlighted code to do that:

>     import org.w3c.dom.Document;
>     import org.w3c.dom.DOMException;
>     import org.w3c.dom.Node;
>     import org.w3c.dom.NodeList;

> The next step is to find a good node for the experiment. Add the following highlighted code to select the first `<slide>` element:

>     try {
>       File f = new File(argv[0]);
>       DocumentBuilder builder = factory.newDocumentBuilder();
>       document = builder.parse(f);

>       // Get the first <slide> element in the DOM
>       NodeList list = document.getElementsByTagName("slide");
>       Node node = list.item(0);

> Then make the following changes to construct a source object that consists of the subtree rooted at that node:

>     DOMSource source = new DOMSource(document);
>     DOMSource source = new DOMSource(node);
>     StreamResult result = new StreamResult(System.out);
>     transformer.transform(source, result);

> Now run the application. Your output should look like this:

>     <?xml version="1.0" encoding="UTF-8"?>
>     <slide type="all">
>         <title>Wake up to WonderWidgets!</title>
>       </slide>

> #### Cleaning Up

> Because it will be easiest to do now, make the following changes to back out the additions you made in this section. (`TransformationApp04.java` contains these changes.)

>     Import org.w3c.dom.DOMException;
>     import org.w3c.dom.Node;
>     import org.w3c.dom.NodeList;
>     ...
>       try {
>         ...
>         // Get the first <slide> element in the DOM
>         NodeList list = document.getElementsByTagName("slide");
>         Node node = list.item(0);
>         ...
>         DOMSource source = new DOMSource(node);
>         StreamResult result = new StreamResult(System.out);
>         transformer.transform(source, result);

> ### Summary

> At this point, you've seen how to use a transformer to write out a DOM and how to use a subtree of a DOM as the source object in a transformation. In the next section, you'll see how to use a transformer to create XML from any data structure you are capable of parsing.

Download PDF Home History |  | API Search Feedback FAQ

All of the material in The J2EE(TM) 1.4 Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.