Java XML – JDOM2 – Namespaces

JDOM2 handles namespaces very well. However, there are three areas where confusion may arise while using namespaces. In this tutorial we look at them.

Creating new elements

While creating new elements in JDOM2, it is possible to pass the namespace to which the element should belong. However, the namespace only applies to the Element and not its children. i.e. the namespace assignment does not cascade. Here’s an example

package com.studytrails.xml.jdom;

import org.jdom2.Attribute;
import org.jdom2.Comment;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

public class NewElementAndNamespace {
	private static String xmlSource = "http://feeds.bbci.co.uk/news/technology/rss.xml?edition=int";

	public static void main(String[] args) {

		Namespace namespace = Namespace.getNamespace("p", "http://namespaceuri");
		// create the jdom
		Document jdomDoc = new Document();
		// create root element
		Element rootElement = new Element("Root", namespace);
		jdomDoc.setRootElement(rootElement);

		// add a comment
		Comment comment = new Comment("This is a comment");
		rootElement.addContent(comment);

		// add child
		Element child1 = new Element("child1", namespace);
		child1.addContent("This is child 1");

		// add child 2
		Element child2 = new Element("child2");
		child2.addContent("This is child 2");

		// add attribute
		Attribute attr1 = new Attribute("key1", "value1");
		child1.setAttribute(attr1);
		rootElement.addContent(child1);
		rootElement.addContent(child2);

		// Output as XML
		// create XMLOutputter
		XMLOutputter xml = new XMLOutputter();
		// we want to format the xml. This is used only for demonstration.
		// pretty formatting adds extra spaces and is generally not required.
		xml.setFormat(Format.getPrettyFormat());
		System.out.println(xml.outputString(jdomDoc));
	}
}

The output is



  
  This is child 1
  This is child 2


Notice how the namespace prefix is applied only to only child.

Searching for a child which is in a namespace

In the next example we read the XML created in the example above. (test.xml) we then search for a child named ‘child1’, first without specifying a namespace and then after specifying a namespace. In the first case it is not able to find the child, in the second case it does

package com.studytrails.xml.jdom;

import java.io.IOException;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;

public class GetChildInANamespace {
	private static String xmlTestFile = "test.xml";

	public static void main(String[] args) throws JDOMException, IOException {
		SAXBuilder jdomBuilder = new SAXBuilder();
		Document jdomDocument = jdomBuilder.build(xmlTestFile);

		// the root element
		Element root = jdomDocument.getRootElement();

		// lets search for a child named child1

		System.out.println(root.getChild("child1"));
		// prints null

		System.out.println(root.getChild("child1", Namespace.getNamespace("p", "http://namespaceuri")));
		// prints [Element: <p:child1 [Namespace: http://namespaceuri]/>]
	}
}

XPath and Namespace

JDOM2 XPath allows searching for an element with a specific Namespace. If an element is specified in a new Namespace then pass that JDOM2 Namespace object when searching for that element. If the XML defines a new default Namespace then create a new ‘dummy’ JDOM2 Namespace object with any prefix and the default Namespace URI specified in the XML. Access elements in the XML using the prefix of the ‘dummy’ JDOM2 Namespace object. . See example for more details. The example uses the following xml



	
	This is child 1
	This is child 2

The Example

package com.studytrails.xml.jdom;

import java.io.IOException;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.filter.Filters;
import org.jdom2.input.SAXBuilder;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;

public class XpathAndNamespace {
	private static String xmlTestFile = "test2.xml";

	public static void main(String[] args) throws JDOMException, IOException {
		// read the XML into a JDOM2 document.
		SAXBuilder jdomBuilder = new SAXBuilder();
		Document jdomDocument = jdomBuilder.build(xmlTestFile);

		XPathFactory xFactory = XPathFactory.instance();

		XPathExpression expr = xFactory.compile("//child2", Filters.element());
		Element child2 = expr.evaluateFirst(jdomDocument);
		System.out.println(child2);
		// prints null

		// we create a dummy namespace prefix that points to the default
		// namespace and then access the element using that namespace
		Namespace defaultNs = Namespace.getNamespace("a", "http://nondefaulnamespace");
		XPathExpression<Element> expr2 = xFactory.compile("//a:child2", Filters.element(), null, defaultNs);
		child2 = expr2.evaluateFirst(jdomDocument);
		System.out.println(child2);
		// prints [Element: <child2 [Namespace: http://nondefaulnamespace]/>]

		// search for a child from another namespace
		Namespace anotherNS = Namespace.getNamespace("p", "http//anothernamespace");
		XPathExpression<Element>> expr3 = xFactory.compile("//p:child1", Filters.element(), null, anotherNS);
		Element child1 = expr3.evaluateFirst(jdomDocument);
		System.out.println(child1);
		// prints [Element: <p:child1 [Namespace: http//anothernamespace]/>]
	}
}








Leave a Comment