Class Editor


  • public class Editor
    extends java.lang.Object
    High-level API for editing XML documents while preserving original formatting.

    The Editor class provides a convenient, user-friendly interface for parsing, modifying, and serializing XML documents. It combines the functionality of Parser, and Serializer to offer a complete XML editing solution with lossless formatting preservation.

    Capabilities:

    • Lossless Parsing - Preserves all formatting, whitespace, and comments
    • Simple Editing - Methods for common XML modifications
    • Format Preservation - Maintains original formatting for unchanged content
    • Flexible Output - Support for different serialization styles
    • Builder Pattern - Fluent API for document construction

    Basic Usage:

    
     // Parse existing XML
     Document doc = Document.of(xmlString);
     Editor editor = new Editor(doc);
    
     // Make modifications
     Element root = editor.root();
     editor.addElement(root, "newChild", "content");
     editor.setAttribute(root, "version", "2.0");  // Intelligently preserves formatting
    
     // Serialize with preserved formatting
     String result = editor.toXml();
     

    Intelligent Formatting Preservation:

    The Editor automatically preserves and infers appropriate formatting for new content:

    
     // For XML with aligned attributes:
     // <element attr1="value1"
     //          attr2="value2"/>
    
     editor.setAttribute(element, "attr3", "value3");
     // Result: <element attr1="value1"
     //                  attr2="value2"
     //                  attr3="value3"/>  // Maintains alignment
     

    Configuration Options:

    
     // Use custom configuration
     DomTripConfig config = DomTripConfig.prettyPrint()
         .withIndentation("  ")
         .withPreserveComments(true);
    
     Document doc = Document.of(xmlString);
     Editor editor = new Editor(doc, config);
    
     // Different output styles
     String pretty = editor.toXml(DomTripConfig.prettyPrint());
     String minimal = editor.toXml(DomTripConfig.minimal());
     

    Document Creation:

    
     // Create new document
     Editor editor = new Editor();
     editor.createDocument("root");
    
     // Build document structure
     Element root = editor.root();
     editor.addElement(root, "child", "value");
     

    Working with Existing Documents:

    
     // Use an existing Document object
     Document existingDoc = Document.of(xmlString);
     Editor editor = new Editor(existingDoc);
    
     // Or with custom configuration
     Editor editor = new Editor(existingDoc, DomTripConfig.prettyPrint());
    
     // Work with programmatically created documents
     Document doc = Document.withRootElement("project");
     Editor editor = new Editor(doc);
     
    See Also:
    Parser, Serializer, DomTripConfig, Document
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      static class  Editor.EditorCommentBuilder
      Builder for creating comments within the Editor context.
      static class  Editor.EditorElementBuilder
      Builder for creating and configuring elements within the Editor context.
      static class  Editor.EditorTextBuilder
      Builder for creating text nodes within the Editor context.
      static class  Editor.NodeBuilder
      Fluent builder for creating and adding nodes to the document.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      Editor.NodeBuilder add()
      Creates a fluent builder for adding nodes.
      void addBlankLineAfter​(Element element)  
      void addBlankLineBefore​(Element element)  
      Comment addComment​(ContainerNode parent, java.lang.String content)
      Adds a comment as a child of the specified parent
      Element addElement​(Element parent, QName qname)
      Adds a new element using a QName.
      Element addElement​(Element parent, QName qname, java.lang.String textContent)
      Adds a new element using a QName with text content.
      Element addElement​(Element parent, java.lang.String elementName)
      Adds a new element as a child of the specified parent element
      Element addElement​(Element parent, java.lang.String elementName, java.lang.String textContent)
      Adds a new element with text content
      void addElements​(Element parent, java.util.Map<java.lang.String,​java.lang.String> nameValuePairs)
      Batch operation to add multiple child elements with text content.
      void addQNameElements​(Element parent, java.util.Map<QName,​java.lang.String> qnameValuePairs)
      Batch operation to add multiple child elements with text content using QNames.
      Comment commentOutElement​(Element element)
      Comments out an element by wrapping it in an XML comment.
      Comment commentOutElements​(Element... elements)
      Comments out multiple elements as a single block comment.
      DomTripConfig config()
      Gets the configuration used by this editor.
      void createDocument​(java.lang.String rootElementName)
      Creates a new XML document with the specified root element.
      Document document()
      Gets the current XML document being edited.
      java.lang.String documentStats()
      Gets statistics about the document structure.
      Element insertElementAfter​(Element referenceElement, java.lang.String elementName)
      Inserts a new element after the specified reference element.
      Element insertElementAfter​(Element referenceElement, java.lang.String elementName, java.lang.String textContent)
      Inserts a new element with text content after the specified reference element.
      Element insertElementAt​(Element parent, int index, java.lang.String elementName)
      Inserts a new element at the specified position within the parent.
      Element insertElementAt​(Element parent, int index, java.lang.String elementName, java.lang.String textContent)
      Inserts a new element with text content at the specified position.
      Element insertElementBefore​(Element referenceElement, java.lang.String elementName)
      Inserts a new element before the specified reference element.
      Element insertElementBefore​(Element referenceElement, java.lang.String elementName, java.lang.String textContent)
      Inserts a new element with text content before the specified reference element.
      boolean isWellFormed()
      Validates that the document is well-formed.
      boolean removeAttribute​(Element element, java.lang.String name)
      Remove the specified attribute from the provided element.
      boolean removeElement​(Element element)
      Removes an element from its parent with intelligent whitespace handling.
      Element root()
      Gets the root element of the document.
      java.util.List<Element> select​(java.lang.String expression)
      Evaluates a mini-XPath expression against the document root and returns all matching elements.
      java.util.Optional<Element> selectFirst​(java.lang.String expression)
      Evaluates a mini-XPath expression against the document root and returns the first match.
      void setAttribute​(Element element, java.lang.String name, java.lang.String value)
      Adds or updates an attribute on an element with intelligent formatting preservation.
      void setAttributes​(Element element, java.util.Map<java.lang.String,​java.lang.String> attributes)
      Batch operation to set multiple attributes on an element.
      void setTextContent​(Element element, java.lang.String content)
      Sets the text content of an element, preserving the node type (CDATA vs plain text) and surrounding whitespace of the existing content.
      java.lang.String toXml()
      Serializes the current document back to XML
      java.lang.String toXml​(DomTripConfig config)
      Serializes the document to XML string with custom configuration.
      java.lang.String toXmlPretty()
      Serializes with pretty printing
      Element uncommentElement​(Comment comment)
      Uncomments a previously commented element by parsing the comment content back to XML.
      DomTripVisitor.Action walk​(DomTripVisitor visitor)
      Walks the entire document tree using the given visitor.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • Editor

        public Editor()
      • Editor

        public Editor​(Document document)
        Creates a new editor with an existing Document.

        This constructor allows you to create an Editor instance from an existing Document object, which is useful when you already have a parsed document or when working with documents created programmatically.

        The editor will use default configuration settings. If you need custom configuration, use Editor(Document, DomTripConfig) instead.

        Usage Examples:

        
         // Working with an existing document
         Document existingDoc = Document.of(xmlString);
         Editor editor = new Editor(existingDoc);
        
         // Working with a programmatically created document
         Document doc = Document.withRootElement("project");
         Editor editor = new Editor(doc);
        
         // Continue editing
         Element root = editor.root();
         editor.addElement(root, "version", "1.0");
         
        Parameters:
        document - the existing Document to edit, may be null
        See Also:
        Editor(Document, DomTripConfig), Document
      • Editor

        public Editor​(Document document,
                      DomTripConfig config)
        Creates a new editor with an existing Document and custom configuration.

        This constructor allows you to create an Editor instance from an existing Document object with custom configuration settings. This is useful when you need specific serialization or formatting behavior for an existing document.

        Usage Examples:

        
         // Working with existing document and custom config
         Document existingDoc = Document.of(xmlString);
         DomTripConfig config = DomTripConfig.prettyPrint()
             .withIndentString("  ")
             .withCommentPreservation(true);
         Editor editor = new Editor(existingDoc, config);
        
         // Working with builder-created document
         Document doc = Document.withRootElement("maven");
         Editor editor = new Editor(doc, DomTripConfig.minimal());
         
        Parameters:
        document - the existing Document to edit, may be null
        config - the configuration to use, or null for default configuration
        See Also:
        Editor(Document), DomTripConfig
    • Method Detail

      • document

        public Document document()
        Gets the current XML document being edited.
        Returns:
        the current Document, or null if no document is loaded
      • toXml

        public java.lang.String toXml()
        Serializes the current document back to XML
      • toXmlPretty

        public java.lang.String toXmlPretty()
        Serializes with pretty printing
      • addElement

        public Element addElement​(Element parent,
                                  QName qname)
                           throws DomTripException
        Adds a new element using a QName.
        Parameters:
        parent - the parent element
        qname - the QName for the new element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the element cannot be added
      • addElement

        public Element addElement​(Element parent,
                                  QName qname,
                                  java.lang.String textContent)
                           throws DomTripException
        Adds a new element using a QName with text content.
        Parameters:
        parent - the parent element
        qname - the QName for the new element
        textContent - the text content for the element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the element cannot be added
      • removeElement

        public boolean removeElement​(Element element)
        Removes an element from its parent with intelligent whitespace handling.

        This method removes an element while preserving proper formatting by intelligently handling surrounding whitespace text nodes:

        • If removing the first element and there's no line before, removes following blank lines
        • If removing the last element and there's no line after, removes blank lines before
        • If removing a middle element, removes any following blank lines
        Parameters:
        element - the element to remove
        Returns:
        true if the element was successfully removed, false otherwise
      • setAttribute

        public void setAttribute​(Element element,
                                 java.lang.String name,
                                 java.lang.String value)
                          throws DomTripException
        Adds or updates an attribute on an element with intelligent formatting preservation.

        When updating an existing attribute, this method preserves the original formatting. When adding a new attribute, it analyzes existing attributes on the element to infer appropriate formatting patterns (quote style and whitespace alignment).

        Formatting Inference for New Attributes:

        • Quote Style - Uses the most common quote style from existing attributes
        • Whitespace - Analyzes existing attribute spacing patterns for alignment
        • Multi-line Support - Preserves newline-based attribute alignment

        Examples:

        
         // XML with aligned attributes:
         // <element attr1="value1"
         //          attr2="value2"/>
        
         editor.setAttribute(element, "attr3", "value3");
         // Result: <element attr1="value1"
         //                  attr2="value2"
         //                  attr3="value3"/>
         
        Parameters:
        element - the element to modify
        name - the attribute name
        value - the attribute value
        Throws:
        DomTripException - if element is null or name is invalid
        See Also:
        setAttributes(Element, Map)
      • removeAttribute

        public boolean removeAttribute​(Element element,
                                       java.lang.String name)
        Remove the specified attribute from the provided element.
        Parameters:
        element - the element from which to remove the attribute; if `null` no action is taken
        name - the name of the attribute to remove; if `null` no action is taken
        Returns:
        `true` if the attribute existed on the element and was removed, `false` otherwise
      • setTextContent

        public void setTextContent​(Element element,
                                   java.lang.String content)
                            throws DomTripException
        Sets the text content of an element, preserving the node type (CDATA vs plain text) and surrounding whitespace of the existing content.

        If the element currently contains a CDATA section, the replacement text will also be wrapped in CDATA. If the element contains plain text, the replacement will be plain text. Surrounding whitespace patterns are preserved in both cases.

        When the element contains mixed content (multiple non-whitespace text nodes), only the first non-whitespace text node is updated and extra non-whitespace text nodes are removed.

        Examples:

        
         // CDATA preservation:
         // Before: <version><![CDATA[1.0]]></version>
         editor.setTextContent(versionElement, "2.0");
         // After:  <version><![CDATA[2.0]]></version>
        
         // Plain text:
         // Before: <version>1.0</version>
         editor.setTextContent(versionElement, "2.0");
         // After:  <version>2.0</version>
         
        Parameters:
        element - the element whose text content to set
        content - the new text content
        Throws:
        DomTripException - if element is null
      • commentOutElement

        public Comment commentOutElement​(Element element)
                                  throws DomTripException
        Comments out an element by wrapping it in an XML comment.

        This method replaces the element with a comment containing the element's XML representation. The original element is preserved within the comment and can be restored using uncommentElement(Comment).

        Example:

        
         // Before: <dependency><groupId>junit</groupId></dependency>
         editor.commentOutElement(dependencyElement);
         // After: <!-- <dependency><groupId>junit</groupId></dependency> -->
         
        Parameters:
        element - the element to comment out
        Returns:
        the comment that replaced the element
        Throws:
        DomTripException - if the element cannot be commented out
      • commentOutElements

        public Comment commentOutElements​(Element... elements)
                                   throws DomTripException
        Comments out multiple elements as a single block comment.

        This method wraps multiple elements in a single XML comment block. All elements must have the same parent. The elements are replaced with a single comment containing all their XML representations.

        Example:

        
         // Before: <dep1/><dep2/><dep3/>
         editor.commentOutElements(dep1, dep2, dep3);
         // After: <!-- <dep1/><dep2/><dep3/> -->
         
        Parameters:
        elements - the elements to comment out as a block
        Returns:
        the comment that replaced the elements
        Throws:
        DomTripException - if the elements cannot be commented out
      • uncommentElement

        public Element uncommentElement​(Comment comment)
                                 throws DomTripException
        Uncomments a previously commented element by parsing the comment content back to XML.

        This method attempts to parse the content of a comment as XML and replace the comment with the parsed elements. This is the reverse operation of commentOutElement(Element) and commentOutElements(Element...).

        Example:

        
         // Before: <!-- <dependency><groupId>junit</groupId></dependency> -->
         Element restored = editor.uncommentElement(comment);
         // After: <dependency><groupId>junit</groupId></dependency>
         
        Parameters:
        comment - the comment containing XML to uncomment
        Returns:
        the first element that was restored, or null if no elements were found
        Throws:
        DomTripException - if the comment content cannot be parsed as XML
      • insertElementAt

        public Element insertElementAt​(Element parent,
                                       int index,
                                       java.lang.String elementName)
                                throws DomTripException
        Inserts a new element at the specified position within the parent.

        This method provides precise control over element positioning by allowing insertion at a specific index. The index is 0-based, where 0 inserts at the beginning and parent.nodeCount() appends at the end.

        Example:

        
         // Insert at position 1 (second position)
         Element newElement = editor.insertElementAt(parent, 1, "newChild");
         
        Parameters:
        parent - the parent element to insert into
        index - the position to insert at (0-based)
        elementName - the name of the new element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • insertElementAt

        public Element insertElementAt​(Element parent,
                                       int index,
                                       java.lang.String elementName,
                                       java.lang.String textContent)
                                throws DomTripException
        Inserts a new element with text content at the specified position.
        Parameters:
        parent - the parent element to insert into
        index - the position to insert at (0-based)
        elementName - the name of the new element
        textContent - the text content for the element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • insertElementBefore

        public Element insertElementBefore​(Element referenceElement,
                                           java.lang.String elementName)
                                    throws DomTripException
        Inserts a new element before the specified reference element.

        This method creates a new element and inserts it immediately before the reference element in the parent's child list. Both elements will have the same parent after insertion.

        Example:

        
         // Insert before existing element
         Element newElement = editor.insertElementBefore(existingElement, "newChild");
         
        Parameters:
        referenceElement - the element to insert before
        elementName - the name of the new element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • insertElementBefore

        public Element insertElementBefore​(Element referenceElement,
                                           java.lang.String elementName,
                                           java.lang.String textContent)
                                    throws DomTripException
        Inserts a new element with text content before the specified reference element.
        Parameters:
        referenceElement - the element to insert before
        elementName - the name of the new element
        textContent - the text content for the element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • insertElementAfter

        public Element insertElementAfter​(Element referenceElement,
                                          java.lang.String elementName)
                                   throws DomTripException
        Inserts a new element after the specified reference element.

        This method creates a new element and inserts it immediately after the reference element in the parent's child list. Both elements will have the same parent after insertion.

        Example:

        
         // Insert after existing element
         Element newElement = editor.insertElementAfter(existingElement, "newChild");
         
        Parameters:
        referenceElement - the element to insert after
        elementName - the name of the new element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • insertElementAfter

        public Element insertElementAfter​(Element referenceElement,
                                          java.lang.String elementName,
                                          java.lang.String textContent)
                                   throws DomTripException
        Inserts a new element with text content after the specified reference element.
        Parameters:
        referenceElement - the element to insert after
        elementName - the name of the new element
        textContent - the text content for the element
        Returns:
        the newly created element
        Throws:
        DomTripException - if the insertion fails
      • createDocument

        public void createDocument​(java.lang.String rootElementName)
                            throws DomTripException
        Creates a new XML document with the specified root element.

        This method creates a new document with a default XML declaration and the specified root element. Any existing document will be replaced.

        Parameters:
        rootElementName - the name of the root element
        Throws:
        DomTripException - if the root element name is null or empty
      • root

        public Element root()
                     throws DomTripException
        Gets the root element of the document.
        Returns:
        the root element of the document
        Throws:
        java.lang.IllegalStateException - if no document is loaded or document has no root element
        DomTripException
      • select

        public java.util.List<Element> select​(java.lang.String expression)
        Evaluates a mini-XPath expression against the document root and returns all matching elements.

        Examples:

        
         List<Element> deps = editor.select("//dependency");
         List<Element> testDeps = editor.select("//dependency[@scope='test']");
         
        Parameters:
        expression - the mini-XPath expression
        Returns:
        a list of matching elements, never null
        Throws:
        DomTripException - if the expression is invalid or no document is loaded
        Since:
        1.3.0
        See Also:
        XPathExpression
      • selectFirst

        public java.util.Optional<Element> selectFirst​(java.lang.String expression)
        Evaluates a mini-XPath expression against the document root and returns the first match.

        Examples:

        
         Optional<Element> dep = editor.selectFirst("//dependency[@scope='test']");
         Optional<Element> ver = editor.selectFirst("project/version");
         
        Parameters:
        expression - the mini-XPath expression
        Returns:
        an Optional containing the first matching element, or empty if none found
        Throws:
        DomTripException - if the expression is invalid or no document is loaded
        Since:
        1.3.0
        See Also:
        XPathExpression
      • walk

        public DomTripVisitor.Action walk​(DomTripVisitor visitor)
        Walks the entire document tree using the given visitor.

        This is a convenience method equivalent to document().accept(visitor).

        Parameters:
        visitor - the visitor to use for traversal
        Returns:
        the action indicating whether traversal completed or was stopped
        Throws:
        java.lang.IllegalArgumentException - if visitor is null
        DomTripException - if no document is loaded
        Since:
        1.3.0
        See Also:
        DomTripVisitor, Node.accept(DomTripVisitor)
      • isWellFormed

        public boolean isWellFormed()
        Validates that the document is well-formed.

        Performs basic well-formedness validation including checking for the presence of a root element. Additional validation rules may be added in the future.

        Returns:
        true if the document is well-formed, false otherwise
      • documentStats

        public java.lang.String documentStats()
        Gets statistics about the document structure.

        Returns a formatted string containing counts of different node types in the document including elements, text nodes, comments, and total nodes.

        Returns:
        a string containing document statistics
      • setAttributes

        public void setAttributes​(Element element,
                                  java.util.Map<java.lang.String,​java.lang.String> attributes)
                           throws DomTripException
        Batch operation to set multiple attributes on an element.

        Sets multiple attributes at once with intelligent formatting preservation. Each attribute uses inferred formatting based on existing patterns on the element.

        Parameters:
        element - the element to modify
        attributes - a map of attribute names to values
        Throws:
        DomTripException - if any attribute operation is invalid
      • addElements

        public void addElements​(Element parent,
                                java.util.Map<java.lang.String,​java.lang.String> nameValuePairs)
                         throws DomTripException
        Batch operation to add multiple child elements with text content.

        Creates multiple child elements at once, each with the specified text content. This is more efficient than adding elements individually.

        Parameters:
        parent - the parent element to add children to
        nameValuePairs - a map of element names to text content values
        Throws:
        DomTripException - if any element creation is invalid
      • addQNameElements

        public void addQNameElements​(Element parent,
                                     java.util.Map<QName,​java.lang.String> qnameValuePairs)
                              throws DomTripException
        Batch operation to add multiple child elements with text content using QNames.
        Parameters:
        parent - the parent element
        qnameValuePairs - a map of QNames to text content
        Throws:
        DomTripException - if any element cannot be added
      • toXml

        public java.lang.String toXml​(DomTripConfig config)
        Serializes the document to XML string with custom configuration.

        Uses the provided configuration instead of the editor's default configuration for this serialization operation only.

        Parameters:
        config - the configuration to use for serialization
        Returns:
        the XML string, or empty string if no document is loaded
      • config

        public DomTripConfig config()
        Gets the configuration used by this editor.
        Returns:
        the DomTripConfig instance used by this editor
      • addBlankLineBefore

        public void addBlankLineBefore​(Element element)
      • addBlankLineAfter

        public void addBlankLineAfter​(Element element)