Editor API
The Editor
class is the main entry point for DomTrip. It provides high-level operations for loading, editing, and serializing XML documents while preserving formatting.
Constructor
Editor()
Creates a new editor with default configuration.
// Default constructor
Editor editor = new Editor();
// With custom configuration
DomTripConfig config = DomTripConfig.prettyPrint();
Editor configuredEditor = new Editor(config);
// With existing document
String xml = "<project></project>";
Document doc = Document.of(xml);
Editor documentEditor = new Editor(doc);
// With document and configuration
Editor fullEditor = new Editor(doc, DomTripConfig.strict());
Editor(DomTripConfig config)
Creates a new editor with custom configuration.
// Default constructor
Editor editor = new Editor();
// With custom configuration
DomTripConfig config = DomTripConfig.prettyPrint();
Editor configuredEditor = new Editor(config);
// With existing document
String xml = "<project></project>";
Document doc = Document.of(xml);
Editor documentEditor = new Editor(doc);
// With document and configuration
Editor fullEditor = new Editor(doc, DomTripConfig.strict());
Editor(Document document)
Creates a new editor with an existing Document object.
// From string
String xmlString = createConfigXml();
Document doc = Document.of(xmlString);
Editor editor = new Editor(doc);
Editor(Document document, DomTripConfig config)
Creates a new editor with an existing Document and custom configuration.
// Default constructor
Editor editor = new Editor();
// With custom configuration
DomTripConfig config = DomTripConfig.prettyPrint();
Editor configuredEditor = new Editor(config);
// With existing document
String xml = "<project></project>";
Document doc = Document.of(xml);
Editor documentEditor = new Editor(doc);
// With document and configuration
Editor fullEditor = new Editor(doc, DomTripConfig.strict());
Throws: IllegalArgumentException
if document is null.
Advanced Constructor Examples
// Working with an existing document
String xmlString = "<project><version>1.0</version></project>";
Document existingDoc = Document.of(xmlString);
Editor editor = new Editor(existingDoc);
// Working with a programmatically created document
Document doc = Document.withRootElement("project");
Editor programmaticEditor = new Editor(doc);
// Continue editing
Element root = programmaticEditor.root();
programmaticEditor.addElement(root, "version", "1.0");
Document Management
document()
Gets the current XML document.
// Get document
Editor editor = new Editor();
editor.createDocument("project");
Document document = editor.document();
// Get root element
Element root = editor.root();
// Create document with root element
editor.createDocument("project");
Element newRoot = editor.root(); // <project></project>
// Serialize to XML
String xml = editor.toXml();
// Pretty printing
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
root()
Gets the root element of the document.
// Get document
Editor editor = new Editor();
editor.createDocument("project");
Document document = editor.document();
// Get root element
Element root = editor.root();
// Create document with root element
editor.createDocument("project");
Element newRoot = editor.root(); // <project></project>
// Serialize to XML
String xml = editor.toXml();
// Pretty printing
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
createDocument(String rootElementName)
Creates a new document with the specified root element.
// Get document
Editor editor = new Editor();
editor.createDocument("project");
Document document = editor.document();
// Get root element
Element root = editor.root();
// Create document with root element
editor.createDocument("project");
Element newRoot = editor.root(); // <project></project>
// Serialize to XML
String xml = editor.toXml();
// Pretty printing
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
Serialization
toXml()
Serializes the document to XML string with preserved formatting.
// Get document
Editor editor = new Editor();
editor.createDocument("project");
Document document = editor.document();
// Get root element
Element root = editor.root();
// Create document with root element
editor.createDocument("project");
Element newRoot = editor.root(); // <project></project>
// Serialize to XML
String xml = editor.toXml();
// Pretty printing
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
toXml(DomTripConfig config)
Serializes with custom configuration.
String xml = "<root><child>value</child></root>";
Editor editor = new Editor(Document.of(xml));
// Default serialization
String defaultXml = editor.toXml();
// Pretty printed
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
// Minimal output
String minimalXml = editor.toXml(DomTripConfig.minimal());
Pretty Printing
For pretty printing, use the configuration approach:
// Get document
Editor editor = new Editor();
editor.createDocument("project");
Document document = editor.document();
// Get root element
Element root = editor.root();
// Create document with root element
editor.createDocument("project");
Element newRoot = editor.root(); // <project></project>
// Serialize to XML
String xml = editor.toXml();
// Pretty printing
String prettyXml = editor.toXml(DomTripConfig.prettyPrint());
Element Operations
findElement(String name)
Finds the first element with the specified name in the document.
String xml = "<project><version>1.0</version><dependency><version>2.0</version></dependency></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// Find first element with name
Element version = root.child("version").orElse(null);
// Find all elements with name using descendants
List<Element> allVersions = root.descendants("version").toList();
// Add new child element
Element child = editor.addElement(root, "newChild");
// Remove element (if it exists)
Element toRemove = root.child("deprecated").orElse(null);
if (toRemove != null) {
editor.removeElement(toRemove);
}
// Get text content
String content = version != null ? version.textContent() : "";
Returns: The element, or null
if not found.
findElements(String name)
Finds all elements with the specified name.
String xml = "<project><version>1.0</version><dependency><version>2.0</version></dependency></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// Find first element with name
Element version = root.child("version").orElse(null);
// Find all elements with name using descendants
List<Element> allVersions = root.descendants("version").toList();
// Add new child element
Element child = editor.addElement(root, "newChild");
// Remove element (if it exists)
Element toRemove = root.child("deprecated").orElse(null);
if (toRemove != null) {
editor.removeElement(toRemove);
}
// Get text content
String content = version != null ? version.textContent() : "";
addElement(Element parent, String name)
Adds a new child element to the parent.
String xml = "<project><version>1.0</version><dependency><version>2.0</version></dependency></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// Find first element with name
Element version = root.child("version").orElse(null);
// Find all elements with name using descendants
List<Element> allVersions = root.descendants("version").toList();
// Add new child element
Element child = editor.addElement(root, "newChild");
// Remove element (if it exists)
Element toRemove = root.child("deprecated").orElse(null);
if (toRemove != null) {
editor.removeElement(toRemove);
}
// Get text content
String content = version != null ? version.textContent() : "";
Returns: The newly created element.
addElement(Element parent, String name, String textContent)
Adds a new child element with text content.
String xml = "<project></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
// Add element without content
Element child = editor.addElement(parent, "newChild");
// Add element with text content
Element version = editor.addElement(parent, "version", "1.0.0");
addElements(Element parent, Map<String, String> nameValuePairs)
Batch operation to add multiple child elements.
String xml = "<project></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
Map<String, String> properties = Map.of(
"groupId", "com.example",
"artifactId", "my-app",
"version", "1.0.0");
editor.addElements(parent, properties);
removeElement(Element element)
Removes an element from its parent.
String xml = "<project><version>1.0</version><dependency><version>2.0</version></dependency></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// Find first element with name
Element version = root.child("version").orElse(null);
// Find all elements with name using descendants
List<Element> allVersions = root.descendants("version").toList();
// Add new child element
Element child = editor.addElement(root, "newChild");
// Remove element (if it exists)
Element toRemove = root.child("deprecated").orElse(null);
if (toRemove != null) {
editor.removeElement(toRemove);
}
// Get text content
String content = version != null ? version.textContent() : "";
Text Content Operations
setTextContent(Element element, String content)
Sets the text content of an element.
String xml = "<project><version>1.0</version></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
Element version = root.child("version").orElse(null);
// Get text content
String content = version.textContent();
// Set text content
editor.setTextContent(version, "2.0.0");
getTextContent(Element element)
Gets the text content of an element.
String xml = "<project><version>1.0</version><dependency><version>2.0</version></dependency></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// Find first element with name
Element version = root.child("version").orElse(null);
// Find all elements with name using descendants
List<Element> allVersions = root.descendants("version").toList();
// Add new child element
Element child = editor.addElement(root, "newChild");
// Remove element (if it exists)
Element toRemove = root.child("deprecated").orElse(null);
if (toRemove != null) {
editor.removeElement(toRemove);
}
// Get text content
String content = version != null ? version.textContent() : "";
Attribute Operations
setAttribute(Element element, String name, String value)
Sets an attribute value with intelligent formatting preservation and inference.
Formatting Behavior:
- Existing attributes: Preserves original quote style and whitespace
- New attributes: Infers formatting from existing attributes on the element
String xml = "<dependency scope='test'></dependency>";
Editor editor = new Editor(Document.of(xml));
Element element = editor.root();
// For XML: <element attr1='existing' attr2="another"/>
editor.setAttribute(element, "attr1", "updated"); // Preserves single quotes
editor.setAttribute(element, "attr3", "new"); // Infers quote style from existing
// Remove attribute
editor.removeAttribute(element, "deprecated");
// Set multiple attributes
Map<String, String> attrs = Map.of(
"scope", "test",
"optional", "true");
editor.setAttributes(element, attrs);
// Get attribute value
String scopeValue = element.attribute("scope");
// Check if attribute exists
boolean hasOptional = element.hasAttribute("optional");
getAttribute(Element element, String name)
Gets an attribute value.
String xml = "<dependency scope='test'></dependency>";
Editor editor = new Editor(Document.of(xml));
Element element = editor.root();
// Get attribute value
String scope = element.attribute("scope");
// Set attribute value
editor.setAttribute(element, "optional", "true");
// Remove attribute
editor.removeAttribute(element, "scope");
removeAttribute(Element element, String name)
Removes an attribute.
String xml = "<dependency scope='test'></dependency>";
Editor editor = new Editor(Document.of(xml));
Element element = editor.root();
// For XML: <element attr1='existing' attr2="another"/>
editor.setAttribute(element, "attr1", "updated"); // Preserves single quotes
editor.setAttribute(element, "attr3", "new"); // Infers quote style from existing
// Remove attribute
editor.removeAttribute(element, "deprecated");
// Set multiple attributes
Map<String, String> attrs = Map.of(
"scope", "test",
"optional", "true");
editor.setAttributes(element, attrs);
// Get attribute value
String scopeValue = element.attribute("scope");
// Check if attribute exists
boolean hasOptional = element.hasAttribute("optional");
setAttributes(Element element, Map<String, String> attributes)
Sets multiple attributes at once with intelligent formatting.
String xml = "<dependency scope='test'></dependency>";
Editor editor = new Editor(Document.of(xml));
Element element = editor.root();
// For XML: <element attr1='existing' attr2="another"/>
editor.setAttribute(element, "attr1", "updated"); // Preserves single quotes
editor.setAttribute(element, "attr3", "new"); // Infers quote style from existing
// Remove attribute
editor.removeAttribute(element, "deprecated");
// Set multiple attributes
Map<String, String> attrs = Map.of(
"scope", "test",
"optional", "true");
editor.setAttributes(element, attrs);
// Get attribute value
String scopeValue = element.attribute("scope");
// Check if attribute exists
boolean hasOptional = element.hasAttribute("optional");
Advanced Attribute Formatting:
For fine-grained control over attribute formatting, you can work with Attribute
objects directly:
String xml = "<dependency scope='test'></dependency>";
Editor editor = new Editor(Document.of(xml));
Element element = editor.root();
// For XML: <element attr1='existing' attr2="another"/>
editor.setAttribute(element, "attr1", "updated"); // Preserves single quotes
editor.setAttribute(element, "attr3", "new"); // Infers quote style from existing
// Remove attribute
editor.removeAttribute(element, "deprecated");
// Set multiple attributes
Map<String, String> attrs = Map.of(
"scope", "test",
"optional", "true");
editor.setAttributes(element, attrs);
// Get attribute value
String scopeValue = element.attribute("scope");
// Check if attribute exists
boolean hasOptional = element.hasAttribute("optional");
Comment Operations
addComment(Element parent, String content)
Adds a comment as a child of the parent element.
String xml = "<project><version>1.0</version></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
Element version = parent.child("version").orElse(null);
// Add comment as child
editor.addComment(parent, " This is a comment ");
// Add comment using fluent API
editor.add().comment().to(parent).withContent(" Configuration section ").build();
addCommentBefore(Element element, String content)
Adds a comment before the specified element.
String xml = "<project><version>1.0</version></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
// Add comment as child of parent
editor.addComment(parent, " Configuration section ");
// Using fluent builder API for comments
editor.add().comment().to(parent).withContent(" End of configuration ").build();
addCommentAfter(Element element, String content)
Adds a comment after the specified element.
String xml = "<project><version>1.0</version></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
// Add comment as child of parent
editor.addComment(parent, " Configuration section ");
// Using fluent builder API for comments
editor.add().comment().to(parent).withContent(" End of configuration ").build();
Fluent Builder API
add()
Creates a fluent builder for adding nodes.
String xml = "<project></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
editor.add()
.element("dependency")
.to(parent)
.withAttribute("scope", "test")
.withText("content")
.build();
editor.add().comment().to(parent).withContent(" This is a comment ").build();
Configuration
config()
Gets the configuration used by this editor.
DomTripConfig config = DomTripConfig.prettyPrint();
Editor editor = new Editor(config);
// Get the configuration used by this editor
DomTripConfig usedConfig = editor.config();
Exception Handling
The Editor class throws specific exceptions for different error conditions:
ParseException
: Thrown when XML parsing failsInvalidXmlException
: Thrown for invalid editing operationsDomTripException
: Base exception for other DomTrip errors
try {
String malformedXml = "<root><unclosed>";
Editor editor = new Editor(Document.of(malformedXml));
// ... editing operations
} catch (DomTripException e) {
// Handle parsing/editing errors
System.err.println("XML error: " + e.getMessage());
}
Best Practices
1. Check for Null Returns
String xml = "<project><version>1.0</version></project>";
Editor editor = new Editor(Document.of(xml));
Element root = editor.root();
// ✅ Safe navigation using Optional
Optional<Element> element = root.child("optional");
element.ifPresent(el -> editor.setTextContent(el, "value"));
// ✅ Or use null check pattern
Element version = root.child("version").orElse(null);
if (version != null) {
editor.setTextContent(version, "updated");
}
2. Use Batch Operations
// ✅ Proper resource management
String xml = "<root><child>value</child></root>";
byte[] xmlBytes = xml.getBytes(StandardCharsets.UTF_8);
try (InputStream inputStream = new ByteArrayInputStream(xmlBytes);
OutputStream outputStream = new ByteArrayOutputStream()) {
Document doc = Document.of(inputStream);
doc.toXml(outputStream);
}
// ✅ Type-safe Charset objects
try (InputStream inputStream = new ByteArrayInputStream(xmlBytes);
OutputStream outputStream = new ByteArrayOutputStream()) {
Document doc = Document.of(inputStream, StandardCharsets.UTF_8);
doc.toXml(outputStream, StandardCharsets.UTF_16);
}
// ✅ Automatic detection
try (InputStream inputStream = new ByteArrayInputStream(xmlBytes)) {
Document doc = Document.of(inputStream);
Assertions.assertNotNull(doc);
}
3. Handle Exceptions Appropriately
// ✅ Specific exception handling
try {
String xmlContent = "<root><unclosed>";
Document doc = Document.of(xmlContent);
Editor editor = new Editor(doc);
} catch (DomTripException e) {
// Handle DomTrip errors (including parsing errors)
System.err.println("DomTrip error: " + e.getMessage());
}
Thread Safety
The Editor
class is not thread-safe. If you need to use an editor instance across multiple threads, you must provide external synchronization.
String xml = "<project></project>";
Editor editor = new Editor(Document.of(xml));
Element parent = editor.root();
// ✅ Thread-safe usage (conceptual example)
synchronized (editor) {
editor.addElement(parent, "child", "value");
String result = editor.toXml();
Assertions.assertTrue(result.contains("child"));
}
// ✅ Or use separate editor instances per thread
Editor editorForThread = new Editor(Document.of(xml));
editorForThread.addElement(editorForThread.root(), "thread-child", "value");