Migration Guide

This guide helps you migrate from other XML libraries to DomTrip. We cover the most common migration scenarios and provide side-by-side examples.

From DOM4J

DOM4J is one of the most popular XML libraries for Java. Here's how to migrate common patterns:

Document Loading

// DomTrip equivalent of DOM4J SAXReader.read()
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Assertions.assertNotNull(editor);

Element Navigation

// DomTrip equivalent of DOM4J element navigation
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();
Optional<Element> child = root.childElement("child");
Stream<Element> children = root.childElements("item");

Adding Elements

// DomTrip equivalent of DOM4J addElement()
String xml = createMavenPomXml();
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element parent = editor.root().descendant("dependencies").orElseThrow();
Element dependency = editor.addElement(parent, "dependency");
editor.addElement(dependency, "groupId", "junit");
editor.addElement(dependency, "artifactId", "junit");

Attribute Handling

// DomTrip equivalent of DOM4J attribute handling
String xml = createTestXml("element");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element element = editor.root();
editor.setAttribute(element, "scope", "test");
String scope = element.attribute("scope");

Serialization

// DomTrip equivalent of DOM4J serialization
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
String result = editor.toXml(); // Preserves original formatting
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());

From JDOM

JDOM has a simpler API than DOM4J but similar concepts:

Document Loading

// DomTrip equivalent of JDOM SAXBuilder.build()
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Assertions.assertNotNull(editor);

Element Operations

// DomTrip equivalent of JDOM element operations
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();
Optional<Element> child = root.childElement("child");
Stream<Element> children = root.childElements("item");

// Add new element
Element newElement = editor.addElement(root, "newChild", "content");

Text Content

// DomTrip equivalent of JDOM text content handling
String xml = createTestXml("element");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element element = editor.root();
editor.setTextContent(element, "new content");
String content = element.textContent();

From Java DOM

The built-in Java DOM API is verbose but powerful:

Document Loading

// DomTrip equivalent of Java DOM document loading
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Assertions.assertNotNull(editor);

Element Navigation

// DomTrip equivalent of Java DOM element navigation
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();
Optional<Element> child = root.childElement("child");

Creating Elements

// DomTrip equivalent of Java DOM element creation
String xml = createTestXml("parent");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element parent = editor.root();
Element newElement = editor.addElement(parent, "newChild", "content");

Attributes

// DomTrip equivalent of Java DOM attribute handling
String xml = createTestXml("element");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element element = editor.root();
editor.setAttribute(element, "scope", "test");
String scope = element.attribute("scope");

From Jackson XML

Jackson XML is primarily for object mapping, but here are equivalent operations:

Simple Parsing

// DomTrip equivalent of Jackson XML parsing
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();
Optional<Element> child = root.childElement("child");

Object Mapping vs Manual Construction

// DomTrip equivalent of Jackson XML object mapping
Element dependency = Element.of("dependency");
dependency.addChild(Element.text("groupId", "junit"));
dependency.addChild(Element.text("artifactId", "junit"));
dependency.addChild(Element.text("version", "4.13.2"));

String xml = dependency.toXml();

Common Migration Patterns

1. Error Handling

// DomTrip provides consistent exception handling
try {
    String xml = createTestXml("root");
    Document document = Document.of(xml);
    Editor editor = new Editor(document);
    Assertions.assertNotNull(editor);
} catch (Exception e) {
    // Handle parsing error
    System.err.println("Failed to parse: " + e.getMessage());
}

2. Namespace Handling

// DomTrip equivalent of DOM4J namespace handling
String xml = createSoapXml();
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();

// Check if root itself is the Envelope element
assertEquals("Envelope", root.localName());
assertEquals("http://schemas.xmlsoap.org/soap/envelope/", root.namespaceURI());

3. XPath Queries

// DomTrip uses Stream-based filtering instead of XPath
String xml = createMavenPomXml();
Document document = Document.of(xml);
Editor editor = new Editor(document);
Element root = editor.root();
Stream<Element> nodes = root.descendants()
        .filter(el -> "dependency".equals(el.name()))
        .filter(el -> "test".equals(el.attribute("scope")));

Breaking Changes in Recent Versions

PomEditor Sub-Object API (v1.0.0+)

The PomEditor convenience methods have been moved to sub-object APIs for better organization:

Migration:

// OLD: Direct methods on PomEditor
editor.addDependency(depsElement, "junit", "junit", "4.13.2");
editor.addPlugin(pluginsElement, "org.apache.maven.plugins", "maven-compiler-plugin", "3.11.0");
editor.addModule(modulesElement, "core");
editor.addProperty(propsElement, "java.version", "17");

// NEW: Sub-object APIs
editor.dependencies().addDependency(depsElement, "junit", "junit", "4.13.2");
editor.plugins().addPlugin(pluginsElement, "org.apache.maven.plugins", "maven-compiler-plugin", "3.11.0");
editor.subprojects().addModule(modulesElement, "core");
editor.properties().addProperty(propsElement, "java.version", "17");

New capabilities added in 1.0.0:

  • editor.dependencies() — CRUD, exclusion management (addExclusion, deleteExclusion, hasExclusion)
  • editor.plugins() — Plugin CRUD and pluginManagement
  • editor.parent()setParent(), updateParent(), deleteParent()
  • editor.profiles()findProfile(), hasProfile()
  • Coordinates class for type-safe artifact coordinate handling

Element Navigation Rename (v0.5.0+)

Method names were renamed for clarity:

Migration:

// OLD: Element child navigation
element.child("name");          // ambiguous: child node or child element?
element.children("dependency"); // ambiguous

// NEW: Explicit element navigation
element.childElement("name");          // clearly an element
element.childElements("dependency");   // clearly elements

// OLD: ContainerNode node access
container.nodeAt(0);
container.nodeCount();

// NEW: ContainerNode child access
container.child(0);
container.childCount();

New ContainerNode methods added in 0.6.0:

  • insertChildBefore(referenceNode, newNode) — insert before a specific child
  • insertChildAfter(referenceNode, newNode) — insert after a specific child
  • firstChild() — returns Optional of first child
  • lastChild() — returns Optional of last child
  • replaceChild(existingNode, replacementNode) — replace a child node

Whitespace API Simplification (v0.1.1+)

The whitespace handling API has been simplified for better maintainability:

Removed Methods:

  • Node.followingWhitespace() and Node.followingWhitespace(String)
  • Element.innerFollowingWhitespace() and Element.innerFollowingWhitespace(String)

Migration Strategy:

// OLD: Setting whitespace after a node
node.followingWhitespace("\n  ");

// NEW: Set whitespace before the next node instead
nextNode.precedingWhitespace("\n  ");

// OLD: Setting whitespace after opening tag
element.innerFollowingWhitespace("\n    ");

// NEW: Set whitespace before first child instead
firstChild.precedingWhitespace("\n    ");

Rationale: The simplified model eliminates redundant whitespace storage where the same whitespace was stored in multiple places. This reduces memory usage and eliminates synchronization issues.

Migration Checklist

Before Migration

  • [ ] Identify all XML processing code in your application
  • [ ] Document current XML formatting requirements
  • [ ] Create test cases for existing functionality
  • [ ] Note any XPath usage (DomTrip doesn't support XPath)

During Migration

  • [ ] Replace library imports
  • [ ] Update document loading code
  • [ ] Convert element navigation to DomTrip patterns
  • [ ] Update attribute handling
  • [ ] Replace serialization code
  • [ ] Handle namespace operations
  • [ ] Update exception handling

After Migration

  • [ ] Run all existing tests
  • [ ] Verify XML output formatting
  • [ ] Check performance impact
  • [ ] Update documentation
  • [ ] Train team on new API patterns

Performance Considerations

Memory Usage

// DomTrip includes formatting metadata (~1.3x base size)
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
// Memory: ~1.3x base size

Processing Speed

  • Parsing: DomTrip is ~15% slower due to metadata collection
  • Navigation: Similar performance to other DOM libraries
  • Serialization: Faster for unmodified content, slower for heavily modified content

Gradual Migration Strategy

Phase 1: New Code

Start using DomTrip for all new XML processing code:

// Phase 1: Use DomTrip for new features
String pomXml = createMavenPomXml();
Document doc = Document.of(pomXml);
Editor editor = new Editor(doc);
// DomTrip operations here

Phase 2: Critical Paths

Migrate code that requires formatting preservation:

// Phase 2: Migrate formatting-critical code to DomTrip
String configXml = createConfigXml();
Document doc = Document.of(configXml);
Editor editor = new Editor(doc);
// Lossless editing operations here

Phase 3: Complete Migration

Replace remaining XML processing code:

// Phase 3: Migrate data extraction code
String xml = createTestXml("root");
Document document = Document.of(xml);
Editor editor = new Editor(document);
// Data extraction operations here

Getting Help

If you encounter issues during migration: