KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > io > STAXEventWriter


1 /*
2  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3  *
4  * This software is open source.
5  * See the bottom of this file for the licence.
6  */

7
8 package org.dom4j.io;
9
10 import java.io.File JavaDoc;
11 import java.io.FileWriter JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.io.StringWriter JavaDoc;
15 import java.io.Writer JavaDoc;
16 import java.util.Iterator JavaDoc;
17
18 import javax.xml.namespace.QName JavaDoc;
19 import javax.xml.stream.XMLEventFactory;
20 import javax.xml.stream.XMLOutputFactory;
21 import javax.xml.stream.XMLStreamException;
22 import javax.xml.stream.events.Characters;
23 import javax.xml.stream.events.DTD;
24 import javax.xml.stream.events.EndDocument;
25 import javax.xml.stream.events.EndElement;
26 import javax.xml.stream.events.EntityReference;
27 import javax.xml.stream.events.ProcessingInstruction;
28 import javax.xml.stream.events.StartDocument;
29 import javax.xml.stream.events.StartElement;
30 import javax.xml.stream.util.XMLEventConsumer;
31
32 import org.dom4j.Attribute;
33 import org.dom4j.Branch;
34 import org.dom4j.CDATA;
35 import org.dom4j.Comment;
36 import org.dom4j.Document;
37 import org.dom4j.DocumentType;
38 import org.dom4j.Element;
39 import org.dom4j.Entity;
40 import org.dom4j.Namespace;
41 import org.dom4j.Node;
42 import org.dom4j.Text;
43
44 /**
45  * Writes DOM4J {@link Node}s to a StAX event stream. In addition the
46  * <code>createXXX</code> methods are provided to directly create STAX events
47  * from DOM4J nodes.
48  *
49  * @author Christian Niles
50  */

51 public class STAXEventWriter {
52     /** The event stream to which events are written. */
53     private XMLEventConsumer consumer;
54
55     /** The event factory used to construct events. */
56     private XMLEventFactory factory = XMLEventFactory.newInstance();
57
58     private XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
59
60     public STAXEventWriter() {
61     }
62
63     /**
64      * Constructs a <code>STAXEventWriter</code> that writes events to the
65      * provided file.
66      *
67      * @param file
68      * The file to which events will be written.
69      *
70      * @throws XMLStreamException
71      * If an error occurs creating an event writer from the file.
72      * @throws IOException
73      * If an error occurs openin the file for writing.
74      */

75     public STAXEventWriter(File JavaDoc file) throws XMLStreamException, IOException JavaDoc {
76         consumer = outputFactory.createXMLEventWriter(new FileWriter JavaDoc(file));
77     }
78
79     /**
80      * Constructs a <code>STAXEventWriter</code> that writes events to the
81      * provided character stream.
82      *
83      * @param writer
84      * The character stream to which events will be written.
85      *
86      * @throws XMLStreamException
87      * If an error occurs constructing an event writer from the
88      * character stream.
89      */

90     public STAXEventWriter(Writer JavaDoc writer) throws XMLStreamException {
91         consumer = outputFactory.createXMLEventWriter(writer);
92     }
93
94     /**
95      * Constructs a <code>STAXEventWriter</code> that writes events to the
96      * provided stream.
97      *
98      * @param stream
99      * The output stream to which events will be written.
100      *
101      * @throws XMLStreamException
102      * If an error occurs constructing an event writer from the
103      * stream.
104      */

105     public STAXEventWriter(OutputStream JavaDoc stream) throws XMLStreamException {
106         consumer = outputFactory.createXMLEventWriter(stream);
107     }
108
109     /**
110      * Constructs a <code>STAXEventWriter</code> that writes events to the
111      * provided event stream.
112      *
113      * @param consumer
114      * The event stream to which events will be written.
115      */

116     public STAXEventWriter(XMLEventConsumer consumer) {
117         this.consumer = consumer;
118     }
119
120     /**
121      * Returns a reference to the underlying event consumer to which events are
122      * written.
123      *
124      * @return The underlying event consumer to which events are written.
125      */

126     public XMLEventConsumer getConsumer() {
127         return consumer;
128     }
129
130     /**
131      * Sets the underlying event consumer to which events are written.
132      *
133      * @param consumer
134      * The event consumer to which events should be written.
135      */

136     public void setConsumer(XMLEventConsumer consumer) {
137         this.consumer = consumer;
138     }
139
140     /**
141      * Returns a reference to the event factory used to construct STAX events.
142      *
143      * @return The event factory used to construct STAX events.
144      */

145     public XMLEventFactory getEventFactory() {
146         return factory;
147     }
148
149     /**
150      * Sets the event factory used to construct STAX events.
151      *
152      * @param eventFactory
153      * The new event factory.
154      */

155     public void setEventFactory(XMLEventFactory eventFactory) {
156         this.factory = eventFactory;
157     }
158
159     /**
160      * Writes a DOM4J {@link Node}to the stream. This method is simply a
161      * gateway to the overloaded methods such as {@link#writeElement(Element)}.
162      *
163      * @param n
164      * The DOM4J {@link Node}to write to the stream.
165      *
166      * @throws XMLStreamException
167      * If an error occurs writing to the stream.
168      */

169     public void writeNode(Node n) throws XMLStreamException {
170         switch (n.getNodeType()) {
171             case Node.ELEMENT_NODE:
172                 writeElement((Element) n);
173
174                 break;
175
176             case Node.TEXT_NODE:
177                 writeText((Text) n);
178
179                 break;
180
181             case Node.ATTRIBUTE_NODE:
182                 writeAttribute((Attribute) n);
183
184                 break;
185
186             case Node.NAMESPACE_NODE:
187                 writeNamespace((Namespace) n);
188
189                 break;
190
191             case Node.COMMENT_NODE:
192                 writeComment((Comment) n);
193
194                 break;
195
196             case Node.CDATA_SECTION_NODE:
197                 writeCDATA((CDATA) n);
198
199                 break;
200
201             case Node.PROCESSING_INSTRUCTION_NODE:
202                 writeProcessingInstruction((org.dom4j.ProcessingInstruction) n);
203
204                 break;
205
206             case Node.ENTITY_REFERENCE_NODE:
207                 writeEntity((Entity) n);
208
209                 break;
210
211             case Node.DOCUMENT_NODE:
212                 writeDocument((Document) n);
213
214                 break;
215
216             case Node.DOCUMENT_TYPE_NODE:
217                 writeDocumentType((DocumentType) n);
218
219                 break;
220
221             default:
222                 throw new XMLStreamException("Unsupported DOM4J Node: " + n);
223         }
224     }
225
226     /**
227      * Writes each child node within the provided {@link Branch}instance. This
228      * method simply iterates through the {@link Branch}'s nodes and calls
229      * {@link #writeNode(Node)}.
230      *
231      * @param branch
232      * The node whose children will be written to the stream.
233      *
234      * @throws XMLStreamException
235      * If an error occurs writing to the stream.
236      */

237     public void writeChildNodes(Branch branch) throws XMLStreamException {
238         for (int i = 0, s = branch.nodeCount(); i < s; i++) {
239             Node n = branch.node(i);
240             writeNode(n);
241         }
242     }
243
244     /**
245      * Writes a DOM4J {@link Element}node and its children to the stream.
246      *
247      * @param elem
248      * The {@link Element}node to write to the stream.
249      *
250      * @throws XMLStreamException
251      * If an error occurs writing to the stream.
252      */

253     public void writeElement(Element elem) throws XMLStreamException {
254         consumer.add(createStartElement(elem));
255         writeChildNodes(elem);
256         consumer.add(createEndElement(elem));
257     }
258
259     /**
260      * Constructs a STAX {@link StartElement}event from a DOM4J {@link
261      * Element}.
262      *
263      * @param elem
264      * The {@link Element}from which to construct the event.
265      *
266      * @return The newly constructed {@link StartElement}event.
267      */

268     public StartElement createStartElement(Element elem) {
269         // create name
270
QName JavaDoc tagName = createQName(elem.getQName());
271
272         // create attribute & namespace iterators
273
Iterator JavaDoc attrIter = new AttributeIterator(elem.attributeIterator());
274         Iterator JavaDoc nsIter = new NamespaceIterator(elem.declaredNamespaces()
275                 .iterator());
276
277         // create start event
278
return factory.createStartElement(tagName, attrIter, nsIter);
279     }
280
281     /**
282      * Constructs a STAX {@link EndElement}event from a DOM4J {@link Element}.
283      *
284      * @param elem
285      * The {@link Element}from which to construct the event.
286      *
287      * @return The newly constructed {@link EndElement}event.
288      */

289     public EndElement createEndElement(Element elem) {
290         QName JavaDoc tagName = createQName(elem.getQName());
291         Iterator JavaDoc nsIter = new NamespaceIterator(elem.declaredNamespaces()
292                 .iterator());
293
294         return factory.createEndElement(tagName, nsIter);
295     }
296
297     /**
298      * Writes a DOM4J {@link Attribute}to the stream.
299      *
300      * @param attr
301      * The {@link Attribute}to write to the stream.
302      *
303      * @throws XMLStreamException
304      * If an error occurs writing to the stream.
305      */

306     public void writeAttribute(Attribute attr) throws XMLStreamException {
307         consumer.add(createAttribute(attr));
308     }
309
310     /**
311      * Constructs a STAX {@link javax.xml.stream.events.Attribute}event from a
312      * DOM4J {@link Attribute}.
313      *
314      * @param attr
315      * The {@link Attribute}from which to construct the event.
316      *
317      * @return The newly constructed {@link javax.xml.stream.events.Attribute}
318      * event.
319      */

320     public javax.xml.stream.events.Attribute createAttribute(Attribute attr) {
321         QName JavaDoc attrName = createQName(attr.getQName());
322         String JavaDoc value = attr.getValue();
323
324         return factory.createAttribute(attrName, value);
325     }
326
327     /**
328      * Writes a DOM4J {@link Namespace}to the stream.
329      *
330      * @param ns
331      * The {@link Namespace}to write to the stream.
332      *
333      * @throws XMLStreamException
334      * If an error occurs writing to the stream.
335      */

336     public void writeNamespace(Namespace ns) throws XMLStreamException {
337         consumer.add(createNamespace(ns));
338     }
339
340     /**
341      * Constructs a STAX {@link javax.xml.stream.events.Namespace}event from a
342      * DOM4J {@link Namespace}.
343      *
344      * @param ns
345      * The {@link Namespace}from which to construct the event.
346      *
347      * @return The constructed {@link javax.xml.stream.events.Namespace}event.
348      */

349     public javax.xml.stream.events.Namespace createNamespace(Namespace ns) {
350         String JavaDoc prefix = ns.getPrefix();
351         String JavaDoc uri = ns.getURI();
352
353         return factory.createNamespace(prefix, uri);
354     }
355
356     /**
357      * Writes a DOM4J {@link Text}to the stream.
358      *
359      * @param text
360      * The {@link Text}to write to the stream.
361      *
362      * @throws XMLStreamException
363      * If an error occurs writing to the stream.
364      */

365     public void writeText(Text text) throws XMLStreamException {
366         consumer.add(createCharacters(text));
367     }
368
369     /**
370      * Constructs a STAX {@link Characters}event from a DOM4J {@link Text}.
371      *
372      * @param text
373      * The {@link Text}from which to construct the event.
374      *
375      * @return The constructed {@link Characters}event.
376      */

377     public Characters createCharacters(Text text) {
378         return factory.createCharacters(text.getText());
379     }
380
381     /**
382      * Writes a DOM4J {@link CDATA}to the event stream.
383      *
384      * @param cdata
385      * The {@link CDATA}to write to the stream.
386      *
387      * @throws XMLStreamException
388      * If an error occurs writing to the stream.
389      */

390     public void writeCDATA(CDATA cdata) throws XMLStreamException {
391         consumer.add(createCharacters(cdata));
392     }
393
394     /**
395      * Constructs a STAX {@link Characters}event from a DOM4J {@link CDATA}.
396      *
397      * @param cdata
398      * The {@link CDATA}from which to construct the event.
399      *
400      * @return The newly constructed {@link Characters}event.
401      */

402     public Characters createCharacters(CDATA cdata) {
403         return factory.createCData(cdata.getText());
404     }
405
406     /**
407      * Writes a DOM4J {@link Comment}to the stream.
408      *
409      * @param comment
410      * The {@link Comment}to write to the stream.
411      *
412      * @throws XMLStreamException
413      * If an error occurs writing to the stream.
414      */

415     public void writeComment(Comment comment) throws XMLStreamException {
416         consumer.add(createComment(comment));
417     }
418
419     /**
420      * Constructs a STAX {@link javax.xml.stream.events.Comment}event from a
421      * DOM4J {@link Comment}.
422      *
423      * @param comment
424      * The {@link Comment}from which to construct the event.
425      *
426      * @return The constructed {@link javax.xml.stream.events.Comment}event.
427      */

428     public javax.xml.stream.events.Comment createComment(Comment comment) {
429         return factory.createComment(comment.getText());
430     }
431
432     /**
433      * Writes a DOM4J {@link ProcessingInstruction}to the stream.
434      *
435      * @param pi
436      * The {@link ProcessingInstruction}to write to the stream.
437      *
438      * @throws XMLStreamException
439      * If an error occurs writing to the stream.
440      */

441     public void writeProcessingInstruction(org.dom4j.ProcessingInstruction pi)
442             throws XMLStreamException {
443         consumer.add(createProcessingInstruction(pi));
444     }
445
446     /**
447      * Constructs a STAX {@link javax.xml.stream.events.ProcessingInstruction}
448      * event from a DOM4J {@link ProcessingInstruction}.
449      *
450      * @param pi
451      * The {@link ProcessingInstruction}from which to construct the
452      * event.
453      *
454      * @return The constructed {@link
455      * javax.xml.stream.events.ProcessingInstruction} event.
456      */

457     public ProcessingInstruction createProcessingInstruction(
458             org.dom4j.ProcessingInstruction pi) {
459         String JavaDoc target = pi.getTarget();
460         String JavaDoc data = pi.getText();
461
462         return factory.createProcessingInstruction(target, data);
463     }
464
465     /**
466      * Writes a DOM4J {@link Entity}to the stream.
467      *
468      * @param entity
469      * The {@link Entity}to write to the stream.
470      *
471      * @throws XMLStreamException
472      * If an error occurs writing to the stream.
473      */

474     public void writeEntity(Entity entity) throws XMLStreamException {
475         consumer.add(createEntityReference(entity));
476     }
477
478     /**
479      * Constructs a STAX {@link EntityReference}event from a DOM4J {@link
480      * Entity}.
481      *
482      * @param entity
483      * The {@link Entity}from which to construct the event.
484      *
485      * @return The constructed {@link EntityReference}event.
486      */

487     private EntityReference createEntityReference(Entity entity) {
488         return factory.createEntityReference(entity.getName(), null);
489     }
490
491     /**
492      * Writes a DOM4J {@link DocumentType}to the stream.
493      *
494      * @param docType
495      * The {@link DocumentType}to write to the stream.
496      *
497      * @throws XMLStreamException
498      * If an error occurs writing to the stream.
499      */

500     public void writeDocumentType(DocumentType docType)
501             throws XMLStreamException {
502         consumer.add(createDTD(docType));
503     }
504
505     /**
506      * Constructs a STAX {@link DTD}event from a DOM4J {@link DocumentType}.
507      *
508      * @param docType
509      * The {@link DocumentType}from which to construct the event.
510      *
511      * @return The constructed {@link DTD}event.
512      *
513      * @throws RuntimeException
514      * DOCUMENT ME!
515      */

516     public DTD createDTD(DocumentType docType) {
517         StringWriter JavaDoc decl = new StringWriter JavaDoc();
518
519         try {
520             docType.write(decl);
521         } catch (IOException JavaDoc e) {
522             throw new RuntimeException JavaDoc("Error writing DTD", e);
523         }
524
525         return factory.createDTD(decl.toString());
526     }
527
528     /**
529      * Writes a DOM4J {@link Document}node, and all its contents, to the
530      * stream.
531      *
532      * @param doc
533      * The {@link Document}to write to the stream.
534      *
535      * @throws XMLStreamException
536      * If an error occurs writing to the stream.
537      */

538     public void writeDocument(Document doc) throws XMLStreamException {
539         consumer.add(createStartDocument(doc));
540
541         writeChildNodes(doc);
542
543         consumer.add(createEndDocument(doc));
544     }
545
546     /**
547      * Constructs a STAX {@link StartDocument}event from a DOM4J {@link
548      * Document}.
549      *
550      * @param doc
551      * The {@link Document}from which to construct the event.
552      *
553      * @return The constructed {@link StartDocument}event.
554      */

555     public StartDocument createStartDocument(Document doc) {
556         String JavaDoc encoding = doc.getXMLEncoding();
557
558         if (encoding != null) {
559             return factory.createStartDocument(encoding);
560         } else {
561             return factory.createStartDocument();
562         }
563     }
564
565     /**
566      * Constructs a STAX {@link EndDocument}event from a DOM4J {@link
567      * Document}.
568      *
569      * @param doc
570      * The {@link Document}from which to construct the event.
571      *
572      * @return The constructed {@link EndDocument}event.
573      */

574     public EndDocument createEndDocument(Document doc) {
575         return factory.createEndDocument();
576     }
577
578     /**
579      * Constructs a STAX {@link QName}from a DOM4J {@link org.dom4j.QName}.
580      *
581      * @param qname
582      * The {@link org.dom4j.QName}from which to construct the STAX
583      * {@link QName}.
584      *
585      * @return The constructed {@link QName}.
586      */

587     public QName JavaDoc createQName(org.dom4j.QName qname) {
588         return new QName JavaDoc(qname.getNamespaceURI(), qname.getName(), qname
589                 .getNamespacePrefix());
590     }
591
592     /**
593      * Internal {@link Iterator}implementation used to pass DOM4J {@link
594      * Attribute}s to the stream.
595      */

596     private class AttributeIterator implements Iterator JavaDoc {
597         /** The underlying DOm4J attribute iterator. */
598         private Iterator JavaDoc iter;
599
600         public AttributeIterator(Iterator JavaDoc iter) {
601             this.iter = iter;
602         }
603
604         public boolean hasNext() {
605             return iter.hasNext();
606         }
607
608         public Object JavaDoc next() {
609             Attribute attr = (Attribute) iter.next();
610             QName JavaDoc attrName = createQName(attr.getQName());
611             String JavaDoc value = attr.getValue();
612
613             return factory.createAttribute(attrName, value);
614         }
615
616         public void remove() {
617             throw new UnsupportedOperationException JavaDoc();
618         }
619     }
620
621     /**
622      * Internal {@link Iterator}implementation used to pass DOM4J {@link
623      * Namespace}s to the stream.
624      */

625     private class NamespaceIterator implements Iterator JavaDoc {
626         private Iterator JavaDoc iter;
627
628         public NamespaceIterator(Iterator JavaDoc iter) {
629             this.iter = iter;
630         }
631
632         public boolean hasNext() {
633             return iter.hasNext();
634         }
635
636         public Object JavaDoc next() {
637             Namespace ns = (Namespace) iter.next();
638             String JavaDoc prefix = ns.getPrefix();
639             String JavaDoc nsURI = ns.getURI();
640
641             return factory.createNamespace(prefix, nsURI);
642         }
643
644         public void remove() {
645             throw new UnsupportedOperationException JavaDoc();
646         }
647     }
648 }
649
650 /*
651  * Redistribution and use of this software and associated documentation
652  * ("Software"), with or without modification, are permitted provided that the
653  * following conditions are met:
654  *
655  * 1. Redistributions of source code must retain copyright statements and
656  * notices. Redistributions must also contain a copy of this document.
657  *
658  * 2. Redistributions in binary form must reproduce the above copyright notice,
659  * this list of conditions and the following disclaimer in the documentation
660  * and/or other materials provided with the distribution.
661  *
662  * 3. The name "DOM4J" must not be used to endorse or promote products derived
663  * from this Software without prior written permission of MetaStuff, Ltd. For
664  * written permission, please contact dom4j-info@metastuff.com.
665  *
666  * 4. Products derived from this Software may not be called "DOM4J" nor may
667  * "DOM4J" appear in their names without prior written permission of MetaStuff,
668  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
669  *
670  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
671  *
672  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
673  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
674  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
675  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
676  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
677  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
678  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
679  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
680  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
681  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
682  * POSSIBILITY OF SUCH DAMAGE.
683  *
684  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
685  */

686
Popular Tags