Flexible XML framework for Java providing comprehensive XML processing capabilities
—
This section covers creating XML documents, parsing XML from various sources, and using the factory classes that manage DOM4J object creation. DOM4J provides flexible approaches for both programmatic document creation and parsing XML from files, streams, and other sources.
DocumentHelper provides convenient static methods for creating DOM4J objects and performing common operations.
import org.dom4j.DocumentHelper;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Attribute;
import org.dom4j.DocumentException;public final class DocumentHelper {
// Document creation
public static Document createDocument();
public static Document createDocument(Element rootElement);
// Parse text as XML
public static Document parseText(String text) throws DocumentException;
}public final class DocumentHelper {
// Element creation
public static Element createElement(QName qname);
public static Element createElement(String name);
// Attribute creation
public static Attribute createAttribute(Element owner, QName qname, String value);
public static Attribute createAttribute(Element owner, String name, String value);
}public final class DocumentHelper {
// Text content nodes
public static CDATA createCDATA(String text);
public static Comment createComment(String text);
public static Text createText(String text);
public static Entity createEntity(String name, String text);
// Processing instructions
public static ProcessingInstruction createProcessingInstruction(String target, String data);
public static ProcessingInstruction createProcessingInstruction(String target, Map<String, String> data);
// Namespace and QName
public static Namespace createNamespace(String prefix, String uri);
public static QName createQName(String localName, Namespace namespace);
public static QName createQName(String localName);
}public final class DocumentHelper {
// XPath creation
public static XPath createXPath(String xpathExpression) throws InvalidXPathException;
public static XPath createXPath(String xpathExpression, VariableContext context) throws InvalidXPathException;
// Pattern and filter creation
public static NodeFilter createXPathFilter(String xpathFilterExpression);
public static Pattern createPattern(String xpathPattern);
// XPath operations on node collections
public static List<Node> selectNodes(String xpathFilterExpression, List<Node> nodes);
public static List<Node> selectNodes(String xpathFilterExpression, Node node);
public static void sort(List<Node> list, String xpathExpression);
public static void sort(List<Node> list, String expression, boolean distinct);
}public final class DocumentHelper {
// Path-based element creation
public static Element makeElement(Branch source, String path);
}// Create empty document
Document document = DocumentHelper.createDocument();
// Create document with root element
Element root = DocumentHelper.createElement("catalog");
Document catalog = DocumentHelper.createDocument(root);
// Parse XML text
String xmlText = "<book><title>XML Guide</title></book>";
Document parsed = DocumentHelper.parseText(xmlText);
// Create various node types
Element product = DocumentHelper.createElement("product");
Attribute id = DocumentHelper.createAttribute(product, "id", "P123");
Comment comment = DocumentHelper.createComment("Product catalog");
CDATA cdata = DocumentHelper.createCDATA("<script>alert('test');</script>");
Text text = DocumentHelper.createText("Product description");
// Create namespaced elements
Namespace ns = DocumentHelper.createNamespace("catalog", "http://example.com/catalog");
QName productQName = DocumentHelper.createQName("product", ns);
Element nsProduct = DocumentHelper.createElement(productQName);
// XPath creation and usage
XPath xpath = DocumentHelper.createXPath("//product[@id]");
List<Node> products = xpath.selectNodes(document);
NodeFilter filter = DocumentHelper.createXPathFilter("self::product");
List<Node> filtered = document.selectNodes("//node()").stream()
.filter(filter::matches)
.collect(Collectors.toList());
// Path-based element creation
Element catalog = DocumentHelper.createElement("catalog");
Element book = DocumentHelper.makeElement(catalog, "books/book");
// Creates: catalog/books/book if they don't existDocumentFactory provides a configurable factory for creating all DOM4J objects with support for customization and singleton access.
import org.dom4j.DocumentFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.QName;public class DocumentFactory {
// Singleton instance
public static synchronized DocumentFactory getInstance();
}public class DocumentFactory {
// Document creation methods
public Document createDocument();
public Document createDocument(String encoding);
public Document createDocument(Element rootElement);
// Document type creation
public DocumentType createDocType(String name, String publicId, String systemId);
}public class DocumentFactory {
// Element creation
public Element createElement(QName qname);
public Element createElement(String name);
public Element createElement(String qualifiedName, String namespaceURI);
}public class DocumentFactory {
// Attribute creation
public Attribute createAttribute(Element owner, QName qname, String value);
public Attribute createAttribute(Element owner, String name, String value);
}public class DocumentFactory {
// Text-based nodes
public CDATA createCDATA(String text);
public Comment createComment(String text);
public Text createText(String text);
public Entity createEntity(String name, String text);
// Processing instructions
public ProcessingInstruction createProcessingInstruction(String target, String data);
public ProcessingInstruction createProcessingInstruction(String target, Map<String, String> data);
}public class DocumentFactory {
// Namespace creation
public Namespace createNamespace(String prefix, String uri);
// QName creation
public QName createQName(String localName, Namespace namespace);
public QName createQName(String localName);
public QName createQName(String name, String prefix, String uri);
public QName createQName(String qualifiedName, String uri);
}public class DocumentFactory {
// XPath and pattern creation
public XPath createXPath(String xpathExpression) throws InvalidXPathException;
public XPath createXPath(String xpathExpression, VariableContext variableContext);
public NodeFilter createXPathFilter(String xpathFilterExpression, VariableContext variableContext);
public NodeFilter createXPathFilter(String xpathFilterExpression);
public Pattern createPattern(String xpathPattern);
}public class DocumentFactory {
// QName management
public List<QName> getQNames();
// XPath namespace configuration
public Map<String, String> getXPathNamespaceURIs();
public void setXPathNamespaceURIs(Map<String, String> namespaceURIs);
}// Get singleton instance
DocumentFactory factory = DocumentFactory.getInstance();
// Create document with encoding
Document document = factory.createDocument("UTF-8");
// Create elements
Element root = factory.createElement("catalog");
document.setRootElement(root);
Element product = factory.createElement("product");
root.add(product);
// Create namespaced elements
Element nsElement = factory.createElement("item", "http://example.com/catalog");
// Create attributes
Attribute id = factory.createAttribute(product, "id", "P123");
product.add(id);
// Create QNames and namespaces
Namespace catalogNS = factory.createNamespace("cat", "http://example.com/catalog");
QName productQName = factory.createQName("product", catalogNS);
Element nsProduct = factory.createElement(productQName);
// Create content nodes
Comment comment = factory.createComment("Generated catalog");
Text description = factory.createText("Product description");
CDATA script = factory.createCDATA("<script>processProduct();</script>");
document.add(comment);
product.add(description);
// Configure XPath namespaces
Map<String, String> namespaces = Map.of(
"cat", "http://example.com/catalog",
"prod", "http://example.com/product"
);
factory.setXPathNamespaceURIs(namespaces);
// Create XPath with configured namespaces
XPath xpath = factory.createXPath("//cat:product[@prod:id]");// Create custom factory for specialized behavior
public class CustomDocumentFactory extends DocumentFactory {
@Override
public Element createElement(QName qname) {
// Return custom element implementation
return new MyCustomElement(qname);
}
@Override
public Attribute createAttribute(Element owner, QName qname, String value) {
// Return custom attribute implementation
return new MyCustomAttribute(qname, value);
}
}
// Use custom factory
DocumentFactory customFactory = new CustomDocumentFactory();
Document document = customFactory.createDocument();
Element element = customFactory.createElement("custom");SAXReader creates DOM4J documents from XML sources using SAX parsing. It provides configurable parsing with support for validation, entity resolution, and custom error handling.
import org.dom4j.io.SAXReader;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.xml.sax.XMLReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;public class SAXReader {
// Constructors
public SAXReader();
public SAXReader(boolean validating);
public SAXReader(DocumentFactory factory);
public SAXReader(XMLReader xmlReader);
public SAXReader(String xmlReaderClassName) throws SAXException;
}public class SAXReader {
// Read from various sources
public Document read(File file) throws DocumentException;
public Document read(InputSource in) throws DocumentException;
public Document read(InputStream in) throws DocumentException;
public Document read(Reader reader) throws DocumentException;
public Document read(String systemId) throws DocumentException;
public Document read(URL url) throws DocumentException;
}public class SAXReader {
// XMLReader configuration
public void setXMLReader(XMLReader reader);
public XMLReader getXMLReader() throws SAXException;
public void setXMLReaderClassName(String className) throws SAXException;
// Validation
public boolean isValidating();
public void setValidating(boolean validation);
// Factory configuration
public DocumentFactory getDocumentFactory();
public void setDocumentFactory(DocumentFactory documentFactory);
// Error handling
public ErrorHandler getErrorHandler();
public void setErrorHandler(ErrorHandler errorHandler);
// Entity resolution
public EntityResolver getEntityResolver();
public void setEntityResolver(EntityResolver entityResolver);
}// Basic parsing
SAXReader reader = new SAXReader();
// Parse from file
Document document = reader.read(new File("catalog.xml"));
// Parse from URL
Document webDoc = reader.read(new URL("http://example.com/data.xml"));
// Parse from string
String xmlContent = "<book><title>Guide</title></book>";
Document stringDoc = reader.read(new StringReader(xmlContent));
// Parse from input stream
try (InputStream is = new FileInputStream("data.xml")) {
Document streamDoc = reader.read(is);
}
// Validating parser
SAXReader validatingReader = new SAXReader(true);
try {
Document validDoc = validatingReader.read("valid.xml");
} catch (DocumentException e) {
System.err.println("Validation error: " + e.getMessage());
}
// Custom error handling
reader.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException e) {
System.out.println("Warning: " + e.getMessage());
}
@Override
public void error(SAXParseException e) throws SAXException {
System.err.println("Error: " + e.getMessage());
throw e;
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
System.err.println("Fatal: " + e.getMessage());
throw e;
}
});
// Custom entity resolver
reader.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
if (systemId.endsWith("custom.dtd")) {
return new InputSource(new StringReader("<!-- Custom DTD -->"));
}
return null; // Use default resolution
}
});
// Custom document factory
DocumentFactory customFactory = new MyDocumentFactory();
reader.setDocumentFactory(customFactory);
// Parse with custom factory
Document customDoc = reader.read("data.xml");// Configure specific XMLReader
XMLReader xmlReader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
xmlReader.setFeature("http://xml.org/sax/features/validation", true);
xmlReader.setFeature("http://apache.org/xml/features/validation/schema", true);
SAXReader reader = new SAXReader(xmlReader);
// Set schema validation
xmlReader.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
"http://example.com/schema http://example.com/schema.xsd");
// Parse with schema validation
try {
Document document = reader.read("instance.xml");
System.out.println("Document is valid");
} catch (DocumentException e) {
System.err.println("Validation failed: " + e.getMessage());
}// Create complete document structure
Document catalog = DocumentHelper.createDocument();
// Add XML declaration and encoding
catalog.setXMLEncoding("UTF-8");
// Add processing instruction
catalog.addProcessingInstruction("xml-stylesheet",
"type=\"text/xsl\" href=\"catalog.xsl\"");
// Create root element with namespace
Namespace catalogNS = Namespace.get("cat", "http://example.com/catalog");
Element root = catalog.addElement(QName.get("catalog", catalogNS));
// Add schema location
root.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.addAttribute(QName.get("schemaLocation",
Namespace.get("xsi", "http://www.w3.org/2001/XMLSchema-instance")),
"http://example.com/catalog catalog.xsd");
// Build content using fluent interface
Element books = root.addElement("books");
Element book1 = books.addElement("book")
.addAttribute("isbn", "123-456-789")
.addAttribute("available", "true");
book1.addElement("title").addText("DOM4J Guide");
book1.addElement("author").addText("John Smith");
book1.addElement("price").addText("29.99");
// Add CDATA section for description
book1.addElement("description").add(
DocumentHelper.createCDATA("<p>Complete guide to <b>DOM4J</b> XML processing.</p>"));
// Add comment
books.addComment("More books will be added");// Create document template
public class CatalogBuilder {
private final DocumentFactory factory;
private final Namespace catalogNS;
public CatalogBuilder() {
this.factory = DocumentFactory.getInstance();
this.catalogNS = factory.createNamespace("cat", "http://example.com/catalog");
}
public Document createCatalog(String title, String version) {
Document document = factory.createDocument("UTF-8");
Element root = document.addElement(factory.createQName("catalog", catalogNS));
root.addAttribute("version", version);
root.addAttribute("title", title);
root.addAttribute("generated", Instant.now().toString());
return document;
}
public Element addBook(Element catalog, String isbn, String title, String author) {
Element books = catalog.element("books");
if (books == null) {
books = catalog.addElement("books");
}
return books.addElement("book")
.addAttribute("isbn", isbn)
.addElement("title").addText(title).getParent()
.addElement("author").addText(author).getParent();
}
}
// Use template
CatalogBuilder builder = new CatalogBuilder();
Document catalog = builder.createCatalog("Technical Books", "1.0");
Element book = builder.addBook(catalog.getRootElement(),
"123-456-789", "XML Processing", "Jane Doe");// For large documents, build incrementally
public class StreamingCatalogBuilder {
private final Document document;
private final Element booksElement;
public StreamingCatalogBuilder() {
this.document = DocumentHelper.createDocument();
Element root = document.addElement("catalog");
this.booksElement = root.addElement("books");
}
public void addBook(Map<String, String> bookData) {
Element book = booksElement.addElement("book");
bookData.forEach((key, value) -> {
if ("isbn".equals(key)) {
book.addAttribute("isbn", value);
} else {
book.addElement(key).addText(value);
}
});
}
public Document getDocument() {
return document;
}
public void writeToFile(String filename) throws IOException {
try (FileWriter writer = new FileWriter(filename)) {
XMLWriter xmlWriter = new XMLWriter(writer, OutputFormat.createPrettyPrint());
xmlWriter.write(document);
}
}
}
// Stream processing
StreamingCatalogBuilder builder = new StreamingCatalogBuilder();
// Process data source (e.g., database results)
while (resultSet.next()) {
Map<String, String> bookData = Map.of(
"isbn", resultSet.getString("isbn"),
"title", resultSet.getString("title"),
"author", resultSet.getString("author"),
"price", resultSet.getString("price")
);
builder.addBook(bookData);
}
builder.writeToFile("catalog.xml");import org.dom4j.DocumentException;
try {
// Parsing operations that may fail
SAXReader reader = new SAXReader();
Document document = reader.read("malformed.xml");
} catch (DocumentException e) {
// Get detailed error information
String message = e.getMessage();
Throwable cause = e.getCause();
// Handle specific error types
if (cause instanceof SAXParseException) {
SAXParseException saxError = (SAXParseException) cause;
int line = saxError.getLineNumber();
int column = saxError.getColumnNumber();
System.err.printf("Parse error at line %d, column %d: %s%n",
line, column, saxError.getMessage());
} else {
System.err.println("Document processing error: " + message);
}
}// Custom error handler for validation
class ValidationErrorHandler implements ErrorHandler {
private final List<String> errors = new ArrayList<>();
private final List<String> warnings = new ArrayList<>();
@Override
public void warning(SAXParseException e) {
warnings.add(formatError("WARNING", e));
}
@Override
public void error(SAXParseException e) {
errors.add(formatError("ERROR", e));
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
String message = formatError("FATAL", e);
errors.add(message);
throw new SAXException(message);
}
private String formatError(String level, SAXParseException e) {
return String.format("%s [%d:%d]: %s",
level, e.getLineNumber(), e.getColumnNumber(), e.getMessage());
}
public List<String> getErrors() { return new ArrayList<>(errors); }
public List<String> getWarnings() { return new ArrayList<>(warnings); }
public boolean hasErrors() { return !errors.isEmpty(); }
}
// Use validation handler
SAXReader reader = new SAXReader(true);
ValidationErrorHandler errorHandler = new ValidationErrorHandler();
reader.setErrorHandler(errorHandler);
try {
Document document = reader.read("document.xml");
if (errorHandler.hasErrors()) {
System.err.println("Validation errors:");
errorHandler.getErrors().forEach(System.err::println);
}
if (!errorHandler.getWarnings().isEmpty()) {
System.out.println("Validation warnings:");
errorHandler.getWarnings().forEach(System.out::println);
}
} catch (DocumentException e) {
System.err.println("Parse failed: " + e.getMessage());
}DOM4J's document creation and parsing capabilities provide both simplicity for basic operations and flexibility for advanced XML processing requirements. The combination of static helper methods, configurable factories, and robust parsing support makes it suitable for a wide range of XML processing scenarios from simple document creation to complex enterprise XML processing pipelines.
Install with Tessl CLI
npx tessl i tessl/maven-org-dom4j--dom4j