News and Status


Get Involved
  Mailing Lists
  Search JDOM Lists

  Who We Are

Serbo-Croatian by Jovana Milutinovich from
French by Nicolas Chevallier.

What is JDOM?

JDOM is, quite simply, a Java representation of an XML document. JDOM provides a way to represent that document for easy and efficient reading, manipulation, and writing. It has a straightforward API, is a lightweight and fast, and is optimized for the Java programmer. It's an alternative to DOM and SAX, although it integrates well with both DOM and SAX.

What is JDOM not?

JDOM is not a wrapper for the W3C's DOM, or another version of DOM. JDOM is a Java-based "document object model" for XML files. JDOM serves the same purpose as DOM, but is easier to use.

JDOM is not an XML parser, like Xerces or Crimson. It is a document object model that uses XML parsers to build documents. JDOM's SAXBuilder class for example uses the SAX events generated by an XML parser to build a JDOM tree. The default XML parser used by JDOM is the JAXP-selected parser, but JDOM can use nearly any parser.

Is JDOM an acronym?

Nope. Just like JDBC is not officially an acronym, neither is JDOM. This ensures we comply with Sun's trademark policies as explained at

What is the JDOM license?

JDOM is available under an Apache-style open source license, with the acknowledgment clause removed. This license is among the least restrictive license available, enabling developers to use JDOM in creating new products without requiring them to release their own products as open source. This is the license model used by the Apache Project, which created the Apache server. The license is available at the top of every source file and in LICENSE.txt in the root of the distribution.

Where can I get JDOM?

JDOM is available in binary and source form from

JDOM is also available in maven central in the group 'org.jdom' with the artifact ID jdom for JDOM 1.x (and some earlier 2.x versions): JDOM 1.x Artifacts on maven, or with the artifact ID jdom2 for JDOM 2.x: JDOM 2.x Artifacts on maven

The full source code repository is maintained on GitHub.

Which Maven artifact should I use?

All JDOM versions are available in the 'jdom' or 'jdom2' artifact in the org.jdom group on Maven. The maven artifacts are a mess with early JDOM 2.x versions appearing in the 'jdom' artifacts, and later 2.x versions in the 'jdom2' artifact. Maven does not allow the fixing of mistakes, so maven users wil just have to live with it as it is.

If your project is one that requires both JDOM 1.x and 2.x, then you can also use the 'jdom-legacy' artifact to pull in version 1.1.3 (or later 1.x version).

What is the JDOM Philosophy?

JDOM has been and will continue to be developed with this philosophy:

  • JDOM should be straightforward for Java programmers.
  • JDOM should support easy and efficient document modification.
  • JDOM should hide the complexities of XML wherever possible, while remaining true to the XML specification.
  • JDOM should integrate with DOM and SAX.
  • JDOM should be lightweight and fast.
  • JDOM should solve 80% (or more) of Java/XML problems with 20% (or less) of the effort

Why is the JDOM API defined in terms of concrete classes rather than interfaces?

This issue has been discussed several times on the JDOM mailing list, with several people on both sides. In general, many people feel that a class-based API is better when subclassing is not needed, while an interface-based API is better when subclassing is needed. However, either system can be used in either case.

Jason Hunter summarizes the arguments against an interface-based API for JDOM:

With interfaces everything becomes a factory, elements have to be 'imported' into new documents instead of just added, features like long-term serialization cannot be guaranteed, and the list goes on.

We started with interfaces actually. During our pre-release review to some peers we received the feedback we should try concrete classes. We did, and the design was much better for it.

Think about as an analogy. There's a reason we say:

File parent = new File(filepath);
File child = new File(parent, "aaa.txt");

rather than

FileSystem fs = FileSystem.getDefaultFileSystem();
File parent = fs.getFile(filepath);
File child = fs.getFile(parent, "aaa.txt");

The former is simply easier and nicer to deal with.

Another point to keep in mind is that anything that can be done with interfaces can be done with subclassing - the only penalty is possibly unused variables in the base class.

For reference, the latest mailing list discussion on this topic started Nov. 30, 2000 with "Interfaces", and continued with "Interface-based JDOM" and "Announce: JDOMPlus". It would help to review this discussion before bringing this topic up on the mailing list.

How does JDOM work with DOM and SAX?

JDOM documents can be built from XML files, DOM trees, SAX events, or any other source. JDOM documents can be converted to XML files, DOM trees, SAX events, or any other destination. This ability proves useful, for example, when integrating with a program that expects SAX events. JDOM can parse an XML file, let the programmer easily and efficiently manipulate the document, then fire SAX events to the second program directly - no conversion to a serialized format is necessary.

Was JDOM designed for Generics?

JDOM was designed before Generics, but JDOM 2.x has taken the proven design of JDOM 1.x and extended it to use Generics where possible. Specifically, all Collections-based operations require appropriately typed inputs, and return appropriately typed results. Further, JDOM 2.x takes advantage of other Java 5 features like varargs, and co-variant return types.

Generics: Element.getAttributes() returns List<Attribute>, Element.getChildren() returns List<Element>, etc.

Co-variant Return Types: Element.clone() returns Element, Text.detach() returns Text, etc.

I tried to use JDOM and get an error like this:

java.lang.NoClassDefFoundError: org/xml/sax/SAXNotRecognizedException

What's wrong?

You need to ensure that the xerces.jar file supplied with the JDOM download is in your classpath before any other XML classes, such as those that come with JAXP or Crimson. These other XML libraries, as well as older versions of Apache Xerces, support DOM Level 1 and SAX 1.0, not the required DOM Level 2 and SAX 2.0. The result is an exception being thrown. Check your classpath, and try again. If the classpath looks OK, the problematic JAR might also be hiding in the system's standard extension directory (see the following).

What do you mean "Standard extension directory"?

The standard extension directory is a directory containing JAR files that is searched automatically by the Java runtime and compiler. If you've installed the JDK (not the just the JRE) you may well have two separate ext directories, one of which is used for compiling (typically somewhere like C:\jdk1.3\jre\lib\ext) and the other of which is used for running code (typically somewhere like C:\Program Files\JavaSoft\jre\1.3\lib\ext). The wrong JAR file in either directory can get in your way (though at different times). Furthermore, the right JAR file has to be in both directories.

How do I avoid the DOM Level 1 problem in Visual Age for Java?

When the WTE feature is added to the workspace, the project 'IBM XML Parser for Java' is added as well. This project contains old DOM Level 1 'org.w3c.*' interfaces. JDOM relies on DOM Level 2, and therefore conficts with this project. The solution is to do the following:

  1. Change workspace owner to Administrator
  2. Create open edition of the project 'IBM XML Parser for Java'
  3. Delete all the packages that contain org.w3c.* interfaces
  4. Version the project.
  5. Create a new Project for DOM Level 2 parser such as Xerces
  6. Import all Xerces classes including org.w3c.* interfaces (you can use a completly different project for those interfaces if you want to work with other parsers)
  7. Version the Xerces project
  8. Create a JDOM project and import jdom classes into it. Version the project

(Contributed by Guy Nirpaz)

How do I avoid the DOM Level 1 problem in WebSphere?

WebSphere has the same issue with DOM Level 1 interfaces as VAJ above. The solution is to do one the following:

  • Put the path to xerces.jar (or other DOM Level 2 interfaces) in the variable '' in the file admin.config. This resides in $WAS_ROOT$/bin before all other variables.
  • or, if you run WAS $WAS_ROOT/bin/debug/adminserver.{bat|sh} add a line 'set WAS_CP=xerces.jar' (or other DOM Level 2 interfaces) before other set WAS_CP commands.
  • or, add JDOM to the application server CLASSPATH, using either the admin.cfg file or the administration console.

(Contributed by Guy Nirpaz)

What JDOM version works with which JDK?

JDOM 1.x versions support JDK 1.2 and later.

JDOM 2.x versions support JDK 1.5 and later.

Are there any performance numbers?

The JDOM 2.x development process included benchmarks for tracking performance changes. There are performance numbers comparing different versions of JDOM 2.x as well as comparing the performance of JDOM on different JDK versions.

Dennis Sosnoski in the past ran performance benchmarks. In general, most XML object models are in a similar neighborhood.

How does JDOM integrate with XSLT?

There are many ways to do XSL transforms with JDOM. The most straightforward way is to use the standard JAXP Transformer interface and the JDOMSource/JDOMResult classes found in the org.jdom2.transform package. Look to the sample named XSLTransform for an example.

Is there XPath support in JDOM?

Yes! It's fully integrated in org.jdom2.xpath as of Beta 9, based on Jaxen.

What features of XML are not handled by JDOM?

None that we know of.

Is JDOM thread safe?

The core API is intentionally not thread safe. In other words, there are no synchronized blocks within org.jdom. This decision makes sense because we expect the primary JDOM use cases to be:

  • Single thread reads an XML stream into JDOM and looks at it read only
  • Single thread reads an XML stream into JDOM and modifies it
  • Single thread reads an XML stream into JDOM and makes it available to a run time system for read only access

The use case where a "Single thread reads an XML stream into JDOM and exposes it to multiple threads to modify its contents" is fairly rare. In that case, JDOM can still be made thread safe but the programmer simply has to perform their own synchronization, perhaps as synchronizing on the Document instance.

On the other hand, there are certain functions that require 'operational' parts of JDOM to be Thread safe:

  • org.jdom2.Namespace.getNamespace() is safe
  • All factory-type classes are safe (XPathFactory, etc.)

Why does equals() only do a == check?

In JDOM two Content objects are only equal if they're the exact same object. This lets a call like list.remove(elem) remove only the exact Element passed in, not any element that's equivalent. This's a very important distinction. Doing a full equals() on an Element would require recursing down the tree, and in general we believe it unlikely you'll want to know if this element and all its children are equivalent to another one. If you really do want to know you can write some comparison code yourself that checks only as much as you want to check (maybe the name/namespaces only) instead of doing a full recurse.

Why is equals() declared final?

The equals() methods are final for JDOM Content classes so that a subclass can't break the == behavior that's required for calls like list.remove(elem) to work as designed. Similarly, the hashCode() methods are also final (to preserve the equals/hashCode contract).

How do I construct a Document from a String?

You use standard Java IO library calls. Wrap the String with a StringReader and pass the reader to SAXBuilder:

Document doc = StringReader(xml));

How do I remove an Element or other content?

Use the methods on the List returned by getChildren() or getContent(). JDOM doesn't need special methods because the methods already exist in List. For example to remove an element from a list of children:

List children = parent.getChildren();
children.remove(element); // given child
children.remove(0);       // first child

Other methods on List provide options to remove all children, add a child at a given location, and so on.

If you have a particular Element or other Content that you want to remove from its parent, you can detach the Content with the Content.detach() method.

How do I move an Element from one place to another?

There's no need for node "importing" like there is with DOM. Just remove the element from its current place, then add the element to its new place. The element's content (including its element children) will naturally "tag" along for the ride. You have to remove the element before adding it to its new place because elements may have only one parent returned by getParent().


How do I copy an Element from one place to another?

There's no need for node "importing" like there is with DOM. Just clone the element being copied and add its clone in its new place. You have to clone the element before adding it to its new place because elements may have only one parent returned by getParent().


Can an element or attribute name contain a colon?

The XML 1.0 specification specifically reserves the colon character for use with XML Namespaces. No other use is compliant with XML 1.0. Therefore JDOM does not allow you to create element and attribute names that contain colons except when using namespaces. Furthermore, because of the way namespaces are implemented in JDOM, you cannot simply create an Element or Attribute with a fully qualified name like svg:title. That is you cannot do this:

Element e = new Element("svg:title");

Instead you must split the two parts into a Namespace and a local name. This is the proper JDOM way to create an element in a namespace:

Element e = 
  new Element("title", "svg", "");

The first argument is the local name. The second argument is the prefix. The third argument is the namespace URI.

If you're trying to create the xml:lang and xml:space attributes use:

Element e = 
  new Element("lang", Namespace.XML_NAMESPACE);

Why do I need to pass in a Namespace to getChild(), when the child element I'm looking for has no namespace declaration?

Specifically, for this XML fragment:

  <y xmlns="">
    <z />

You need to use code like this:

Namespace ns = Namespace.getNamespace("");
Element y = x.getChild("y", ns);
Element z = y.getChild("z", ns);


If I leave out the namespace from the second call to getChild(), it returns null. Why?

JDOM works on the logical in-memory XML tree, not the textual representation on-disk. While the element z has no namespace declaration, it does have a namespace - the one inherited from its parent, which declares a default namespace (associated with the URI

According to the namespaces specification, the following XML fragment is identical in meaning to the previous one:

  <y xmlns="">
    <z xmlns="" />

The way that the JDOM API handles namespaces means that you can write code that works for both examples. Otherwise, you would need to have code that checked for each case separately.

Similarly, if you were constructing (instead of reading) the XML in the first example above, you would need to write code like this:

Namespace ns = Namespace.getNamespace("");
Element y = new Element("y", ns);
Element z = new Element("z", ns);
If you left out the Namespace instance from the constructor for the element z, you would have the following tree in-memory:
  <y xmlns="">
    <z xmlns="" />

Why do all new lines appear as \n, even on Windows?

According to section 2.11 of the XML Recommendation, 2nd edition:

To simplify the tasks of applications, an XML processor must normalize line breaks in parsed entities to #xA either by translating the two-character sequence #xD #xA and any #xD that is not followed by #xA to #xA on input before parsing, or by using some other method such that the characters passed to the application are the same as if it did this translation.

In other words, this is exactly what's supposed to happen.

Some XML input may escape the \r carriage return as &#xD; and the XML parser will translate this in to a true \r character in your JDOM Text. When this Text is output again it will be re-escaped as &#xD;.

Why does setText("&#160;") not do what I want?

When you pass a string into a method like setText() JDOM assumes it's just that, a string, not a fragment of XML. For example, when you call:


JDOM assumes you want to set the content to the string containing the six characters & # 1 6 0 ;. It does not parse it to attempt to understand it as XML first. Thus when you output the text using XMLOutputter it will naturally escape the special ampersand character and output &amp;#160;. The solution is to pass regular Unicode characters to the setText() method or, if you have text data that you want to be interpreted as XML, pass it through an XML parser before it goes into JDOM. This is what the SAXBuilder and DOMBuilder classes do.

When using an IDE debugger why do I see a strange ArrayIndexOutOfBoundsException?

Some parsers (Xerces included) use this exception as part of their standard operating procedure, internally throwing and catching the exception. No code outside the library is meant see it. However, IDE debuggers are often configured to report any time this exception is thrown, and thus they expose the exception. It can be safely ignored.

How do I add a PI or Comment before the root element?

You must access the document content as a List. Either get the list and add content to its head, or set the list of content explicitly.

doc.getContent().add(0, pi);

How do I avoid getting an OutOfMemoryError?

Most JVMs have an option to increase their maximum heap size, which is the maximum amount of memory the JVM can use for its objects. You can set your initial heap size to 32 Megs and maximum heap size to 64 Megs with the following command:

java -Xms32m -Xmx64m SomeClass

If you don't require all the document in memory, look at the jdom-contrib module's org.jdom.contrib.input.scanner package which lets you build the portion of a document matching an XPath expression.

Why does my file encoding on output not match the encoding on input?

The default character encoding used by XMLOutputter is UTF-8, a variable-length encoding that can represent all Unicode characters. This can be changed with a call to format.setEncoding() on the Format object passed to XMLOutputter. It would be nice if XMLOutputter could default to the original encoding for a file, but unfortunately parsers don't indicate the original encoding. You have to set it programatically.

This issue most often affects people with documents in the common ISO-8859-1 (Latin-1) encoding who use characters like ñ but aren't familiar with having to think about encodings. The tip to remember is that with these documents you must set the output encoding to ISO-8859-1, otherwise characters in the range 128-255 will be output using a double byte encoding in UTF-8 instead of the normal single byte encoding of ISO-8859-1.

Why does passing a document through a socket sometimes hang the parser?

The problem is that several XML parsers close the input stream when they read EOF (-1). This is true of Xerces, which is JDOM's default parser. It is also true of Crimson. Unfortunately, closing a SocketInputStream closes the underlying SocketImpl, setting the file descriptor to null. The socket's output stream is useless after this, so your application will be unable to send a response. To workaround, protect your socket's input stream with an InputStream wrapper that doesn't close the underlying stream (override the close() method), or read everything into a buffer before handing off to the JDOM builder:

byte[] buf = new byte[length];
new DataInputStream(inputStream).readFully(buf);
InputStream in = new ByteArrayInputStream(buf);
(Contributed by Joseph Bowbeer)

How do I keep the DTD from loading? Even when I turn off validation the parser tries to load the DTD file.

Even when validation is turned off, an XML parser will by default load the external DTD file in order to parse the DTD for external entity declarations. Xerces has a feature to turn off this behavior named "" and if you know you're using Xerces you can set this feature on the builder.

  "", false);

If you're using another parser like Crimson, your best bet is to set up an EntityResolver that resolves the DTD without actually reading the separate file.

import org.xml.sax.*;
public class NoOpEntityResolver implements EntityResolver {
  public InputSource resolveEntity(String publicId, String systemId) {
    return new InputSource(new StringBufferInputStream(""));

Then in the builder...

builder.setEntityResolver(new NoOpEntityResolver());

There is a downside to this approach. Any entities in the document will be resolved to the empty string, and will effectively disappear. If your document has entities, you need to setExpandEntities(false) code and ensure the EntityResolver only suppresses the DocType.

How do I validate against a schema when using JDOM 2.x?

JDOM 2.x introduces a simplified model for Document validation. The org.jdom2.input.sax.XMLReaders Enum contains members that set up your validation for you.

The complete code in JDOM 2.x looks like this:

SAXBuilder builder =
  new SAXBuilder(XMLReaders.XSDVALIDATING);
Document doc =;

How do I validate against a schema when using JDOM 1.x?

JDOM 1.x doesn't have it's own parser, it uses standard parsers like Xerces to do the heavy lifting. If you want schema validation make sure you choose a parser that supports schemas. Xerces 2 is a good choice (get it from You also need to use code JDOM Beta 8 or later.

To specify the parser JDOM uses, you can either configure JAXP appropriately (since JDOM uses JAXP if it's available, see the end of this entry for details) or you can explicitly pass the name of the parser to the SAXBuilder constructor. For Xerces 2 the parser class is org.apache.xerces.parsers.SAXParser. You must also enable parser validation by passing "true" when creating a SAXBuilder.

SAXBuilder builder =
  new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);

Next, you tell the parser (Xerces) you want to validate against a schema (or schemas), and you pass the parser information about those schema. Different parsers do this in different ways. In Xerces you do this by setting special 'features' and 'properties' of the parser. JDOM exposes these parser settings with the setFeature() and setProperty() methods on SAXBuilder. These pass-through methods were added after Beta 7, which is why you need Beta 8 or above.

Schemas are enabled by setting the feature "" to true.

"", true);

Schema locations are given by setting the property "" to a list of whitespace separated name-value pairs. The 'name' is the namespace the schema is associated with, the 'value' is the location of the schema for that namespace. For example:

"",   " soap-envelope.xsd" + " " +   " weblog.xsd");

The above example shows how to validate against multiple schemas -- against the SOAP 1.2 schema where the namespace is and the and against a schema for namespace The files describing these schemas are in soap-envelope.xsd and weblog.xsd respectively. You can add as many of these name value pairs as necessary. The values themselves are URLs. The name value pairs follow the meaning given in the Schema recommendation ( ).

The complete code looks like this:

SAXBuilder builder =
  new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
  "", true);
  " soap-envelope.xsd" + " " +
  " weblog.xsd");
Document doc =;

If you want to use JAXP to select the parser, you can skip specifying a class to the SAXBuilder constructor and instead set the system property "javax.xml.parsers.SAXParserFactory" to the value "org.apache.xerces.jaxp.SAXParserFactoryImpl". That tells JAXP to use Xerces' factory to build parsers. If you like, you can specify this property on the command line:

java -Djavax.xml.parsers.SAXParserFactory=
          org.apache.xerces.jaxp.SAXParserFactoryImpl ...

(Contributed by Kevin Jones)

How can I perform in-memory validation against a DTD or Schema?

Currently you can't do this, in JDOM or any other Java document object model API. However, this is something we'd like JDOM to support, and we have a volunteer who's working on it.

JDOM ensures the document in memory is always well-formed. Can JDOM also ensure the document in memory is always valid?

No, it's our current belief that it's better to expose a checkValid() type of call than to attempt constant validation checking. One reason is performance. A second reason is that you have a chicken-and-egg problem where for example an element needs exactly two child elements to be valid, but after adding either child the document will be in a temporarily invalid state. To work around this would require something like transactional modifications, and that's a lot of overhead for little gain.

Why do I get an IndexOutOfBoundsException or ConcurrentModificationException on looping?

Code like the following will throw an IndexOutOfBoundsException:

 List children = root.getChildren("foo");
 int size = children.size();
 for (int i = 0; i < size; i++) {
   Element child = (Element) children.get(i);

The reason is that the size of the list is pre-calculated but the size is reduced by one on each detach() call, causing the for loop to walk off the end of the list. The right way to loop is to use an Iterator. With an Iterator you don't have this problem, and it's faster as well.

However, even with an Iterator, the following code throws a ConcurrentModificationException:

 List children = root.getChildren("foo");
 Iterator itr = children.iterator();
 while (itr.hasNext()) {
   Element child = (Element);

The reason is that the detach() call modifies the list of children at the same time the iterator is traversing the list, and that's a concurrent modification. The solution is to use the Iterator's remove() method instead of detach() in this situation:

List children = root.getChildren("foo");
 Iterator itr = children.iterator();
 while (itr.hasNext()) {
   Element child = (Element);

Is there an archive for the JDOM mailing lists?

Yes, all the messages are available for your Web-based perusal. Below are the slick searchable all-in-one archives:

There are additional archives at:

How do I unsubscribe from a mailing list?

The URL to manage your list membership (including subscription) is attached at the bottom of every list message. It should be something like Make sure to replace "youraddr" with your address and "yourhost" with your host. For jdom-announce replace "interest" with "announce" in the URL.

How do I post to the mailing list from multiple addresses?

For spam protection, only members of the mailing list may post. To post from multiple accounts, subscribe each account and set the "Disable mail delivery" feature to "On" for all the extra accounts. You can set that feature at the URL given in the previous answer.

Should I ask general XML questions to Jason, Brett, or Rolf?

No, they're busy enough already. But you can order Brett's book Java and XML or one of the other XML introductory books like XML Bible by Elliotte Rusty Harold (one of our prominent jdom-interest list members).

The book Java and XML talks about JDOM 1.0; why the confusion?

The book covers an early beta. Much has changed (for the better) since publication of the book. For the most accurate JDOM API trust the Javadocs, not the book. Brett was a little optimistic when writing the book. His 2nd Edition sets things straight.

I have a question that isn't answered here. What do I do?

First, you should search the JDOM mailing list archives. For example, if you're using an Oracle parser and see an IllegalTargetException that smells fishy, you can search for "oracle IllegalTargetException" and you'll find discussion about the issue. The searches are powerful and fast!

If you don't find an answer in the archives, you can post to jdom-interest. If you think you found a bug, make sure you follow the following advice about bug reporting!

How do I submit a bug report?

If you believe you found a bug in JDOM, please follow this procedure:

  1. Check both the open issues and closed issues to see if it's a known issue.
  2. Check if the problem occurs when using the latest development version (source .zip) of JDOM.
  3. Search the JDOM mailing list archives as explained above.
  4. If you don't find resolution with the latest snapshot, either create an issue on GitHub or post to the jdom-interest mailing list; make sure you're a subscriber first as only subscribers can post.
  5. In the bug report, give as much information as possible -- the stack trace, a reproducible and short code example, the XML file causing problems. Make sure to state the version of JDOM used (official version or GitHub commit).
  6. If you have a patch to fix the bug, please submit that along with the problem report. We love patches.

Where can I learn more?

JDOM API documentation, slides from the initial JDOM announcement, and other helpful resources can all be downloaded here.