SAX Event Output
DomTrip can emit SAX ContentHandler events from a Document or Element tree, enabling
direct integration with SAX-based XML processing pipelines. This avoids the overhead of
serializing to a string and re-parsing when feeding domtrip documents into tools that consume
SAX events.
Note: Formatting preservation is intentionally lost at the SAX boundary since SAX events do not carry formatting metadata. The value is interoperability, not round-tripping through SAX.
Use Cases
| Scenario | How |
|---|---|
| Schema validation | Feed a domtrip document through a javax.xml.validation.Validator via SAXSource |
| XSLT transformation | Use a domtrip document as input to a javax.xml.transform.Transformer |
| Content pipelines | Integrate with SAX-based filters, indexers, or content extractors |
| Library interop | Bridge domtrip with libraries that only accept SAX input |
Basic Usage
Emitting Events to a ContentHandler
Document doc = Document.of(xml);
SAXOutputter outputter = new SAXOutputter();
outputter.output(doc, myContentHandler);
With a LexicalHandler
Pass a LexicalHandler to receive events for comments and CDATA sections:
SAXOutputter outputter = new SAXOutputter();
outputter.output(doc, contentHandler, lexicalHandler);
Outputting a Single Element
You can also emit events for just an element subtree. This does not emit
startDocument/endDocument events:
Element element = doc.root().childElement("child").orElseThrow();
outputter.output(element, contentHandler);
JAXP Integration with SAXSource
The DomTripSAXSource class provides a SAXSource adapter for seamless use with
JAXP APIs like Transformer and Validator.
XSLT Transformation
Document doc = Document.of(xml);
SAXSource source = DomTripSAXSource.of(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer(new StreamSource(xsltFile));
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
String result = writer.toString();
Schema Validation
Document doc = Document.of(xml);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(schemaFile);
Validator validator = schema.newValidator();
SAXSource source = DomTripSAXSource.of(doc);
validator.validate(source); // throws SAXException if invalid
Building a DOM Tree
Document doc = Document.of(xml);
SAXSource source = DomTripSAXSource.of(doc);
DOMResult result = new DOMResult();
TransformerFactory.newInstance().newTransformer().transform(source, result);
org.w3c.dom.Document domDoc = (org.w3c.dom.Document) result.getNode();
SAX Events Emitted
The outputter walks the domtrip tree and emits the following SAX events:
| domtrip Node | SAX Event(s) |
|---|---|
Document start |
startDocument() |
Document end |
endDocument() |
Element open |
startPrefixMapping() (for ns decls), startElement() |
Element close |
endElement(), endPrefixMapping() |
Text (regular) |
characters() |
Text (CDATA) |
startCDATA(), characters(), endCDATA() (via LexicalHandler) |
Comment |
comment() (via LexicalHandler) |
ProcessingInstruction |
processingInstruction() |
Namespace Handling
Namespace declarations on elements are emitted as startPrefixMapping/endPrefixMapping
pairs. The element's namespace URI is resolved and passed to startElement/endElement.
// Given: <root xmlns="http://example.com" xmlns:ns="http://ns.example.com">
// <ns:child/>
// </root>
//
// Events emitted:
// startPrefixMapping("", "http://example.com")
// startPrefixMapping("ns", "http://ns.example.com")
// startElement("http://example.com", "root", "root", ...)
// startElement("http://ns.example.com", "child", "ns:child", ...)
// endElement("http://ns.example.com", "child", "ns:child")
// endElement("http://example.com", "root", "root")
// endPrefixMapping("ns")
// endPrefixMapping("")
Reporting Namespace Declarations as Attributes
By default, xmlns and xmlns:prefix attributes are not included in the Attributes
parameter of startElement. Enable this to match the SAX namespace-prefixes feature:
SAXOutputter outputter = new SAXOutputter();
outputter.setReportNamespaceDeclarations(true);
outputter.output(doc, contentHandler);
This is also configurable via the DomTripXMLReader feature API:
DomTripXMLReader reader = new DomTripXMLReader(doc);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
DomTripXMLReader
The DomTripXMLReader implements org.xml.sax.XMLReader and is used internally by
DomTripSAXSource. You can also use it directly when you need fine-grained control
over features and properties.
Supported Features
| Feature URI | Default | Description |
|---|---|---|
http://xml.org/sax/features/namespaces |
true |
Always enabled, cannot be disabled |
http://xml.org/sax/features/namespace-prefixes |
false |
Report namespace declarations as attributes |
Supported Properties
| Property URI | Type | Description |
|---|---|---|
http://xml.org/sax/properties/lexical-handler |
LexicalHandler |
Handler for comments and CDATA events |
DomTripXMLReader reader = new DomTripXMLReader(doc);
reader.setContentHandler(myHandler);
reader.setProperty("http://xml.org/sax/properties/lexical-handler", myLexicalHandler);
reader.parse(new InputSource()); // InputSource is ignored; document was provided at construction
Classes
| Class | Purpose |
|---|---|
SAXOutputter |
Walks the tree and emits SAX events to a ContentHandler |
DomTripXMLReader |
XMLReader implementation for JAXP interop |
DomTripSAXSource |
SAXSource adapter wrapping a domtrip Document |
All classes are in the eu.maveniverse.domtrip.sax package.
See Also
- StAX Stream Reader -- pull-based StAX bridge for the same interoperability scenarios