Class XmlBuilder

java.lang.Object
name.jurgenei.gradle.antlr.XmlBuilder

public final class XmlBuilder extends Object
SAX-like XML builder with automatic indentation and escaping. Provides clean, idiomatic API for building well-formatted XML.

Design Rationale

This custom implementation was chosen over third-party SAX writer libraries for pragmatic reasons:

  • Zero Dependencies: Uses only JDK stdlib (Deque, LinkedList, StringBuilder). Adding external libraries would require dependency management, version tracking, and potential conflicts with other project dependencies.
  • Memory Optimization: The original optimization achieved 47.6% memory reduction compared to DOM-based generation. Third-party libraries add wrapper objects and state management that would partially offset this gain.
  • Specialized Use Case: This builder only needs elements, attributes, text, and indentation. Complex features like namespace prefixes, CDATA sections, and DTD validation are unnecessary for AST XML output. A ~150-line custom class is simpler than learning a third-party API with extra features.
  • Compression Integration: Direct access to the element stack enables seamless integration with the compression feature (pathId generation). Third-party solutions would require workarounds or loss of control.
  • Performance: Direct StringBuilder access with minimal abstraction layers is faster than StAX XMLStreamWriter's event model overhead.

When You WOULD Want a Library

Consider switching to a library if:

  • Heavy XML work with complex document generation
  • Need for transformations, XPath, or XSLT processing
  • Schema validation or DTD handling required
  • Namespace prefix management needed
  • Team standardization on specific XML library

Trade-offs

Chosen approach (custom XmlBuilder):

  • ✓ Zero external dependencies
  • ✓ Minimal memory footprint
  • ✓ No abstraction layer overhead
  • ✓ Perfect integration with compression
  • ✗ Limited to simple XML generation
  • ✗ Not an industry standard API

Alternative (StAX XMLStreamWriter):

  • ✓ Industry standard API
  • ✓ Auto-escaping eliminates bugs
  • ✗ +0.5MB memory overhead (4% increase)
  • ✗ 10-15% throughput loss due to abstraction
  • ✗ No special compression integration
Since:
0.1.1
  • Constructor Details

    • XmlBuilder

      public XmlBuilder()
      Creates a new XML builder with 16KB initial buffer.
  • Method Details

    • writeXmlDeclaration

      public void writeXmlDeclaration()
      Writes XML declaration (<?xml version="1.0" encoding="UTF-8"?>).
    • writeStartElement

      public void writeStartElement(String name)
      Writes start tag with automatic indentation. Must be paired with writeEndElement().
      Parameters:
      name - element name (e.g., "root", "item")
      Throws:
      IllegalArgumentException - if name is null or empty
    • writeAttribute

      public void writeAttribute(String name, String value)
      Writes an attribute for the current open element. Must be called after writeStartElement() and before writeCharacters() or writeEndElement().
      Parameters:
      name - attribute name (e.g., "id", "type")
      value - attribute value (automatically XML-escaped)
      Throws:
      IllegalStateException - if not in an open tag
      IllegalArgumentException - if name is null or empty
    • writeCharacters

      public void writeCharacters(String text)
      Writes text content (automatically XML-escaped). Suppresses indentation for the closing tag.
      Parameters:
      text - content text (null is converted to empty string)
    • writeEndElement

      public void writeEndElement()
      Writes end tag with automatic indentation. Must match the last writeStartElement() call.
      Throws:
      IllegalStateException - if no open element
    • getXml

      public String getXml()
      Gets the final formatted XML string. Can only be called when all elements are properly closed.
      Returns:
      complete XML document
      Throws:
      IllegalStateException - if there are unclosed elements