Outputting a Document

The process of outputting a JDOM Document object is even simpler than the process of creating one. The org.jdom.output package provides helper and utility classes for outputting a Document to various sources. No interface is provided to define required behavior, as output of a Document can be used in a variety of ways, from something as simple as writing to a file to something as complex as triggering events for another application component to use.

Standard XML Output

The most common use for XML data within a JDOM Document is to output that data as XML to a file or another application component, using an OutputStream . Of course, this stream may wrap a console’s output, a file, a URL, or any other construct that can receive data. This task is handled in JDOM by the org.jdom.output.XMLOutputter class. This class provides the following constructors and output method:

public class XMLOutputter {

    // Accept defaults: 2 space indent and new line feeds on
    public XMLOutputter(  );

    // Specify indent, accept default for new line feeds (on)
    public XMLOutputter(String indent);

    // Specify the indention to use and if new line feeds should be used
    public XMLOutputter(String indent, boolean newlines);

    // Output a JDOM Document to a stream
    public void output(Document doc, OutputStream out)throws IOException;

}

When instantiated with the default constructor, this results in a “pretty printing” of the JDOM Document; other options can be supplied for more compact output (such as turning off new lines and removing indentation, resulting in the smallest file possible). The following example shows the SAXTest class we looked at earlier, revised to print the document to the standard output:

import java.io.File;import java.io.IOException;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.Builder;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class SAXTest {

    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: SAXTest [filename to parse]");
            return;
        }

        try {
            // Request document building without validation
            Builder builder = new SAXBuilder(false);
            Document doc = builder.build(new File(args[0]));
            printDocument(doc);
        } catch (JDOMException e) {
            if (e.getRootCause(  ) != null) {
                e.getRootCause().printStackTrace(  );
            }
            e.printStackTrace(  );
        } catch (Exception e) {
               
            e.printStackTrace(  );
               
        }
    }

    public static void printDocument(Document doc) throws IOException {
               
        XMLOutputter fmt = new XMLOutputter(  );
               
        fmt.output(doc, System.out);
               
    }
}

Notice that in our methods that build JDOM Document objects with SAXBuilder and DOMBuilder, we didn’t perform any data massaging or manipulation after building; a built Document is immediately ready for output, making reading and writing XML (possibly from one source to another source) extremely easy.

Firing Off SAX Events

We have already discussed applications of JDOM even when the original XML is available only as a pre-built DOM tree; the DOMBuilder can convert the DOM tree to the much lighter-weight JDOM Document object, and the JDOM API can be used to manipulate the XML data. In the same manner, JDOM can communicate with other applications that expect SAX events as input. The org.jdom.SAXOutputter class provides the ability to fire off SAX events from a supplied JDOM Document object. This provides a complete isolation level between application components, allowing you to use JDOM while still interacting with applications that don’t use JDOM (or just haven’t caught up yet!). Additionally, a DOMOutputter class is being developed to perform the same type of task, converting a JDOM Document object into a DOM tree to pass to other application components. Both of these classes should be complete by the publication of this book, so visit http://www.jdom.org to obtain these updates, as well as the latest version of the JDOM implementation classes.

More important than these two specific classes is the flexibility they indicate: rather than being tied to a specific format, JDOM seeks to allow input and output from any type of input source and to any type of output source. An ApacheOutputter class, for example, could be created to output a JDOM Document created with ApacheBuilder back into an Apache HTTP configuration file format. The output formats can be as varied as the input formats, as JDOM provides only an object model, rather than a specific XML model.

Putting JDOM to Work

As a more complete example of using JDOM, Example 8.5 is a JDOM “test suite” that builds a JDOM Document object from scratch, using both SAXBuilder and DOMBuilder.

Example 8-5. JDOM Test Suite

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import org.jdom.Attribute;
import org.jdom.Comment;
import org.jdom.DocType;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.ProcessingInstruction;
import org.jdom.input.Builder;
import org.jdom.input.DOMBuilder;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

/**
 * <p>
 * Demonstrate building JDOM Documents from scratch and existing XML 
 *   data sources.
 * </p>
 *
 * @version 1.0
 */
public class JDOMTest {
    
    public JDOMTest(  ) {        
    }
    
    /**
     * <p>
     * Build a JDOM <code>Document</code> from scratch
     * </p>
     *
     * @param out <code>OutputStream</code> to write created XML to
     * @throws <code>IOException</code> when output errors occur.
     */
    public void newDocument(OutputStream out) 
        throws IOException, JDOMException {
            
       Namespace ns = Namespace.getNamespace("linux", "http://www.linux.org");
       Document doc = 
         new Document(new Element("config", ns))             
           .setDocType(new DocType("linux:config", 
                                   "DTD/linux.dtd"))
           .addProcessingInstruction("cocoon-process", 
                                     "type="xsp"")
           .addProcessingInstruction(
               new ProcessingInstruction("cocoon-process", 
                                         "type="xslt""));
           
         doc.getRootElement(  )
              .addAttribute("kernel", "2.2.14")         // easy way
              .addAttribute(
                  new Attribute("dist", "RedHat 6.1"))  // hard way
              .addChild(new Element("gui", ns)
                 .setContent("No Window Manager Installed"))
              .addChild(new Comment("Sound Card Configuration"))
              .addChild(new Element("sound")
                .addChild(new Comment("Sound Blaster Card"))
                .addChild(new Element("card")
                    .addChild(new Element("name")
                        .setContent("Sound Blaster Platinum")))
                );
  
       XMLOutputter fmt = new XMLOutputter(  );
       fmt.output(doc, out);        
    }
    
    public void domDocument(File file, OutputStream out) 
        throws IOException, JDOMException {
            
        Builder builder = new DOMBuilder(true);
        Document doc = builder.build(file);
        
        XMLOutputter fmt = new XMLOutputter(  );
        fmt.output(doc, out);        
    }
    
    public void saxDocument(File file, OutputStream out) 
        throws IOException, JDOMException {
            
        Builder builder = new SAXBuilder(true);
        Document doc = builder.build(file);
        
        XMLOutputter fmt = new XMLOutputter(  );
        fmt.output(doc, out);            
    }    
    
    /**
     * <p>
     * Static entry point for JDOM testing.
     * </p>
     */
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: JDOMTest [filename to parse]");
            System.exit(-1);
        }
        
        try {
            JDOMTest test = new JDOMTest(  );

            System.out.println(
                "

----------------------------------------");        
            System.out.println(
                "Testing creating Document from scratch ...");
            System.out.println(
                "----------------------------------------

");        
            test.newDocument(System.out);
        
            System.out.println(
                "

----------------------------------------");
            System.out.println(
                "Testing reading Document using DOM ...");
            System.out.println(
                "----------------------------------------

");                
            test.domDocument(new File(args[0]), System.out);
        
            System.out.println(
                "

----------------------------------------");
            System.out.println(
                "Testing reading Document using SAX ...");
            System.out.println(
                "----------------------------------------

");                
            test.saxDocument(new File(args[0]), System.out);        

            System.out.println(
                "

----------------------------------------");        
            System.out.println(
                "Tests complete. Successful build in place.");
            
        } catch (Exception e) {
            e.printStackTrace(  );
            if (e instanceof JDOMException) {
                System.out.println(((JDOMException)e).getRootCause(  )
                                                     .getMessage(  ));
            } else {
                System.out.println(e.getMessage(  ));
            }
        }
    }    
    
}

Compile the JDOMTest class, and let’s take a look at its output. Supplying an XML file to the class, we can see the file output twice, once built with SAX and once built with DOM, which follows the new XML data created from scratch. Example 8.6 shows parts of this output.

Example 8-6. Output from JDOMTest Class

$ java JDOMText contents.xml

----------------------------------------
Testing creating tree from scratch ...
----------------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE linux:config SYSTEM "DTD/linux.dtd">

<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>


<linux:config xmlns:linux="http://www.linux.org" kernel="2.2.14" 
              dist="RedHat 6.1">
  <linux:gui>No Window Manager Installed</linux:gui>
  <!--Sound Card Configuration-->
  <sound>
    <!--Sound Blaster Card-->
    <card>
      <name>Sound Blaster Platinum</name>
    </card>
  </sound>
</linux:config>

----------------------------------------
Testing reading tree using DOM ...
----------------------------------------


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JavaXML:Book SYSTEM "DTDJavaXML.dtd">

<?xml-stylesheet href="XSLJavaXML.html.xsl" type="text/xsl"?>
<?xml-stylesheet href="XSLJavaXML.wml.xsl" type="text/xsl"
                 media="wap"?>
<?cocoon-process type="xslt"?>
<!--  Java and XML  -->

<JavaXML:Book xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">
  <JavaXML:Title>Java and XML</JavaXML:Title>
  <JavaXML:Contents>
    <JavaXML:Chapter focus="XML">
      <JavaXML:Heading>Introduction</JavaXML:Heading>
      <JavaXML:Topic subSections="7">What Is It?</JavaXML:Topic>

...

----------------------------------------
Testing reading tree using SAX ...
----------------------------------------


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JavaXML:Book SYSTEM "DTDJavaXML.dtd">

<?xml-stylesheet href="XSLJavaXML.html.xsl" type="text/xsl"?>
<?xml-stylesheet href="XSLJavaXML.wml.xsl" type="text/xsl"
                 media="wap"?>
<?cocoon-process type="xslt"?>
<!--  Java and XML  -->

<JavaXML:Book xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/">
  <JavaXML:Title>Java and XML</JavaXML:Title>
  <JavaXML:Contents>
    <JavaXML:Chapter focus="XML">
      <JavaXML:Heading>Introduction</JavaXML:Heading>
...

This output was the result of running JDOMTest with the contents.xml document we have been working with through the various chapters. The JavaXML:References element (and its children) is commented out, as our DTD does not allow those elements in the document. Leaving those elements in results in the following error message (when validation is requested in creating a SAXBuilder or DOMBuilder instance):

org.jdom.JDOMException: Error on line 59 of XML document: Element type 
    "JavaXML:References" must be declared.
        at org.jdom.input.DOMBuilder.build(DOMBuilder.java:121)
        at org.jdom.input.AbstractBuilder.build(AbstractBuilder.java:58)
        at JDOMTest.domDocument(JDOMTest.java:46)
        at JDOMTest.main(JDOMTest.java:79)
Error on line 59 of XML document: Element type "JavaXML:References" 
    must be declared.

One of the key features of JDOM is this error testing; this provides detailed information about the location within the XML input where errors occurred, making validation and well-formedness checking simple. Because input and output of an XML source takes only four lines of code (as shown in the domDocument( ) and saxDocument( ) methods), JDOM can be used to provide a means to ensure your XML documents are well-formed and valid.

Note

For those of you paying close attention, you may have noticed something we did not have to worry about in the code above: validation and namespaces cooperating! Because JDOM handles namespaces internally (rather than depending on DOM Level 2 or SAX 2.0 to supply namespace information), it can perform validation while still providing namespace support. In fact, JDOM actually turns namespace-awareness off in SAXBuilder and DOMBuilder! Not only does this allow validation to occur, but it actually speeds up processing of XML documents.

As a final look at JDOM, we revisit the SAXParserDemo and DOMParserDemo from Chapter 3 and Chapter 7 briefly. Both of these programs printed out XML documents from an input file; while the SAXParserDemo provided more of a lifecycle view of the SAX parsing process, DOMParserDemo was essentially a “pretty-printer” class, outputting the DOM tree in human-readable format. Both classes allowed a look at an XML document; Example 8.7 shows the source for com.oreilly.xml.PrettyPrinter, a utility class that performs this same task using JDOM.

Example 8-7. The com.oreilly.xml.PrettyPrinter Utility Class

package com.oreilly.xml;
 
import java.io.File;

import org.jdom.Document;
import org.jdom.input.Builder;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

/**
 * <b><code>PrettyPrinter</code></b> will output the XML document at a
 *   given URI
 * 
 * @author 
 *   <a href="mailto:[email protected]">Brett McLaughlin</a>
 * @author <a href="mailto:[email protected]">Jason Hunter</a>
 * @version 1.0
 */
public class PrettyPrinter {
    
    /**
     * <p>
     * Pretty prints a given XML URI
     * </p>
     */
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: " +
                "java com.oreilly.xml.PrettyPrinter [XML_URI]");
            return;
        }
        
        String filename = args[0];

        try {
            // Build the Document with SAX and Xerces, no validation
            Builder builder = new SAXBuilder(  );

            // Create the document (without validation)
            Document doc = builder.build(new File(filename));

            // Output the document, use standard formatter
            XMLOutputter fmt = new XMLOutputter(  );
            fmt.output(doc, System.out);
        } catch (Exception e) {
            e.printStackTrace(  );
        }
    }
}

At this point, we have taken a bit of a whirlwind tour through JDOM, and only seen a glimpse of its full functionality. The complete API is documented in Appendix A, and includes all JDOM classes and interfaces, as well as the methods available for each. The support packages for JDOM, org.jdom.adapters, org.jdom.input, and org.jdom.output, are also documented in Appendix A. To continue to illustrate how JDOM is used (as we do with SAX and DOM), we will use JDOM in the examples throughout the rest of the book. Additionally, we compare JDOM to SAX and DOM in each example, ensuring that you can perform tasks using all three APIs when needed. Ultimately, you can decide when each API is useful, and code accordingly. Finally, the most current version of JDOM and the corresponding Javadoc are available online at http://www.jdom.org and http://www.newInstance.com.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.97.216