0
# DOM4J I/O Operations
1
2
DOM4J provides comprehensive input/output capabilities for reading and writing XML documents. This section covers the I/O classes in the `org.dom4j.io` package, including XML reading, writing, formatting, and integration with various XML processing APIs like SAX, DOM, and STAX.
3
4
## STAXEventReader - StAX Event Stream Reading
5
6
STAXEventReader reads DOM4J documents from StAX XMLEventReader streams, providing integration with Java's StAX API.
7
8
### Package and Import
9
```java { .api }
10
import org.dom4j.io.STAXEventReader;
11
import javax.xml.stream.XMLEventReader;
12
import javax.xml.stream.XMLStreamException;
13
import java.io.*;
14
```
15
16
### STAXEventReader Constructors
17
```java { .api }
18
public class STAXEventReader {
19
// Default constructor with default DocumentFactory
20
public STAXEventReader();
21
22
// Constructor with custom DocumentFactory
23
public STAXEventReader(DocumentFactory factory);
24
}
25
```
26
27
### Document Reading Methods
28
```java { .api }
29
public class STAXEventReader {
30
// Read from streams
31
public Document readDocument(InputStream is) throws XMLStreamException;
32
public Document readDocument(InputStream is, String systemId) throws XMLStreamException;
33
public Document readDocument(Reader reader) throws XMLStreamException;
34
public Document readDocument(Reader reader, String systemId) throws XMLStreamException;
35
36
// Read from StAX event reader
37
public Document readDocument(XMLEventReader eventReader) throws XMLStreamException;
38
39
// Read individual elements
40
public Element readElement(XMLEventReader eventReader) throws XMLStreamException;
41
42
// Configuration
43
public void setDocumentFactory(DocumentFactory documentFactory);
44
public DocumentFactory getDocumentFactory();
45
}
46
```
47
48
**Usage Examples:**
49
50
```java
51
import org.dom4j.io.STAXEventReader;
52
import javax.xml.stream.XMLInputFactory;
53
54
// Read from InputStream
55
STAXEventReader staxReader = new STAXEventReader();
56
Document document = staxReader.readDocument(inputStream);
57
58
// Read from XMLEventReader
59
XMLInputFactory factory = XMLInputFactory.newInstance();
60
XMLEventReader eventReader = factory.createXMLEventReader(inputStream);
61
Document doc = staxReader.readDocument(eventReader);
62
```
63
64
## STAXEventWriter - StAX Event Stream Writing
65
66
STAXEventWriter writes DOM4J documents and nodes to StAX XMLEventWriter streams.
67
68
### Package and Import
69
```java { .api }
70
import org.dom4j.io.STAXEventWriter;
71
import javax.xml.stream.XMLEventWriter;
72
import javax.xml.stream.XMLStreamException;
73
```
74
75
### STAXEventWriter Constructors
76
```java { .api }
77
public class STAXEventWriter {
78
// Constructor with XMLEventWriter
79
public STAXEventWriter(XMLEventWriter xmlEventWriter);
80
}
81
```
82
83
### Writing Methods
84
```java { .api }
85
public class STAXEventWriter {
86
// Write complete documents
87
public void writeDocument(Document document) throws XMLStreamException;
88
89
// Write individual nodes
90
public void writeNode(Node node) throws XMLStreamException;
91
public void writeElement(Element element) throws XMLStreamException;
92
93
// Write open/close element tags
94
public void writeStartElement(Element element) throws XMLStreamException;
95
public void writeEndElement(Element element) throws XMLStreamException;
96
97
// Configuration
98
public XMLEventWriter getXMLEventWriter();
99
}
100
```
101
102
## HTMLWriter - HTML Output Format
103
104
HTMLWriter extends XMLWriter to produce HTML-compliant output with HTML-specific formatting rules.
105
106
### Package and Import
107
```java { .api }
108
import org.dom4j.io.HTMLWriter;
109
import org.dom4j.io.OutputFormat;
110
```
111
112
### HTMLWriter Constructors
113
```java { .api }
114
public class HTMLWriter extends XMLWriter {
115
// Default constructor
116
public HTMLWriter();
117
118
// Writer-based constructors
119
public HTMLWriter(Writer writer);
120
public HTMLWriter(Writer writer, OutputFormat format);
121
122
// OutputStream-based constructors
123
public HTMLWriter(OutputStream out) throws UnsupportedEncodingException;
124
public HTMLWriter(OutputStream out, OutputFormat format) throws UnsupportedEncodingException;
125
}
126
```
127
128
### HTML-specific Features
129
```java { .api }
130
public class HTMLWriter extends XMLWriter {
131
// HTML element handling
132
protected boolean isElementSpaceSensitive(Element element);
133
protected void writeElementContent(Element element) throws IOException;
134
135
// HTML formatting options
136
public void setHtmlMode(boolean htmlMode);
137
public boolean isHtmlMode();
138
}
139
```
140
141
## XMLWriter - Formatted XML Output
142
143
XMLWriter is the primary class for writing DOM4J documents to XML format with configurable formatting options.
144
145
### Package and Import
146
```java { .api }
147
import org.dom4j.io.XMLWriter;
148
import org.dom4j.io.OutputFormat;
149
import java.io.*;
150
```
151
152
### XMLWriter Constructors
153
```java { .api }
154
public class XMLWriter {
155
// Default constructor - writes to System.out
156
public XMLWriter();
157
158
// Writer-based constructors
159
public XMLWriter(Writer writer);
160
public XMLWriter(Writer writer, OutputFormat format);
161
162
// OutputStream-based constructors
163
public XMLWriter(OutputStream out) throws UnsupportedEncodingException;
164
public XMLWriter(OutputStream out, OutputFormat format) throws UnsupportedEncodingException;
165
}
166
```
167
168
### Writing Methods
169
```java { .api }
170
public class XMLWriter {
171
// Write complete documents
172
public void write(Document doc) throws IOException;
173
174
// Write individual nodes
175
public void write(Element element) throws IOException;
176
public void write(Node node) throws IOException;
177
public void write(Attribute attribute) throws IOException;
178
public void write(CDATA cdata) throws IOException;
179
public void write(Comment comment) throws IOException;
180
public void write(Entity entity) throws IOException;
181
public void write(ProcessingInstruction pi) throws IOException;
182
public void write(Text text) throws IOException;
183
184
// Element streaming
185
public void writeOpen(Element element) throws IOException;
186
public void writeClose(Element element) throws IOException;
187
188
// Stream management
189
public void flush() throws IOException;
190
public void close() throws IOException;
191
}
192
```
193
194
### Configuration Methods
195
```java { .api }
196
public class XMLWriter {
197
// Format configuration
198
public OutputFormat getOutputFormat();
199
public void setOutputFormat(OutputFormat outputFormat);
200
201
// Entity reference handling
202
public boolean getResolveEntityRefs();
203
public void setResolveEntityRefs(boolean resolve);
204
}
205
```
206
207
### Using XMLWriter
208
```java { .api }
209
// Basic document writing
210
Document document = createSampleDocument();
211
212
// Write to file with default formatting
213
try (FileWriter fileWriter = new FileWriter("output.xml")) {
214
XMLWriter writer = new XMLWriter(fileWriter);
215
writer.write(document);
216
}
217
218
// Write to string
219
StringWriter stringWriter = new StringWriter();
220
XMLWriter xmlWriter = new XMLWriter(stringWriter);
221
xmlWriter.write(document);
222
String xmlString = stringWriter.toString();
223
224
// Write to output stream with encoding
225
try (FileOutputStream fos = new FileOutputStream("output.xml")) {
226
OutputFormat format = OutputFormat.createPrettyPrint();
227
format.setEncoding("UTF-8");
228
XMLWriter writer = new XMLWriter(fos, format);
229
writer.write(document);
230
}
231
232
// Write individual elements
233
Element rootElement = document.getRootElement();
234
try (PrintWriter pw = new PrintWriter("element.xml")) {
235
XMLWriter writer = new XMLWriter(pw, OutputFormat.createCompactFormat());
236
writer.write(rootElement);
237
}
238
239
// Streaming element writing for large documents
240
try (FileWriter fw = new FileWriter("large.xml")) {
241
XMLWriter writer = new XMLWriter(fw, OutputFormat.createPrettyPrint());
242
243
// Manual document structure
244
writer.writeOpen(DocumentHelper.createElement("catalog"));
245
246
for (Product product : products) {
247
Element productElement = createElement(product);
248
writer.write(productElement);
249
}
250
251
writer.writeClose(DocumentHelper.createElement("catalog"));
252
}
253
```
254
255
## OutputFormat - XML Formatting Configuration
256
257
OutputFormat controls how XML is formatted during output, including indentation, encoding, and various formatting options.
258
259
### Package and Import
260
```java { .api }
261
import org.dom4j.io.OutputFormat;
262
```
263
264
### OutputFormat Factory Methods
265
```java { .api }
266
public class OutputFormat {
267
// Predefined formats
268
public static OutputFormat createPrettyPrint();
269
public static OutputFormat createCompactFormat();
270
271
// Custom format
272
public OutputFormat();
273
public OutputFormat(String indent);
274
public OutputFormat(String indent, boolean newlines);
275
public OutputFormat(String indent, boolean newlines, String encoding);
276
}
277
```
278
279
### Declaration and Encoding Configuration
280
```java { .api }
281
public class OutputFormat {
282
// XML declaration
283
public boolean isSuppressDeclaration();
284
public void setSuppressDeclaration(boolean suppressDeclaration);
285
public boolean isNewLineAfterDeclaration();
286
public void setNewLineAfterDeclaration(boolean newLineAfterDeclaration);
287
288
// Encoding configuration
289
public String getEncoding();
290
public void setEncoding(String encoding);
291
public boolean isOmitEncoding();
292
public void setOmitEncoding(boolean omitEncoding);
293
}
294
```
295
296
### Indentation and Formatting
297
```java { .api }
298
public class OutputFormat {
299
// Indentation
300
public String getIndent();
301
public void setIndent(String indent);
302
public void setIndent(boolean doIndent);
303
304
// Line formatting
305
public boolean isNewlines();
306
public void setNewlines(boolean newlines);
307
public String getLineSeparator();
308
public void setLineSeparator(String separator);
309
310
// Element formatting
311
public boolean isExpandEmptyElements();
312
public void setExpandEmptyElements(boolean expandEmptyElements);
313
}
314
```
315
316
### Text Content Formatting
317
```java { .api }
318
public class OutputFormat {
319
// Text processing
320
public boolean isTrimText();
321
public void setTrimText(boolean trimText);
322
public boolean isPadText();
323
public void setPadText(boolean padText);
324
325
// Attribute formatting
326
public char getAttributeQuoteCharacter();
327
public void setAttributeQuoteCharacter(char quoteChar);
328
}
329
```
330
331
### HTML/XHTML Support
332
```java { .api }
333
public class OutputFormat {
334
// XHTML mode
335
public boolean isXHTML();
336
public void setXHTML(boolean doXHTML);
337
}
338
```
339
340
### Using OutputFormat
341
```java { .api }
342
// Pretty printed XML with indentation
343
OutputFormat prettyFormat = OutputFormat.createPrettyPrint();
344
prettyFormat.setEncoding("UTF-8");
345
prettyFormat.setIndent(" "); // 2-space indentation
346
prettyFormat.setNewLineAfterDeclaration(false);
347
348
// Compact format for minimal size
349
OutputFormat compactFormat = OutputFormat.createCompactFormat();
350
compactFormat.setSuppressDeclaration(true);
351
compactFormat.setTrimText(true);
352
353
// Custom formatting
354
OutputFormat customFormat = new OutputFormat();
355
customFormat.setIndent(true);
356
customFormat.setNewlines(true);
357
customFormat.setLineSeparator("\n");
358
customFormat.setEncoding("ISO-8859-1");
359
customFormat.setExpandEmptyElements(false); // Use <element/> instead of <element></element>
360
customFormat.setAttributeQuoteCharacter('\''); // Use single quotes for attributes
361
362
// XHTML formatting
363
OutputFormat xhtmlFormat = OutputFormat.createPrettyPrint();
364
xhtmlFormat.setXHTML(true);
365
xhtmlFormat.setExpandEmptyElements(false);
366
367
// Text processing configuration
368
OutputFormat textFormat = OutputFormat.createPrettyPrint();
369
textFormat.setTrimText(true); // Remove leading/trailing whitespace
370
textFormat.setPadText(false); // Don't add extra whitespace
371
372
// Use formats with XMLWriter
373
Document document = createDocument();
374
375
try (FileWriter writer = new FileWriter("pretty.xml")) {
376
XMLWriter xmlWriter = new XMLWriter(writer, prettyFormat);
377
xmlWriter.write(document);
378
}
379
380
try (FileWriter writer = new FileWriter("compact.xml")) {
381
XMLWriter xmlWriter = new XMLWriter(writer, compactFormat);
382
xmlWriter.write(document);
383
}
384
```
385
386
## SAXReader - Advanced Parsing Options
387
388
Extended coverage of SAXReader for advanced parsing scenarios beyond basic document creation.
389
390
### Advanced Configuration
391
```java { .api }
392
import org.dom4j.io.SAXReader;
393
import org.xml.sax.XMLReader;
394
import org.xml.sax.helpers.XMLReaderFactory;
395
396
// Custom XMLReader configuration
397
SAXReader reader = new SAXReader();
398
XMLReader xmlReader = reader.getXMLReader();
399
400
// Configure SAX features
401
xmlReader.setFeature("http://xml.org/sax/features/namespaces", true);
402
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
403
xmlReader.setFeature("http://xml.org/sax/features/validation", true);
404
405
// Configure SAX properties
406
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler);
407
xmlReader.setProperty("http://xml.org/sax/properties/declaration-handler", declHandler);
408
409
// Schema validation
410
xmlReader.setFeature("http://apache.org/xml/features/validation/schema", true);
411
xmlReader.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
412
"http://example.com/schema http://example.com/schema.xsd");
413
```
414
415
### Large Document Processing
416
```java { .api }
417
// Memory-efficient parsing for large documents
418
SAXReader reader = new SAXReader();
419
420
// Configure for memory efficiency
421
reader.setValidating(false); // Disable validation for speed
422
reader.setEntityResolver(null); // No external entity resolution
423
424
// Custom document factory for memory optimization
425
reader.setDocumentFactory(new DocumentFactory() {
426
@Override
427
public Element createElement(QName qname) {
428
// Return memory-optimized element implementation
429
return new LightweightElement(qname);
430
}
431
});
432
433
// Parse with progress monitoring
434
class ProgressEntityResolver implements EntityResolver {
435
private long bytesRead = 0;
436
437
@Override
438
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
439
// Monitor parsing progress
440
System.out.println("Processing entity: " + systemId);
441
return null;
442
}
443
}
444
445
reader.setEntityResolver(new ProgressEntityResolver());
446
```
447
448
## HTMLWriter - HTML-Specific Output
449
450
HTMLWriter extends XMLWriter for HTML-specific formatting requirements.
451
452
### Package and Import
453
```java { .api }
454
import org.dom4j.io.HTMLWriter;
455
```
456
457
### Using HTMLWriter
458
```java { .api }
459
// HTML-specific formatting
460
HTMLWriter htmlWriter = new HTMLWriter();
461
462
// HTML formatting automatically handles:
463
// - Empty elements (br, hr, img, etc.)
464
// - Case sensitivity
465
// - Entity encoding for HTML
466
467
Document htmlDocument = createHtmlDocument();
468
try (FileWriter writer = new FileWriter("output.html")) {
469
HTMLWriter htmlOut = new HTMLWriter(writer);
470
htmlOut.write(htmlDocument);
471
}
472
473
// Custom HTML formatting
474
OutputFormat htmlFormat = OutputFormat.createPrettyPrint();
475
htmlFormat.setXHTML(true); // XHTML compatibility
476
htmlFormat.setExpandEmptyElements(false); // <br/> instead of <br></br>
477
478
try (FileWriter writer = new FileWriter("xhtml.html")) {
479
HTMLWriter htmlOut = new HTMLWriter(writer, htmlFormat);
480
htmlOut.write(htmlDocument);
481
}
482
```
483
484
## SAXWriter - Generate SAX Events
485
486
SAXWriter writes DOM4J documents as SAX events, enabling integration with SAX-based processing pipelines.
487
488
### Package and Import
489
```java { .api }
490
import org.dom4j.io.SAXWriter;
491
import org.xml.sax.ContentHandler;
492
import org.xml.sax.helpers.DefaultHandler;
493
```
494
495
### Using SAXWriter
496
```java { .api }
497
// Write DOM4J document as SAX events
498
Document document = createDocument();
499
500
// Custom SAX content handler
501
ContentHandler handler = new DefaultHandler() {
502
@Override
503
public void startElement(String uri, String localName, String qName, Attributes attributes) {
504
System.out.println("Start element: " + qName);
505
}
506
507
@Override
508
public void endElement(String uri, String localName, String qName) {
509
System.out.println("End element: " + qName);
510
}
511
512
@Override
513
public void characters(char[] ch, int start, int length) {
514
String text = new String(ch, start, length).trim();
515
if (!text.isEmpty()) {
516
System.out.println("Text: " + text);
517
}
518
}
519
};
520
521
// Generate SAX events
522
SAXWriter saxWriter = new SAXWriter(handler);
523
saxWriter.write(document);
524
525
// Chain with SAX transformers
526
TransformerFactory factory = TransformerFactory.newInstance();
527
Templates template = factory.newTemplates(new StreamSource("transform.xsl"));
528
Transformer transformer = template.newTransformer();
529
530
SAXResult result = new SAXResult(handler);
531
SAXWriter chainedWriter = new SAXWriter(transformer);
532
chainedWriter.write(document);
533
```
534
535
## Dispatch Handlers for Event-Driven Processing
536
537
DOM4J provides dispatch handler classes for event-driven processing of large XML documents with memory efficiency.
538
539
### DispatchHandler - Element Event Processing
540
```java { .api }
541
import org.dom4j.io.DispatchHandler;
542
import org.dom4j.ElementHandler;
543
import org.dom4j.ElementPath;
544
545
public class DispatchHandler extends SAXContentHandler {
546
// Constructor
547
public DispatchHandler();
548
549
// Handler registration
550
public void addHandler(String path, ElementHandler handler);
551
public void removeHandler(String path);
552
public boolean containsHandler(String path);
553
554
// Handler access
555
public ElementHandler getHandler(String path);
556
public int getActiveHandlerCount();
557
558
// Path-based handlers
559
public void setDefaultHandler(ElementHandler handler);
560
public ElementHandler getDefaultHandler();
561
}
562
```
563
564
### PruningDispatchHandler - Memory-Efficient Processing
565
```java { .api }
566
import org.dom4j.io.PruningDispatchHandler;
567
568
public class PruningDispatchHandler extends DispatchHandler {
569
// Automatically prunes elements when no handlers are active
570
// Useful for processing large documents with minimal memory usage
571
572
// Constructor
573
public PruningDispatchHandler();
574
575
// Inherited methods from DispatchHandler
576
// Automatically detaches processed elements to save memory
577
}
578
```
579
580
**Usage Examples:**
581
582
```java
583
import org.dom4j.io.PruningDispatchHandler;
584
import org.dom4j.ElementHandler;
585
import org.dom4j.ElementPath;
586
587
// Memory-efficient processing of large documents
588
PruningDispatchHandler handler = new PruningDispatchHandler();
589
590
// Process specific elements and prune them
591
handler.addHandler("/catalog/product", new ElementHandler() {
592
public void onStart(ElementPath path) {
593
Element product = path.getCurrent();
594
System.out.println("Processing product: " + product.attributeValue("id"));
595
}
596
597
public void onEnd(ElementPath path) {
598
Element product = path.getCurrent();
599
// Process product data
600
processProduct(product);
601
// Element will be automatically pruned after this handler
602
}
603
});
604
605
// Use with SAXReader for large document processing
606
SAXReader reader = new SAXReader();
607
reader.setContentHandler(handler);
608
reader.read(largeXmlFile); // Processes with minimal memory usage
609
```
610
611
### ElementStack - Element Path Tracking
612
```java { .api }
613
import org.dom4j.io.ElementStack;
614
615
public class ElementStack {
616
// Constructor
617
public ElementStack();
618
619
// Stack operations
620
public void pushElement(Element element);
621
public Element popElement();
622
public Element peekElement();
623
624
// Path access
625
public ElementPath getPath();
626
public String getPathString();
627
public int getDepth();
628
629
// Path queries
630
public boolean matches(String pathPattern);
631
public Element getElementAtDepth(int depth);
632
}
633
```
634
635
## DOM Interoperability
636
637
DOM4J provides classes for converting between DOM4J and W3C DOM representations.
638
639
### DOMReader - W3C DOM to DOM4J
640
```java { .api }
641
import org.dom4j.io.DOMReader;
642
import org.w3c.dom.Document as W3CDocument;
643
644
// Convert W3C DOM to DOM4J
645
DOMReader domReader = new DOMReader();
646
647
// From W3C Document
648
W3CDocument w3cDocument = getW3CDocument();
649
Document dom4jDocument = domReader.read(w3cDocument);
650
651
// From W3C Element
652
org.w3c.dom.Element w3cElement = getW3CElement();
653
Document fragmentDoc = domReader.read(w3cElement);
654
```
655
656
### DOMWriter - DOM4J to W3C DOM
657
```java { .api }
658
import org.dom4j.io.DOMWriter;
659
import javax.xml.parsers.DocumentBuilderFactory;
660
661
// Convert DOM4J to W3C DOM
662
DOMWriter domWriter = new DOMWriter();
663
664
Document dom4jDocument = createDocument();
665
666
// Write to W3C Document
667
W3CDocument w3cDocument = domWriter.write(dom4jDocument);
668
669
// Write to existing W3C Document
670
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
671
factory.setNamespaceAware(true);
672
W3CDocument targetDocument = factory.newDocumentBuilder().newDocument();
673
W3CDocument result = domWriter.write(dom4jDocument, targetDocument);
674
675
// Write element to W3C Document
676
Element dom4jElement = dom4jDocument.getRootElement();
677
org.w3c.dom.Element w3cElement = domWriter.write(dom4jElement, targetDocument);
678
```
679
680
## JAXP Integration
681
682
DOM4J provides JAXP (Java API for XML Processing) integration classes for seamless interoperability with other XML processing APIs.
683
684
### DocumentInputSource - DOM4J to SAX InputSource
685
```java { .api }
686
import org.dom4j.io.DocumentInputSource;
687
import org.xml.sax.InputSource;
688
689
public class DocumentInputSource extends InputSource {
690
// Constructors
691
public DocumentInputSource();
692
public DocumentInputSource(Document document);
693
694
// Document access
695
public Document getDocument();
696
public void setDocument(Document document);
697
698
// InputSource methods (inherited)
699
public Reader getCharacterStream();
700
public void setCharacterStream(Reader characterStream);
701
}
702
```
703
704
### DocumentResult - JAXP Result for DOM4J
705
```java { .api }
706
import org.dom4j.io.DocumentResult;
707
import javax.xml.transform.Result;
708
709
public class DocumentResult implements Result {
710
// Constructors
711
public DocumentResult();
712
public DocumentResult(DocumentFactory factory);
713
714
// Result interface implementation
715
public void setSystemId(String systemId);
716
public String getSystemId();
717
718
// DOM4J specific methods
719
public Document getDocument();
720
public void setDocumentFactory(DocumentFactory factory);
721
public DocumentFactory getDocumentFactory();
722
}
723
```
724
725
### DocumentSource - JAXP Source for DOM4J
726
```java { .api }
727
import org.dom4j.io.DocumentSource;
728
import javax.xml.transform.Source;
729
730
public class DocumentSource implements Source {
731
// Constructors
732
public DocumentSource(Document document);
733
public DocumentSource(Node node);
734
735
// Source interface implementation
736
public void setSystemId(String systemId);
737
public String getSystemId();
738
739
// DOM4J specific methods
740
public Document getDocument();
741
public Node getNode();
742
}
743
```
744
745
## XML Pull Parser (XPP) Integration
746
747
DOM4J supports XML Pull Parser for efficient streaming XML processing.
748
749
### XPP3Reader - XPP to DOM4J
750
```java { .api }
751
import org.dom4j.io.XPP3Reader;
752
import org.xmlpull.v1.XmlPullParser;
753
import org.xmlpull.v1.XmlPullParserFactory;
754
755
// Create pull parser
756
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
757
factory.setNamespaceAware(true);
758
XmlPullParser parser = factory.newPullParser();
759
parser.setInput(new FileReader("input.xml"));
760
761
// Read with XPP3Reader
762
XPP3Reader xppReader = new XPP3Reader();
763
Document document = xppReader.read(parser);
764
765
// Custom document factory
766
xppReader.setDocumentFactory(customFactory);
767
Document customDoc = xppReader.read(parser);
768
```
769
770
## Advanced I/O Patterns
771
772
### Streaming Large Documents
773
```java { .api }
774
// Process large XML documents incrementally
775
public class StreamingXMLProcessor {
776
private final XMLWriter writer;
777
private final OutputFormat format;
778
779
public StreamingXMLProcessor(OutputStream output) throws IOException {
780
this.format = OutputFormat.createCompactFormat();
781
this.writer = new XMLWriter(output, format);
782
}
783
784
public void processLargeDocument(InputStream input) throws Exception {
785
SAXReader reader = new SAXReader();
786
787
// Custom content handler for streaming processing
788
reader.setContentHandler(new DefaultHandler() {
789
private Element currentElement;
790
private boolean inTargetElement = false;
791
792
@Override
793
public void startElement(String uri, String localName, String qName, Attributes attributes) {
794
if ("target".equals(localName)) {
795
inTargetElement = true;
796
currentElement = DocumentHelper.createElement(qName);
797
// Copy attributes
798
for (int i = 0; i < attributes.getLength(); i++) {
799
currentElement.addAttribute(attributes.getQName(i), attributes.getValue(i));
800
}
801
}
802
}
803
804
@Override
805
public void characters(char[] ch, int start, int length) {
806
if (inTargetElement && currentElement != null) {
807
currentElement.addText(new String(ch, start, length));
808
}
809
}
810
811
@Override
812
public void endElement(String uri, String localName, String qName) throws SAXException {
813
if ("target".equals(localName) && currentElement != null) {
814
try {
815
// Process and write element immediately
816
processElement(currentElement);
817
writer.write(currentElement);
818
writer.flush();
819
} catch (IOException e) {
820
throw new SAXException("Write error", e);
821
} finally {
822
currentElement = null;
823
inTargetElement = false;
824
}
825
}
826
}
827
});
828
829
reader.read(input);
830
}
831
832
private void processElement(Element element) {
833
// Custom processing logic
834
String processed = element.getText().toUpperCase();
835
element.setText(processed);
836
}
837
838
public void close() throws IOException {
839
writer.close();
840
}
841
}
842
```
843
844
### Parallel Document Processing
845
```java { .api }
846
// Process multiple documents concurrently
847
public class ParallelXMLProcessor {
848
private final ExecutorService executor;
849
private final OutputFormat format;
850
851
public ParallelXMLProcessor(int threads) {
852
this.executor = Executors.newFixedThreadPool(threads);
853
this.format = OutputFormat.createPrettyPrint();
854
}
855
856
public CompletableFuture<Void> processDocumentAsync(File inputFile, File outputFile) {
857
return CompletableFuture.runAsync(() -> {
858
try {
859
SAXReader reader = new SAXReader();
860
Document document = reader.read(inputFile);
861
862
// Process document
863
transformDocument(document);
864
865
// Write result
866
try (FileWriter writer = new FileWriter(outputFile)) {
867
XMLWriter xmlWriter = new XMLWriter(writer, format);
868
xmlWriter.write(document);
869
}
870
} catch (Exception e) {
871
throw new RuntimeException("Processing failed for " + inputFile, e);
872
}
873
}, executor);
874
}
875
876
public void processMultipleDocuments(List<File> inputFiles, File outputDirectory) {
877
List<CompletableFuture<Void>> futures = inputFiles.stream()
878
.map(file -> {
879
File outputFile = new File(outputDirectory, file.getName());
880
return processDocumentAsync(file, outputFile);
881
})
882
.collect(Collectors.toList());
883
884
// Wait for all to complete
885
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
886
}
887
888
private void transformDocument(Document document) {
889
// Custom transformation logic
890
List<Element> elements = document.selectNodes("//element");
891
elements.forEach(element -> element.addAttribute("processed", "true"));
892
}
893
894
public void shutdown() {
895
executor.shutdown();
896
}
897
}
898
```
899
900
### Memory-Efficient Processing
901
```java { .api }
902
// Custom document factory for memory optimization
903
public class MemoryEfficientDocumentFactory extends DocumentFactory {
904
@Override
905
public Element createElement(QName qname) {
906
return new MemoryEfficientElement(qname);
907
}
908
909
@Override
910
public Attribute createAttribute(Element owner, QName qname, String value) {
911
return new MemoryEfficientAttribute(qname, value);
912
}
913
}
914
915
// Lightweight element implementation
916
class MemoryEfficientElement extends DefaultElement {
917
public MemoryEfficientElement(QName qname) {
918
super(qname);
919
}
920
921
// Override methods to reduce memory usage
922
@Override
923
protected List<Node> createContentList() {
924
// Use memory-efficient list implementation
925
return new ArrayList<>(4); // Small initial capacity
926
}
927
928
@Override
929
protected List<Attribute> createAttributeList() {
930
return new ArrayList<>(2); // Most elements have few attributes
931
}
932
}
933
934
// Use memory-efficient factory
935
SAXReader reader = new SAXReader();
936
reader.setDocumentFactory(new MemoryEfficientDocumentFactory());
937
938
Document document = reader.read(largeXmlFile);
939
// Document uses less memory due to optimized implementations
940
```
941
942
DOM4J's I/O capabilities provide comprehensive support for reading and writing XML documents with fine-grained control over formatting, performance, and integration with other XML processing APIs. The flexible architecture allows for both simple operations and complex enterprise XML processing scenarios.