Interactive Java & JDOM online tutorial

Written by James Britt, published at TopXML

What is this PDF?
This PDF is supplied to our customers for printing purposes. This PDF does not contain live links, nor does it have many of the other advantages of the live online tutorial. If you purchase this online tutorial you will get the source code, all accompanying material, the interactive exam and this PDF. We encourage you to go to http://www.topxml.com/tutorials to make your purchase, if you haven’t yet! If you already have made your purchase, then thank you!

Page 1

Introduction
Java and XML play well together. Most XML parsers and tools are written in Java; the XML DOM specification from the W3C even defines language bindings for Java. Despite all this, there are aspects of the XML specs that do not lend themselves to an easy mapping to Java constructs. JDOM is an attempt to define an XML DOM API built around native Java data types and objects. JDOM itself is not a parser; it is a wrapper, and requires the presence of an underlying parser, such as Xerces. The name JDOM follows the Sun™ practice of NAA (not an abbreviation). Despite the presence of s leading letter J, and the letters DOM, it does not actually stand for anything. JDOM stands for JDOM. This tutorial will first show you how to obtain and install JDOM, including setting up the required environment variables. It will then go through the fundamental JDOM features. You will learn how to create XML documents from scratch, using the familiar node types: elements, attributes, character data, comments, and processing instructions You will see how to read and write XML files from and to disk, and how to have a JDOM instance receive DOM data from other objects. The tutorial explains JDOM exceptions. You’ll see how JDOM can interact with SAX and W3C DOM objects, and finally, how use JDOM with XSLT.

Page 2

Installing JDOM
The most current version of JDOM is always available from the JDOM web site, http://www.jdom.org. The code is written in Java, so there are no known platform dependencies. However, you may prefer to get the collection of source, class files, and documentation in an archive format best suited for your operating system. You can get any of the stable (though still beta) releases, or live dangerously and pull the latest code from CVS. However, unless you need some essential JDOM feature that is not part of the most current beta release, you would do best to avoid the bleeding edge. The version used for this tutorial is jdom_1_0_b7. Each time you move from one version to the next you should read the assorted text files that accompany the code. In particular, pay attention to the README, CHANGES, and LICENSE files. These will inform you of installation procedures, any known issues, changes since the last release, and conditions under which you may use the software. JDOM installation is as simple as extracting the compressed files into some suitable location and running a single script. On Microsoft Windows, the files will extract to a folder named jdom-b7. Where this is created is up to you. I generally place all of my Java tools under c:\java (for example, c:\java\j2sdkee1.3 or c:\java\jdk1.3). There is nothing special about this, and where you install JDOM is not important so long as you can add the location to your Java class path. Once the files are extracted, open up a command prompt window and go to the jdom-b7 directory. There should be a batch script named build.bat. (There will be other files with similar names, but they do not concern us right now.) The build process relies on at least one bit of environment information, so you must have an environment variable named JAVA_HOME defined to point to your Java SDK root directory. You already have done this if you have installed other Java applications, but you can always do it at the command prompt as in this example: C:\> set JAVA_HOME=C:\java\jdk1.2.2 On Unix, you would do JAVA_HOME=/usr/java; export JAVA_HOME or setenv JAVA_HOME /usr/local/java depending on your shell. Of course, be sure to use the actual path and directory name for your particular installation. Run this batch script by typing build at the command prompt and pressing the return key: C:\java\jdom-b7>build And on Unix, run $ ./build.sh The build script will compile and install the JDOM class files. Actually, the script will really just call the Java ant program (included as part of the JDOM archive), and ant will handle the compilation and installation. If you are not familiar with ant, don’t worry. While it is a handy tool for managing Java source compilation you do not need it once JDOM is installed.

Page 3

Note that if you’re compiling with Java 1.1, then you need to use the build11 script: C:\java\jdom-b7>build11 Or $ ./build11.sh

Page 4

sh for bash shell JDOM_HOME=/usr/local/java/jdom-b7.Further Installation Details Aside from the basic class files. You can add this to current CLASSPATH environment variable like this. and that you may want to make a global CLASSPATH change by altering how your environment variables are set at boot time.sh) to set the class path. One handy way to manage this is to use simple batch scripts to set the class path when needed./build/jdom. or create a JDOM jar archive. you may also want to compile the samples.jar. you should set your class path to include the new jar and class files. C:\java\jdom-b7\build Note that this will only effect the environment for the current command line session. at the command line: Set CLASSPATH=%CLASSPATH%.%JDOM_HOME%\lib\jaxp.bat (or setcp.%JAVA_HOME%\lib\t ools. These.jar: $JDOM_HOME/lib/xerces. %JDOM_HOME%\lib\xerces. there are other files needed by JDOM applications. running build will create a jdom. export JDOM_HOME CLASSPATH=$CLASSPATH:$JDOM_HOME/build/classes:$JAVA_HOME/lib/tool s. use # setcp. should be added to your class path.jar file in the build subdirectory of the JDOM installation directory.jar:$JDOM_HOME/lib/jaxp. and what versions. Aside from jdom. prior to compiling or running any JDOM code. like this: @echo off REM File setcp. Page 5 .bat set JDOM_HOME=C:\java\jdom-b7 set CLASSPATH=%CLASSPATH%. or you may prefer to have more control over what classes. Here are the available build targets: Target name package [default] compile samples javadoc clean Results Creates .jar.jar Compiles the source code Compiles example code Generates the API documentation Restores the distribution to its original and clean state You can call any of these targets by running the build script with the target name as a parameter: C:\java\jdom-b7>build javadoc Once the source has been compiled. are included in your class path. too.jar For Unix.jar.jar export CLASSPATH Then. By default.%JDOM_HOME%\build\classes. Depending on your Java development environment you may not want to clutter the class path with too many items. you run setcp.

To begin. let’s learn more about constructing XML documents. Finally. which may be used to define namespace details. For a Document. it has been deprecated out of existence: if you try to use it. the code sets some text content for the root element. root.) Once the Document is created. The simplest one takes a single String that becomes the name of the element. (Later on we’ll look at the other constructors. If you compile and run this code you should see these results: E:\dev\topxml\jdom\testcode>java example1 [Document: No DOCTYPE declaration.*.7 beta API describes the getSerializedForm method as a way to emit the actual XML. we’ll set up a basic Java class file.) The class contains the ubiquitous main method to allow testing from the command line. Root is [Element: <myRootElement/>]] Hmm … that doesn’t look like XML. which we’ll see in a moment. we’ll cover this shortly. (The code omits its own package declaration since we will compile and test the code in the same directory. Inside main the code declares a variable of type Element (a JDOM class). a Document object is instantiate by calling the Document constructor. you will get a run-time error saying that the method is not yet implemented. The proper way to emit the XML text is to use an XMLOutputter object. Page 6 . public class example1 { public static void main(String[] args) { Element root = new Element("myRootElement"). showing how to construct our XML by hand using the JDOM API. The Element class has multiple constructors. but states that it has been deprecated. Document doc = new Document(root).) After crating an Element. this emits a somewhat verbose delineation of the object. passing in the new Element. the toString method is called by default. The reason is that when a Document object is used in a context.setText("This is a root element"). (There is a second Document constructor that accepts an Element and a DocType object.jdom. which can be handy during debugging.println(doc). We’re going to begin from the ground up. the code prints out the Document object. System.java: import org.Creating a DOM from Scratch There are multiple ways to create an XML document using JDOM. We’ll display the XML when we have something a bit more substantial. } } The file begins with the import of the jdom package. example1.out. String The JDOM 0. and instantiates it by calling the Element constructor. In fact. First.

After recompiling the code we get this output: E:\dev\topxml\jdom\testcode>java example1 [Document: [DocType: <!DOCTYPE myRootElement> ]. System. root.println(doc).out. DocType dt = new DocType("myRootElement"). dt). Document doc = new Document(root. Root is [Element: <myRootElement/>]] Page 7 . It works like this: Element root = new Element("myRootElement").I mentioned that there was another Document constructor that allows us to pass in a DocType object.setText("This is a root element").

System. Root is [Element: <myRootElement/>]] Hmm. toString for a Document only tells you about the Document per se. what’s new? In this version.println(doc). Attributes.setText("This is el!"). public class example2 { public static void main(String[] args) { Element root = new Element("myRootElement"). That’s not the whole document. Compiling and running this class gives this output: E:\dev\topxml\jdom\testcode>java example2 [Document: [DocType: <!DOCTYPE myRootElement> ]. el.*. } } So. dt).jdom. to see the complete XML we need to use an outputter object Page 8 . root. So. not the lower levels.Adding Elements. Element el = new Element("el"). According to the JDOM API JavaDocs. Document doc = new Document(root. this method’s primary value is for debugging.java: import org.setText("This is a root element"). and Character Data A document with only a root element and some basic text is probably less than what we want from XML. we create another Element instance.out. let’s see how we can build up the document by adding elements and attributes. and add it as a child of the root element using addContent. DocType dt = new DocType("myRootElement"). we’ll create a new Java file named example2.addContent(el). root. Using our first file as a base.

addContent(el). Element el = new Element("el").setText("This is el!").io. but a root element named “rootBeer.setText("This is a root element"). named ‘Foo” and ‘Bar. Document doc = new Document(root. } } } Before we go further.Emitting the JDOM XML Let’s see how to get to the actual XML. System." Each element will have the text "Look at me. I think there enough has been covered that you can begin trying some worksheet code.output.output(doc. dt). create a new Document that has no DOCTYPE.out). root. To actually use the XMLOutputter the code needs to trap for possible exceptions.” The root element will have two child elements. root. as in this improved version of example2: import org.output(doc. but the choice is yours. import org. el.*. outputter. like this: XMLOutputter outputter = new XMLOutputter(" outputter. For the first worksheet.” Page 9 .XMLOutputter. To do this we need to use the JDOM XMLOutputter object. ". public class example2a { public static void main(String[] args) { Element root = new Element("myRootElement"). emit the XML using the XMLOutputter object Worksheet 1 Create a new Document that has no DocType. true). System. It probably makes sense to set this to true if you’ve specified an indentation string.jdom.out).” Each element will have the text “Look at me. } catch (java.” The root element will have two child elements. The first is a String used to indent the resulting XML. DocType dt = new DocType("myRootElement"). The second parameter is a Boolean telling the constructor if this outputter should add line feeds to the XML.jdom. named "Foo" and "Bar.IOException e){ e. true). try{ XMLOutputter outputter = new XMLOutputter(" ".printStackTrace(). The constructor takes two arguments." Finally. but a root element named “rootBeer.

println.XMLOutputter.If you like. } catch (java. you can pass the resulting Document to System. System. Page 10 . bar. Element foo = new Element("Foo"). try{ XMLOutputter outputter = new XMLOutputter(" outputter.io. Solution 1: import org.").setText("Look at me.addContent(bar).*.IOException e){ e." // Each element will have the text "Look at me.out. root. Document doc = new Document(root).jdom.output(doc. but a root element named "rootBeer." Element root = new Element("rootBeer").printStackTrace()." // The root element will have two child elements. foo. } } } ". root. public class ws1 { public static void main(String[] args) { // Task: Create a new Document that has no // DocType.addContent(foo). // named "Foo" and "Bar. true).setText("Look at me.jdom.").output. import org. Element bar = new Element("Bar").out).

try{ XMLOutputter outputter = new XMLOutputter(" ".addContent(foo). though be mindful that there may be more name changes in future versions. here’s a new Java file.) Page 11 .IOException e){ e. root.Attributes Debates about “Elements or Attributes?” erupt with amazing regularity. foo. adding element content is done using a method named addContent. passing in the name of the attribute and the attribute value.setText("Look at me. true). "20011021"). we’ll see now how to add attributes to your XML.XMLOutputter. example3.printStackTrace(). Attribute attrBar = new Attribute("city". } catch (java. Building on the solution for worksheet 2.output(doc. not setContent. bar.*. Element foo = new Element("Foo"). Do not be thrown off by naming inconsistencies. "Scottsdale"). foo.setText("Look at me. import org. Element bar = new Element("Bar").jdom.").java: import org. Then you can go argue about which one is better. foo.addContent(bar).io. } } } It’s pretty straightforward: Create a new Attribute instance by calling the Attribute constructor. outputter. (Something to note here is that the JDOM JavaDocs list a method named addAttribute that has been deprecated in favor of setAttribute. public class example3 { public static void main(String[] args) { Element root = new Element("rootBeer"). Document doc = new Document(root). Attribute attrFoo = new Attribute("date". Rather than force you to use only Element objects. root. Then add the Attribute to an Element by calling setAttribute.").output. System.setAttribute(attrBar).setAttribute(attrFoo).jdom. However.out).

In each case the child element is named “number. Element root = new Element("count"). el. x < 10.” Each element has an attribute named “value”.out). the value of this attribute is the current value of the loop index.etc . and add child elements to the root element by looping from 0 to 9.addContent(el). x + ""). for(int x = 0.output.output(doc. Document doc = new Document(root).*.printStackTrace()." Each element // has an attribute named "value".jdom.. import org. --> Worksheet 2 Task: Write a program that creates a document.” Each element has an attribute named “value”. Attribute val = null. true). In each case the child element is named “number. } try{ XMLOutputter outputter = new XMLOutputter(" ". the value // of this attribute is the current value of // the loop index.jdom.IOException e){ e. the value of this attribute is the current value of the loop index: <number value=’0’/> <number value=’1’/> <!-.. In each case the child // element is named "number. and adds child elements to the root element by looping from 0 to 9. Solution 2: import org. } catch (java.XMLOutputter. outputter. System. x++){ val = new Attribute ("value". public class ws2 { public static void main(String[] args) { // Write a program that creates a document.For our next worksheet project. } } } Page 12 . root.setAttribute(val).io. Element el = null. el = new Element("number"). the task is to create a document. // and adds child elements to the root element by // looping from 0 to 9.

and the XML is displayed: root. Document doc = new Document(root. You do this by using one of three namespace-aware constructers: The first two involve only strings passed to the constructor: Element el = new Element("el". } } } Page 13 . "www. "www. outputter.addContent(el).com").IOException e) { e. "www.Element Namespaces It is possible to create JDOM elements that use a namespace.*. System. true).rubyxml. } catch (java. Let’s modify the code from example2 to see the difference between the two: import org. and Element el = new Element("el". in addition to the element name and namespace URI: Element el2 = new Element("el2". The first element will be created by passing the element name. and the URI of the namespace it belongs to: Element el = new Element("el".io. import org. dt).output. "jgb".jdom.com").output(doc.com").rubyxml. DocType dt = new DocType("myRootElement"). "jgb".rubyxml.jdom. root.printStackTrace().addContent(el2). The elements are then added to the document. try{ XMLOutputter outputter = new XMLOutputter(" ".XMLOutputter.com"). public class example2b { public static void main(String[] args) { Element root = new Element("myRootElement"). The second element will include the namespace prefix.setText("This is a root element"). root.rubyxml. "www.out).

com" /> <jgb:el2 xmlns:jgb="www.rubyxml.0" encoding="UTF-8"?> <!DOCTYPE myRootElement> <myRootElement> This is a root element <el xmlns="www.rubyxml.com" /> </myRootElement> Page 14 .Compiling and running this code produces: <?xml version="1.

root. } } } The results should be: Page 15 . dt).The JDOM Namespace Class The third way to create and element with a namespace is to use a Namespace class. } catch (java.printStackTrace(). Element el2 = new Element("el2".io. Element el = new Element("el". root. "www.addContent(el2). nsURI). Now add the Elements and display the XML: root. The new Namespace instance can be used to store and retrieve namespace attributes.setText("This is a root element").output. Document doc = new Document(root. "www.jdom.rubyxml.jamesbritt. This is a static class that can be sued a namespace factory. Now use that same Namespace object to supply a URI.rubyxml. "www.com"). root. outputter. ns). Element el4 = new Element("el4". root.*.getURI().IOException e){ e.addContent(el3).com").XMLOutputter.out). DocType dt = new DocType("myRootElement").addContent(el). such as the URI or the prefix: import org. try{ XMLOutputter outputter = new XMLOutputter(" ". "jgb". public class example2c { public static void main(String[] args) { Element root = new Element("myRootElement").jdom. import org. Use the Namespace to cerate a new Element: Element el3 = new Element("el3".output(doc.com").addContent(el4). System. Create a Namespace object … Namespace ns = Namespace.getNamespace("james". for another Element: String nsURI = ns. true).

com" /> <el4 xmlns="www.rubyxml.com" /> <james:el3 xmlns:james="www.<?xml version="1.rubyxml.com" /> <jgb:el2 xmlns:jgb="www.jamesbritt.0" encoding="UTF-8"?> <!DOCTYPE myRootElement> <myRootElement> This is a root element <el xmlns="www.com" /> </myRootElement> Page 16 .jamesbritt.

the same technique is used for adding a PI to an Element: Element el= new Element("example").addContent(pi). The JavaDocs say that you should use getContent and add PIs manually. bar=’ain’t it cool” is a perfectly valid piece of PI data. Although the data is simply a string.e.put("number:" + x. some applications. The format of a PI is very basic: there is a target. or processing instruction. but you do have to take care to properly quote you data string. This would create a PI like this: <?sniggle number:2="2!" number:1="1!" number:0="0!" number:3="3!"?> We’ve seen how to add a PI to a Document. the Document object provides a setContent method that takes a ProcessingInstruction argument doc. el. this is “deprecated” (i. though the external application that hopes to parse the PI may have some issues. hash). removed) in beta version 7. JDOM offers another constructor that accepts a Map object as the second parameter. x++){ hash. look at PIs as ersatz elements.) To make adding name/value pairs as PI data easier. x + "!"). PI Creating a PI. there are other XML node types that often come in handy. pi = new ProcessingInstruction("target". Actually. such as Cocoon.addContent(pi). as quite like creating an attribute: ProcessingInstruction “someData”). for(int x = 0. so you’ll need to instantiate a subclass. and there is some arbitrary data for that target. x < 4. } pi = new ProcessingInstruction("sniggle". Earlier versions of JDOM allowed the use of Document::addProcessingInstruction. and format the PI data as if it were an attribute: <?foo bar=”blug” ?> Creating such a PI is not especially hard. such as a Hashtable: Hashtable hash = new Hashtable(). Comment Creating a comment is also pretty much what you might expect: Page 17 . Actually. (Note that the quoting syntax is not significant according to W3C XML recommendations.Adding other nodes types Aside from elements and attributes. Map is a Java interface.

And the method for adding a comment to a document is the same as for adding a PI: doc. Page 18 .addContent(com).Comment com = new Comment("Docs need more comments!").

We’ve already seen how to use an XMLOutputter object to print the results of our example classes.) Solution 3: import import import import org. Document doc) { try{ FileOutputStream out = new FileOutputStream(fname).util.println(e).flush(). We can add this ability to our example code by creating a simple method: private static void writeToFile(String fname. we can use this same approach to write the XML to a file.*. and calls the XMLOutputter output method to write the XML to the file. Finally.outputString(doc).out. and write the document' s XML to a text file. out).jdom.*. java. java. } } This method takes two parameters: the name of the file to write to.err. It creates an output stream using the file name. XMLOutputter op = new XMLOutputter(" ". and a JDOM Document object. } catch (IOException e){ System. you may want to simply assign the XML to a String. We can do that by calling the XMLOutputter’s outputString method: XMLOutputter op = new XMLOutputter(" ". org. // Write a program that creates document with a Page 19 . op. true). allow the user to specify the file name on the command line. (For bonus points.io.XMLOutputter. out.Saving your JDOM Having gone through all this trouble to create a JDOM document. Add a comment to the root element. your task now is to write a program that creates a document with a single root element.jdom.*.output.output(doc.close(). out. Worksheet 3 To review what we’ve recently covers. write the String to System. String myXml = op. and assign the document’s XML to a local string. true). Getting the Document as a String Depending on what you want to do with the Document you’ve created. we’ll want to have some way to save it.

Element root = new Element("simple"). } } } Page 20 . For bonus points. Document doc) { try { FileOutputStream out = new FileOutputStream(fname).xml". true).flush().out. out).outputString(doc). System.length > 0) filename = args[0]. XMLOutputter outputter = new XMLOutputter(" ". true). doc). writeToFile(filename.err. allow the user to specify the file name on the command line. out.close(). Document doc = new Document(root). } catch (IOException e) { System. root. out. and assign the document’s XML to a local string.out. serializer. public class ws3 { public static void main(String[] args) { String filename = "default. Add a comment to the root element.output(doc.println(e). Comment cmt = new Comment("A bare document!"). String xml = outputter. XMLOutputter serializer = new XMLOutputter(" ". } private static void writeToFile(String fname.println(xml). if(args. write the String to System.addContent(cmt). and write the document to a text file. Finally.// // // // // // single root element.

DocType type = new DocType("rootBeer". adding a DOCTYPE to a document is straightforward: Element root = new Element("rootBeer").setAttribute(attrBar).setText("Look at me. "Scottsdale").jdom.XMLOutputter. out). DocType type = new DocType("rootBeer". try{ XMLOutputter outputter = new XMLOutputter(" ". and under what conditions.xml"). FileOutputStream out = new FileOutputStream("rootBeer.io. "20011021").jdom.").close().setAttribute(attrFoo). root. } catch (java. outputter. Element bar = new Element("Bar"). type). outputter. You may want your document to have a doctype.setText("Look at me.More complex document construction: DOCTYPEs and DTDs. Attribute attrFoo = new Attribute("date". public class example3a { public static void main(String[] args) { Element root = new Element("rootBeer").addContent(bar). import import import import org.out).flush(). foo. true). specifying (among other things) what elements and attributes may appear in the document. Document doc = new Document(root.IOException e){ Page 21 .output. foo. Element foo = new Element("Foo"). out.output(doc. foo.dtd"). root. Document doc = new Document(root.").output(doc.*. "rootBeer. "rootBeer. org.dtd").*. The doctype is a declaration appearing at the head of an XML document. Attribute attrBar = new Attribute("city". java.addContent(foo). As we briefly saw earlier. type). We can revisit some earlier code to see what XML this produces.*. out. System.io. bar.util. java.

</Foo> <Bar>Look at me.e.</Bar> </rootBeer> Page 22 .0" encoding="UTF-8"?> <!DOCTYPE rootBeer SYSTEM "rootBeer.printStackTrace().dtd"> <rootBeer> <Foo date="20011021" city="Scottsdale">Look at me. } } } Running the compiled code will give us this XML: <?xml version="1.

JDOM itself does no validation.println("Error loading XML: " + e. } catch (org. Let’s see how this works.input. To validate a document you need to use the facilities provided by an underlying SAX or DOM parser.input.JDOMException e){ System.xml.jdom. trying to create a JDOM document with a validation SAX parser should throw an error.build("myFile.JDOMException e){ // The DTD parsing failed } The first thing to notice is that we’re creating a Document by running a source XML file through a SAXBuilder object.getMessage() ). The previous code created a file named rootBeer. that’s easy enough to test: import org.jdom.xml").SAXBuilder(true).println("XML loaded fine!"). Well. We’ll discuss the details of SAXBuilder in the next section.SAXBuilder(true). In fact. Since we don’t actually have the doctype file.input. There is a SAXBuilder constructor that takes a boolean parameter indicating if validation should occur.*. System. and b) the underlying parser is what does the actual validation.dtd file.jdom. using a brief code fragment: org.out. try{ Document foo = builder.jdom. Yet JDOM did not complain.out. The builder is then used to load and parse a file from disk: try{ Document foo = builder.jdom.SAXBuilder builder = new org.xml").jdom. public class saxValidate { public static void main(String[] args) { org.jdom.JDOM and XML Validation You may have noticed that we never created any rootBeer. The reason is that JDOM does not validate the XML as it is constructed. which included a DOCTYPE declaration. but for now you just need to know that a) it uses a SAX parser. } } } Running this code after compilation produces this: C:\dev\topxml\jdom\testcode>java saxValidate Error loading XML: Error on line 2 of document file:/C:/dev/topxml/jdom/testcode/rootBeer. } catch (org.build("rootBeer.SAXBuilder builder = new org.xml: Page 23 .

Page 24 .dtd".External entity not found: "file:/C:/dev/topxml/jdom/testcode/rootBeer.

Worksheet 4 JDOM does not validate in-memory documents. an acceptable DTD would be: <!ELEMENT <!ELEMENT <!ELEMENT <!ATTLIST <!ATTLIST rootBeer (Foo. "Blug" is not allowed. Page 25 . previously described).Validation Errors Let’s take this further and create the missing DTD.0" encoding="UTF-8"?> <!DOCTYPE rootBeer SYSTEM "rootBeer.xml: Element "rootBeer" allows no further input. in the same directory as XML file and java program.0" encoding="UTF-8"?> <!DOCTYPE rootBeer SYSTEM "rootBeer.dtd"> <rootBeer> <Foo date="20011021" city="Scottsdale">Look at me. and add content to the Document.</Bar> </rootBeer> So. For this task.dtd"> <rootBeer> <Foo date="20011021" city="Scottsdale">Look at me.</Foo> <Bar>Look at me.dtd.</Foo> <Bar>Look at me. In other words.</Bar> <Blug>This is wrong</Blug> </rootBeer> We get this error message: C:\dev\topxml\jdom\testcode>java saxValidate Error loading XML: Error on line 6 of document file:/C:/dev/topxml/jdom/testcode/rootBeer. Create a JDOM Document. Suppose we add a new child element below rootBeer: <?xml version="1. we should see this when we run the code: C:\dev\topxml\jdom\testcode>java saxValidate XML loaded fine! We can see the validation in process by selectively breaking parts of our XML document. your only chance to validate a document is when you first load it. create a DocType that refers to the rootBeer DTD (rootBeer. add the DocType. Bar) > Foo (#PCDATA) > Bar (#PCDATA) > Foo date CDATA #REQUIRED > Foo city CDATA #IMPLIED > If we put this into a file named rootBeer. Which is what we should expect. Here’s what our XML looks like: <?xml version="1.dtd.

addContent(foo).input. validateDocument(doc). return true.addContent(bar).outputString(jdoc).jdom.JDOMException e){ System. root.build( sr ).jdom.StringReader object to convert an XML string into a character stream. System. Note: One approach might be to save the XML to a temporary disk file. import org.output.Re-parse the JDOM XML using the earlier SaxValidate code to see if the XML you created adheres to the given DOCTYPE. } catch (org. "rootBeer. then read into the Another approach is to use a java.setDocType(dt).SAXBuilder builder = new org. Display either an "OK" message. root. XMLOutputter outputter = new XMLOutputter().out.println("Error loading XML: " + Page 26 . Document doc = new Document(root).input. StringReader sr = new StringReader(xmlString).dtd"). import java.io.*.StringReader.XMLOutputter. then re-parse the XML using SAX validation to verify that the XML is valid. try{ Document testDoc = builder. "2002-01-01").jdom. doc. public class ws4 { public static void main(String[] args) { Element root = new Element("rootBeer"). DocType dt = new DocType("rootBeer". Element bar = new Element("Bar"). or any errors. Solution 4: // // // // Create a JDOM. StringReader sr = new StringReader(xml).jdom. import org.io. Add content to the JDOM.SAXBuilder(true). Element foo = new Element("Foo"). with a DocType pointing to an external DTD. } private static boolean validateDocument(Document jdoc) { org.jdom.out. foo.setAttribute("date".println("XML loaded fine!"). suitable for passing to a SAXBuilder’s build method: SAXBuilder. String xml = outputter.

getMessage() ). return false.e. } } } Page 27 .

jdom.xml". Page 28 . java.println( e. The new code looks like this: import import import import org. The JDOM installation includes a SAX parser. Creating a DOM from a file We’ve seen the basics of creating a JDOM Document from scratch. As the name suggests. which is the one we’ll use. where an XML document is viewed as a node tree (or a directed graph.output. } try{ Document doc = readFromFile(filename).jdom.toString() ). System.outputString(doc). If you choose to use the default constructor then JDOM will not attempt to validate the XML input. We start with the org.input.out. if(args.XMLOutputter. String xml = outputter. } catch(Exception e){ System.” A SAX parser hooks code to these events.length > 0){ filename = args[0]. if you prefer). There is a SAXBuilder constructor allows you to specify a particular SAX parser. We can now modify the file from worksheet 3 so that.SAXBuilder. Now let’s see about doing the reverse: taking an existing XML source and creating a JDOM Document. such as “Start of Document”.println(xml). JDOM and SAX may be used in two ways: To create a new JDOM Document from a SAX parser.jdom. instead of writing a file. public class example4 { public static void main(String[] args) { String filename = "default. } } private static Document readFromFile(String fname) throws JDOMException { SAXBuilder sxb = new SAXBuilder(). and getting the XML.io. or you can use the no-argument constructor and have JDOM locate a default. and to use a JDOM Document as an XML source to drive a SAX parser. In contrast to the DOM.*. org. This class will allow us to get a Document object by reading in a source file. false). which provides a class named SAXBuilder. it reads one. SAX looks at an XML document as a series of events.Integration with SAX SAX (simple API for XML) is an event-driven approach to XML processing.input package. or “Start of Element.out. org.jdom.*. a SAX parser is involved someplace. XMLOutputter outputter = new XMLOutputter(" ".

0" encoding="UTF-8"?> <simple> <!--This is a bare document!--> </simple> Page 29 . } } If you compile the code and run it from the command line it should find the sample XML file previously created you should see the contents of "default.build(new File(fname)).xml" written to the screen: E:\dev\topxml\jdom\testcode>java example4 <?xml version="1.return sxb.

you want to see those SAX events. All of that was hidden by the call to SAXBuilder.xml.sax. However. a SAX parser will send a notification whenever it encounters the start of an element. processing a series of records from a database. In our next example. But often the XML and the work to be done. For example. There are times when you need to process a large XML file. the SAX itself does not then do anything. Even if you have sufficient system resources. SAX parsers work by raising events when different parts of an XML stream are encountered. say. For example. from text file to Document object. it depends on task-specific code to carry on. though. From our point of view it was single event. The key to SAX parsing is the code that responds to the various SAX events. we will look at using SAX events to transform a repetitive XML source document into a more concise XML document. The org. Page 30 . The SAX specification defines some Java interfaces for classes that perform the work in response to an event notification. sending SAX event notifications to a “registered” ContentHandler class. This can be a problem if the XML is. several megabytes in size.ContentHandler interface defines a set of methods corresponding to SAX content notifications. “Registered” simply means the ContentHandler class was passed to the SAXOutputter constructor.build. Typical DOM parsers work by loading the entire XML document into memory before you can use it. Sometimes. JDOM provides SAXOutputter class that knows how to parse a JDOMN Document. Now.Firing SAX events from JDOM Our previous example used a SAX parser to create a document. there are of course cases where the task to be done really does require the entire document in memory. is highly repetitive. However. your application must wait until the entire document is loaded.

int length){ sop("ignorableWhitespace!"). String localName. a class implementing org. } // Receive notification of the end of an element.Attributes. Creating a class that implements org.sax. public void processingInstruction(String target. public class DocHandler implements org.ContentHandler looks like this: // File DocHandler. 3.xml.xml. } // Receive notification of a processing instruction.Responding to SAX Events Using SAX events with JDOM requires: 1.xml. import org. } // End the scope of a prefix-URI mapping. } // Receive notification of the end of a document. but added to reduce typing :) private void sop(String msg){ System. int length){ sop("characters!"). } // Receive notification of ignorable whitespace // in element content. public void endElement(String namespaceURI.sax. 2. public void characters(char[] ch.println("DocHandler: " + msg). String qName){ sop("endElement!").xml. public void ignorableWhitespace(char[] ch. } // Receive an object for locating the origin of Page 31 .Locator.out.java import org.ContentHandler { // Not part of interface. public void endPrefixMapping(String prefix){ sop("endPrefixMapping!"). public void endDocument(){ sop("endDocument!").sax. int start. } // Receive notification of character data.xml. String data){ sop("processingInstruction!").sax.ContentHandler Instantiating a SAXOutputter object (passing in our ContentHandler class) Passing a JDOM Document to the SAXOutputter output method In its simplest form. int start.sax.

ContentHandler { // Just write the methods you need to do the work . a SAX handler class only needs to respond to a handful of events. } } Even without the short inline comments it should be fairly obvious what each of these methods do. You can avoid typing a lot of empty methods.. and create your SAX handler by extending from this class. and extend the code from example 4 to: • Instantiate a ContentHandler object • Instantiate a SAXOutputter object • Output the results of the SAX event by parsing the JDOM Document object. Worksheet 5 Our next worksheet task is to use the DocHandler. The SAX distribution that comes with JDOM includes a class called DefaultHandler that implements empty methods.java file as our ContentHandler class.. } // Receive notification of the beginning of // an element.// SAX document events. when the SAX parser encounters the start or end of some particular XML item.DefaultHandler. } // Receive notification of the beginning of a // document.sax.xml. } // Begin the scope of a prefix-URI Namespace mapping. overriding the specific methods you need: import org. Attributes atts){ sop("startElement!"). public void setDocumentLocator(Locator locator){ sop("setDocumentLocator!").sax. String qName. public void skippedEntity(String name){ sop("skippedEntity!"). String uri){ sop("startPrefixMapping!"). Often. public class MyHandler extends DefaultHandler implements org. String localName.xml. Basically. it calls a corresponding method. public void startDocument(){ sop("startDocument!"). public void startPrefixMapping(String prefix. The example code above is not as unusual as you might think. Page 32 . } // Receive notification of a skipped entity. the other methods must be implemented just to fulfill the implementation requirements. public void startElement(String namespaceURI.helpers.

input. false).jdom.jdom.output. } } private static Document readFromFile(String fname) throws JDOMException { SAXBuilder sxb = new SAXBuilder(). } try{ Document doc = readFromFile(filename). import org.println( e. } } Page 33 .SAXBuilder.out.SAXOutputter. import org. public class ws5 { public static void main(String[] args) { String filename = "default. import java.toString() ).out.length > 0){ filename = args[0].println(xml). return sxb. SAXOutputter saxo = new SAXOutputter(dh). System. XMLOutputter outputter = new XMLOutputter(" ". import org.jdom. import org. if(args.*. DocHandler dh = new DocHandler().outputString(doc).output.build(new File(fname)). // extend the code from example 4 to: // * Instantiate a ContentHandler object // * Instantiate a SAXOutputter object // * Output the results of the SAX event by // parsing the JDOM Document object.output(doc). saxo.*.XMLOutputter. String xml = outputter.java file just described. } catch(Exception e){ System.io.xml".jdom.Solution 5: // Using the DocHandler.

ContentHandler { private StringBuffer sb = new StringBuffer(). A list of attributes attached to the element. public class AttrToElFormatter extends DefaultHandler implements org. } public void endElement(String namespaceURI. and convert each element’s attributes into child elements. Our sample code will perform a simple task: read in an XML document. } public void characters(char[] ch. it receives the following information: • • • • A namespace URI. If no namespace processing is available then this will be an empty string.Example: Transforming XML using SAX Events DocHandler class does pretty much nothing. Page 34 . the attributes will be converted into child elements. However. Our code will build the new XML string by appending text to a StringBuffer object. If there is namespace processing. public String getXML() { return sb.xml.xml.append(ch). In order to correctly reconstruct each element as it arrives. String localName. When this method is called.sax. then this string will be empty. so we need to add code to do something useful with the data available from the SAX calls. if the SAX parser supports namespace processing. the code must examine the parameters and see what values are present. int start. All of it will be collected and used to construct a new XML document. Most of the work will happen in the startElement method.sax. The local name of the element. when the parser signals the start of an element. } public void startElement(String namespaceURI.sax. The AttrToElFormatter class will grab the XML data presented by the SAX parser.append("</" + qName + ">").toString() . int length) { sb. Otherwise this will be empty.xml. if there is namespace processing. The qualified name. if no namespace processing is available.Attributes.DefaultHandler. import org. String qName) { sb. String localName.helpers. import org.

getQName(x) + ">" + attrs. AttrToElFormatter a2e = new AttrToElFormatter(). SAXOutputter saxo = new SAXOutputter(a2e). Attributes attrs = atts. saxo.String qName.getLength(). } try{ Document doc = readFromFile(filename). System.*.out. if(args.getValue(x) + "</" + attrs.outputString(doc).append("<" + attrs.jdom.*. } } private static Document readFromFile(String fname) throws JDOMException { SAXBuilder sxb = new SAXBuilder(). public class ws5a { public static void main(String[] args) { String filename = "default.SAXBuilder. x++){ sb.build(new File(fname)).getQName(x) + ">\n"). String xml = outputter.toString() ). } } } } Calling the transformer import import import import import org. org.output(doc). false). if(attrs != null){ for(int x = 0.SAXOutputter.out.xml".input.length > 0){ filename = args[0].println(xml). org.io. System. java. return sxb. Attributes atts) { sb.append("<" + qName + ">\n"). XMLOutputter outputter = new XMLOutputter(" ".XMLOutputter. x < attrs.jdom.println( e.jdom. } catch(Exception e) System. org.getXML() ).out.jdom.println("New XML = \n" + a2e. } } Page 35 .output.output.

processing instructions. The DOM was a step forward as it defined a common model for all developers to target.getDocument().sax. Building a JDOM object from a W3C DOMDocument Shortly after the W3C made XML official. and the code then uses it to create the DOM object: DOMParser parser = new DOMParser(). which supplies the initial DOM object The code begins with the main method declaring a w3cdom.Document to hold our initial XML. public class W3DomTest { public static void main(String[] args) { org. JDOM provides ways to move from one type of DOM to another. } catch(Exception e){ Page 36 . as well as the Xerces package.xerces. and so on. } A parser object is created. The code will use first command line argument as the file name.DOMParser. org.jdom. org.DOMBuilder. org. they set about to define a way to manipulate XML documents.parse(new InputSource(xmlFile)).IOException.length == 1){ xmlFile = args[0]. In a nutshell.output.jdom. you may find yourself having to work with W3C DOM implementations.Document domDoc = null. as you’ll see. They came up with the XML DOM Level 1 specification. org. and get back a JDOM Document. and a great deal of software has been written that targets the W3C DOM interface. you may find a need to interact with W3C DOM objects.apache.io. We need to import the usual JDOM packages for in out and output.Integrating JDOM with a W3C DOM JDOM provides an API intended to be more natural to Java developers than the W3C XML DOM API. and a default file name where the XML can be found. org.dom.jdom. A node was basically any of the “tangible” XML parts. String xmlFile = "rootBeer. JDOM makes the conversion from DOMDocument to JDOM a snap. most of the code is busy creating the initial DOM import import import import import import java. although you may have elected to work with JDOM. if one is given: if(args.w3c.parsers. elements.JDOMException.xml".xml. JDOM allows us to pass a W3C DOM object to a JDOM builder. So. domDoc = parser. The following examples will show this. defining an interface for manipulating a tree of nodes.InputSource. However. try{ parser.input.XMLOutputter. attributes.

jdom.IOException.io.) If all went well.printStackTrace().io.out). org. } catch ( java.xml.build(domDoc). or an org. } } } DOMBuilder. Page 37 . XMLOutputter outputter = new XMLOutputter(). } (The try block might throw either a java.printStackTrace(). outputter.output(jdomDoc. from the parser.e. the code uses the new DOM to initialize a JDOM object by passing it to a The new JDOM is then written to the console: try{ DOMBuilder builder = new DOMBuilder().Document jdomDoc = builder.IOException e){ e. due to the InputSource.SAXException. System.sax.

org.output(doc).dom. At this point we want to take our JDOM doc and convert it into a W3C DOMDocument.jdom.out.jdom. String xml = xmlOutputter. is that we will now have two classes called Document. System.output. though. Page 38 .w3c.Outputting a JDOM object to a W3C DOMDocument Converting a JDOM to W3C DOM is quite simple. XMLOutputter xmlOutputter = new XMLOutputter(" ".*. The code instantiates a DOMOutputter object to do the work: DOMOutputter domOutputter = new DOMOutputter().output.io.println(xml). Note that the declaration of the JDOM Document and W3C Document variables use fully qualified package names: org. org. org.println( e. One thing to keep in mind.jdom.jdom.jdom.xml".input.JDOMException.Document dom = null. org.toString() ).outputString(doc).SAXBuilder.Document doc = null.XMLOutputter. SAXBuilder.length > 0){ filename = args[0]. false). } } private static org. } try{ doc = readFromFile(filename). java.Document readFromFile(String fname) throws JDOMException { SAXBuilder sxb = new SAXBuilder(). which returns a W3C DOMDocument: dom = domOutputter. public class example5 { public static void main(String[] args) { String filename = "default. so our code must use qualified class names to prevent ambiguity. if(args. we can use a JDOM outputter class to do all of the work. The JDOM doc is then passed to the DOMOutputter.out. Let’s revisit some code we used to create a JDOM Document by reading a file through a This code now takes that JDOM and converts it to a W3C DOMDocument: import import import import import org. } catch(Exception e){ System.DOMOutputter.jdom.

JDOM provides adapter classes for the most popular Java DOM parsers in use.return sxb. the choice of adapter may be important. most implementations add one out of practical necessity.build(new File(fname)). so the code apparently has given us a DOMDocument. However. Now what? With JDOM we could easily see what XML the document held. This tells the DOMOutputter to use a specific DOMAdapter. but with a DOMDocument it’s a bit different: the W3C specification made no provision for actually getting the XML from a DOMDocument. So what are our options? While the W3C DOM specification does not define a method for simply retrieving the complete XML from a DOM. the name of that method may vary among different W3C DOM implementations. Depending on what you plan to do with the DOMDocument after conversion. The DOMOutputter class provides a constructor that allows us to pass the name of a DOM adapterClass. If you omit the name of the adapterClass then JDOM will locate a default W3C DOM implementation using JAXP Page 39 . } } OK. rather than the JDOM default.

jdom. The getCause method allows us to pass through information about any previous exception. We’ll use a simple program that just tries to read in an XML file: import import import import org. We’ve seen some code that lets us read an XML file from disk and turn it into a JDOM. Throwable cause) { super("Error loading XML: " + msg. if(args.JDOM Exception Handling As you may have noticed from the various code examples.out. Along with the standard getMessage and printStackTrace methods. First.jdom. } try{ doc = readFromFile(filename). org. JDOM includes a JDOMException class. This can be used to pass through the root cause of the load error. String xml = outputter. the exception. org.Document doc = null. and then throwing it in some sample code.jdom.io. } } Quite spare. there is also a getCause method.input. System. It can be subclassed to define more specific exceptions. public class LoadException extends JDOMException { public LoadException (String msg.jdom.jdom. of which the subclass is a special type.length > 0){ filename = args[0]. false).output.XMLOutputter. cause). XMLOutputter outputter = new XMLOutputter(" ".outputString(doc). We’ll create an exception for when any JDOMExceptions are thrown during file loading: import org. We can see how this works by creating our own JDOMException subclass. public class Example6 { public static void main(String[] args) { String filename = "bad. java.*. it provides methods for passing along error messages. The JavaDocs for the JDOMException say that the class is a top-level exception. } Page 40 . The class is fairly sparse. org. Notice that the constructor includes a parameter for another exception.SAXBuilder.*.xml".println(xml). Now we need some code to throw the exception.JDOMException.

out.toString() ).getCause() ). System. System.out.out.println( "\n****JDOM Exception *********" ). System. } If the call to readFromFile throws a LoadException. } Page 41 .println( "getMessage(): " + jde.println( "\n***********************" ).getMessage() ).println( e. the difference from previous code examples is that we’ll now try to catch our custom exception: catch(LoadException lde){ printJdomException(lde). will print out the different exception messages. System.out.out. as we’ll see in a moment. we want to catch it and pass it to another method that.out.println( "toString: " + jde.So far nothing too remarkable.println( "getCause() " + jde. } } We have a small method that just takes a JDOMException and writes out error information in different ways so we can see the difference: private static void printJdomException(JDOMException jde) { System.toString() ). If we get any other type of exception we’ll just emit the string: catch(Exception e){ System.

getMessage(): Error loading XML: Error reading from file. In that case. When we compile and run example6. ************************************ So. we should see something like this: ************JDOM Exception ********* toString: LoadException: Error loading XML: Error reading from file.". the code will catch the exception and use it construct a LoadException. return sxb.xml: <?xml version="1. The error text from the JDOMException has been appended to this text.xml: Expected "</foo>" to terminate element starting on line 4.: Error on line 5 of document file:/E:/dev/topxml/jdom/testcode/bad.: Error on line 5 of document file:/E:/dev/topxml/jdom/testcode/bad. getCause() org. which is then thrown in its place: private static Document readFromFile(String fname) throws LoadException { try{ SAXBuilder sxb = new SAXBuilder().jdom. } catch(JDOMException jde){ throw new LoadException("Error reading file. toString and getMessage showed us the error message passed in when the LoadException was created. The SAXBuilder class may throw a JDOMException if there is a problem with the XML. } } } After compiling the two classes. Page 42 .xml: Expected "</foo>" to terminate element starting on line 4. so this should cause an exception.Throwing a Custom JDOM Exception Finally.xml: Expected "</foo>" to terminate element starting on line 4.JDOMException: Error on line 5 of document file:/E:/dev/topxml/jdom/testcode/bad.0" encoding="UTF-8"?> <x> <!--This is a bare document!--> <foo>Hello!<foo> </x> The foo element isn’t properly closed. suppose we have this XML in bad.build(new File(fname)). jde). we have the method that reads the XML from a file. we can trigger an exception by having the program try to load some faulty XML. For example.

on the other hand. omits any information about the LoadException. Page 43 .getCause. and only gives the error text for the root JDOMException.

addContent("--"). Page 44 . el. if you try (for whatever reason) to add an element to itself. then a DataConversionException will be thrown. If you call this method. = new Comment("My comment text"). // Throws exception. However. since double-hypen is not allowed IllegalNameException As you might guess. For example.addContent("This is the text"). For example.addContent(el). Comm. For example. the code will throw an IllegalAddException exception. The same emthoid (though with a different implementation) allows you to add one element as a child element of another: Element newEl = new Element("myNewEl"). // Throws exception: el.. while you can add almost anything as the content of a Comment. el. the IllegalDataException exception is thrown: Comment comm. For example. the Attribute class provides a getIntValue method that returns the value of an Attribute as an integer (i. some strings are disallowed. XML elements may not begin with a numeral. For example. there are cases where an addition violates some fundamental rule of JDOM structure. and trying to create an element named "2bad4U" will throw an exception. type int). In these cases.jdom package includes some additional exceptions that derive from JDOMException. They are thrown in response to failures to perform particular DOM actions. but the attribute value does not have an integer representation.Additional JDOM Exceptions The com. IllegalTargetException Similar to the IllegalNameException. DataConversionException This exception is thrown when code attempts to convert some XML into a particular form. to add character data to an Element. IllegalDataException Not all forms of data are appropriate in all cases. an IllegalNameException is thrown if you try to name something in violation of XML naming rules.addContent(newEl). IllegalAddException Various JDOM objects implement an addContent method. the IllegalTargetException is thrown when an invalid name is applied to a processing instruction.e. you might use code like this: Element el = new Element("myEl").

which allows the code to pipe the XSLT file into the Transformer object. The JAXP classes are part of the javax. of course.xml packages. the JDOM installation includes Xalan. use a different XSLT engine. Document docResults = null.*.*. The code will need a TransformerFactory to get a reference to an XSLT engine import javax. the examples here will use Xalan. The first thing to know is that JDOM itself does not do any XSLT processing.transform package provides us with JDOMResult and JDOMSource objects. import javax.xml".*. Let’s first look at some sample code. the code will use some defaults. You can.xml.*. which are conduits for the JDOM we pass to and from the transformer objects. org.transform. xslFile = args[1]. but the general approach is the same for other processors. and see just what needs to happen. The jdom.xml.XSL Transformations In this section we’ll learn how to using XSLT with JDOM to transform XML.*.transform. JDOM ships with some sample code. so we’ll use the catalog XML and XSLT files for this example. If the arguments are missing.input. org.transform. The program will read the command line arguments for the names of an XML and an XSL file. The code will also need a StreamSource object. } The code uses a SAXBuilder to read in the XML file and create a JDOM document. Document docXml = builder.xsl".jdom.stream.jdom. Instead. org.build(xmlFile). Page 45 . String xslFile. public class Xsltex{ public static void main(String[] args) throws Exception { String xmlFile. } catch(Exception e){ xmlFile = "catalog. xslFile = "catalog. and Xalan will quite happily do XSLT. As it happens. try{ xmlFile = args[0]. SAXBuilder builder = new SAXBuilder().output. JDOM may be used to feed a DOM Document or SAX stream to a third-party XSLT processor.jdom. import import import import org.jdom.*.

the name of the XSLT file is passed to a StreamSource constructor: try{ StreamSource strmSrc = new StreamSource(xslFile). JDOMSource jdSrc = new JDOMSource(docXml).xml.transform. the results are placed in the JDOMResults object passed to the method.sax.SAXResult. JDOMSource extends SAXSource and allows the transformer object to receive the JDOM Document as a series of SAX events. It allows the code to get the results of an XSLT transformation as a JDOM Document. The transform method expects to receive a javax. Once transform is called. Other types of sources are SAXSource and DOMSource.output(docResults. } ". transformer.transform(jdSrc. and a JDOMResult object to hold the transformed XML. the code instantiates a TrasformerFactory object. First. The role of the JDOMSource object is to make the bridge from a JDOM Document to a Source object. so the code uses the TransformerFactory to create a Transformer based on the StreamSource just created: Transformer transformer = tFact.xml. Next. JDOMResult extends javax.transform. Now the code is about ready to actually transform our XML.xml. Whew! Almost there. The JAXP API JavaDocs say that a StreamSource “[a]cts as [a] holder for a transformation Source in the form of a stream of XML markup. Let’s look a little closer at what’s happening here. out.Result object. System. Each of these act as XML input sources.newTransformer(strmSrc).setTextNormalize(true).newInstance().getDocument().transform. Now the code can emit the new XML using an XMLOutputter: XMLOutputter out = new XMLOutputter(" out. To actually get the resulting JDOM Document we just need to call getDocument: docResults = jdRes. These are then passed to the Transformer’s transform method: JDOMResult jdRes = new JDOMResult(). TransformerFactory tFact = TransformerFactory. This is an abstract class that may be used to create Transformer and Templates objects.transform. true). The code creates a JDOMSource using XML JDOM Document.” It is an implementation of the javax.Source interface. jdRes ).xml. It is the Transformer that will be doing the real work.out). Specifically. Page 46 .Creating an XSLT Transformer The code then goes through a series of steps to create a Transformer object.Source object and a javax. Similarly.

xpath. thrown when the actual transformation occurs. as does xalan.toString() ).lang. For example.out.NoSuchMethodError. Page 47 .catch(Exception e){ System. If you have the J2EE SDK installed then your program may be finding an older version of some required classes. To resolve these.println("Error: " + e.apache. make sure that you have your CLASSPATH set so that the jar files with the XSLT and XML processors you want to use are at the start of the path. A common exception is java. } } } Note: When you try to run this.jar. you may get various exceptions from one of the underlying transformer classes.jar archive contains org. or similar code.patterns. the j2ee.

For example. and content using the JDOM API. as well as how to load existing XML into a document. It went on to show how JDOM could interact with SAX parsers and W3C DOM documents. JDOM exceptions were covered. adding elements. It covered the fundamentals of creating a JDOM document from scratch. attributes. and how to install and configure it. However. as well as XSL transformations. Page 48 . what has been covered here will serve as a strong foundation to continue learning the ins and outs of JDOM. It also showed how to get the XML from a JDOM document. a JDOM Attribute has over fifteen public methods. There is more to JDOM than this tutorial could hope to properly cover.Summary This tutorial has shown where to obtain JDOM.

oreilly.jdom. JavaWorld (http://www.html) O’Reilly Book Excerpts: Java and XSLT Chapter 5: XSLT Processing with Java (http://www.JDOM Resources • • • • The JDOM home page. http://www.com/developerworks/library/j-jdom/) Page 49 .com/javaworld/jw-05-2000/jw-0518-jdom.javaworld.ibm. IBM developerWorks (http://www106.org/ Easy Java/XML integration with JDOM.html) Simplify XML programming with JDOM.com/catalog/javaxslt/chapter/ch05.

Sign up to vote on this title
UsefulNot useful