| /* | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * This software is open source. | ||
| * See the bottom of this file for the licence. | ||
| * | ||
| * $Id: STAXEventWriter.java,v 1.6 2004/07/14 19:32:23 maartenc Exp $ | ||
| */ | ||
| package org.dom4j.io; | ||
| import java.io.File; | ||
| import java.io.FileWriter; | ||
| import java.io.IOException; | ||
| import java.io.OutputStream; | ||
| import java.io.StringWriter; | ||
| import java.io.Writer; | ||
| import java.util.Iterator; | ||
| import javax.xml.namespace.QName; | ||
| import javax.xml.stream.XMLEventFactory; | ||
| import javax.xml.stream.XMLOutputFactory; | ||
| import javax.xml.stream.XMLStreamException; | ||
| import javax.xml.stream.events.Characters; | ||
| import javax.xml.stream.events.DTD; | ||
| import javax.xml.stream.events.EndDocument; | ||
| import javax.xml.stream.events.EndElement; | ||
| import javax.xml.stream.events.EntityReference; | ||
| import javax.xml.stream.events.StartDocument; | ||
| import javax.xml.stream.events.StartElement; | ||
| import javax.xml.stream.util.XMLEventConsumer; | ||
| import org.dom4j.Attribute; | ||
| import org.dom4j.Branch; | ||
| import org.dom4j.CDATA; | ||
| import org.dom4j.Comment; | ||
| import org.dom4j.Document; | ||
| import org.dom4j.DocumentType; | ||
| import org.dom4j.Element; | ||
| import org.dom4j.Entity; | ||
| import org.dom4j.Namespace; | ||
| import org.dom4j.Node; | ||
| import org.dom4j.ProcessingInstruction; | ||
| import org.dom4j.Text; | ||
| /** | ||
| * Writes DOM4J {@link Node}s to a StAX event stream. In addition the | ||
| * <code>createXXX</code> methods are provided to directly create STAX events | ||
| * from DOM4J nodes. | ||
| * | ||
| * @author Christian Niles | ||
| */ | ||
| public class STAXEventWriter { | ||
| /** The event stream to which events are written. */ | ||
| private XMLEventConsumer consumer; | ||
| /** The event factory used to construct events. */ | ||
| 0x | private XMLEventFactory factory = XMLEventFactory.newInstance(); | |
| 0x | private XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); | |
| 0x | public STAXEventWriter() { | |
| 0x | } | |
| /** | ||
| * Constructs a <code>STAXEventWriter</code> that writes events to the | ||
| * provided file. | ||
| * | ||
| * @param file The file to which events will be written. | ||
| * @throws XMLStreamException If an error occurs creating an event writer from | ||
| * the file. | ||
| * @throws IOException If an error occurs openin the file for writing. | ||
| */ | ||
| 0x | public STAXEventWriter(File file) throws XMLStreamException, IOException { | |
| 0x | consumer = outputFactory.createXMLEventWriter(new FileWriter(file)); | |
| 0x | } | |
| /** | ||
| * Constructs a <code>STAXEventWriter</code> that writes events to the | ||
| * provided character stream. | ||
| * | ||
| * @param writer The character stream to which events will be written. | ||
| * @throws XMLStreamException If an error occurs constructing an event writer | ||
| * from the character stream. | ||
| */ | ||
| 0x | public STAXEventWriter(Writer writer) throws XMLStreamException { | |
| 0x | consumer = outputFactory.createXMLEventWriter(writer); | |
| 0x | } | |
| /** | ||
| * Constructs a <code>STAXEventWriter</code> that writes events to the | ||
| * provided stream. | ||
| * | ||
| * @param stream The output stream to which events will be written. | ||
| * @throws XMLStreamException If an error occurs constructing an event writer | ||
| * from the stream. | ||
| */ | ||
| 0x | public STAXEventWriter(OutputStream stream) throws XMLStreamException { | |
| 0x | consumer = outputFactory.createXMLEventWriter(stream); | |
| 0x | } | |
| /** | ||
| * Constructs a <code>STAXEventWriter</code> that writes events to the | ||
| * provided event stream. | ||
| * | ||
| * @param consumer The event stream to which events will be written. | ||
| */ | ||
| 0x | public STAXEventWriter(XMLEventConsumer consumer) { | |
| 0x | this.consumer = consumer; | |
| 0x | } | |
| /** | ||
| * Returns a reference to the underlying event consumer to which events are | ||
| * written. | ||
| * | ||
| * @return The underlying event consumer to which events are written. | ||
| */ | ||
| public XMLEventConsumer getConsumer() { | ||
| 0x | return consumer; | |
| } | ||
| /** | ||
| * Sets the underlying event consumer to which events are written. | ||
| * | ||
| * @param consumer The event consumer to which events should be written. | ||
| */ | ||
| public void setConsumer(XMLEventConsumer consumer) { | ||
| 0x | this.consumer = consumer; | |
| 0x | } | |
| /** | ||
| * Returns a reference to the event factory used to construct STAX events. | ||
| * | ||
| * @return The event factory used to construct STAX events. | ||
| */ | ||
| public XMLEventFactory getEventFactory() { | ||
| 0x | return factory; | |
| } | ||
| /** | ||
| * Sets the event factory used to construct STAX events. | ||
| * | ||
| * @param factory The new event factory. | ||
| */ | ||
| public void setEventFactory(XMLEventFactory factory) { | ||
| 0x | this.factory = factory; | |
| 0x | } | |
| /** | ||
| * Writes a DOM4J {@link Node} to the stream. This method is simply a | ||
| * gateway to the overloaded methods such as {@link #writeElement(Element)}. | ||
| * | ||
| * @param n The DOM4J {@link Node} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeNode(Node n) throws XMLStreamException { | ||
| 0x | switch (n.getNodeType()) { | |
| case Node.ELEMENT_NODE : | ||
| 0x | writeElement((Element) n); | |
| 0x | break; | |
| case Node.TEXT_NODE : | ||
| 0x | writeText((Text) n); | |
| 0x | break; | |
| case Node.ATTRIBUTE_NODE : | ||
| 0x | writeAttribute((Attribute) n); | |
| 0x | break; | |
| case Node.NAMESPACE_NODE : | ||
| 0x | writeNamespace((Namespace) n); | |
| 0x | break; | |
| case Node.COMMENT_NODE : | ||
| 0x | writeComment((Comment) n); | |
| 0x | break; | |
| case Node.CDATA_SECTION_NODE : | ||
| 0x | writeCDATA((CDATA) n); | |
| 0x | break; | |
| case Node.PROCESSING_INSTRUCTION_NODE : | ||
| 0x | writeProcessingInstruction((ProcessingInstruction) n); | |
| 0x | break; | |
| case Node.ENTITY_REFERENCE_NODE : | ||
| 0x | writeEntity((Entity) n); | |
| 0x | break; | |
| case Node.DOCUMENT_NODE : | ||
| 0x | writeDocument((Document) n); | |
| 0x | break; | |
| case Node.DOCUMENT_TYPE_NODE : | ||
| 0x | writeDocumentType((DocumentType) n); | |
| 0x | break; | |
| default : | ||
| 0x | throw new XMLStreamException("Unsupported DOM4J Node: " + n); | |
| } | ||
| 0x | } | |
| /** | ||
| * Writes each child node within the provided {@link Branch} instance. This | ||
| * method simply iterates through the {@link Branch}'s nodes and calls | ||
| * {@link #writeNode(Node)}. | ||
| * | ||
| * @param branch The node whose children will be written to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeChildNodes(Branch branch) throws XMLStreamException { | ||
| 0/2 0x | for (int i = 0, s = branch.nodeCount(); i < s; i++) { | |
| 0x | Node n = branch.node(i); | |
| 0x | writeNode(n); | |
| } | ||
| 0x | } | |
| /** | ||
| * Writes a DOM4J {@link Element} node and its children to the stream. | ||
| * | ||
| * @param elem The {@link Element} node to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeElement(Element elem) throws XMLStreamException { | ||
| 0x | consumer.add(createStartElement(elem)); | |
| 0x | writeChildNodes(elem); | |
| 0x | consumer.add(createEndElement(elem)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link StartElement} event from a DOM4J | ||
| * {@link Element}. | ||
| * | ||
| * @param elem The {@link Element} from which to construct the event. | ||
| * @return The newly constructed {@link StartElement} event. | ||
| */ | ||
| public StartElement createStartElement(Element elem) { | ||
| // create name | ||
| 0x | QName tagName = createQName(elem.getQName()); | |
| // create attribute & namespace iterators | ||
| 0x | Iterator attrIter = new AttributeIterator(elem.attributeIterator()); | |
| 0x | Iterator nsIter = new NamespaceIterator( | |
| elem.declaredNamespaces().iterator()); | ||
| // create start event | ||
| 0x | return factory.createStartElement(tagName, attrIter, nsIter); | |
| } | ||
| /** | ||
| * Constructs a STAX {@link EndElement} event from a DOM4J {@link Element}. | ||
| * | ||
| * @param elem The {@link Element} from which to construct the event. | ||
| * @return The newly constructed {@link EndElement} event. | ||
| */ | ||
| public EndElement createEndElement(Element elem) { | ||
| 0x | QName tagName = createQName(elem.getQName()); | |
| 0x | Iterator nsIter = new NamespaceIterator( | |
| elem.declaredNamespaces().iterator()); | ||
| 0x | return factory.createEndElement(tagName, nsIter); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Attribute} to the stream. | ||
| * | ||
| * @param attr The {@link Attribute} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeAttribute(Attribute attr) throws XMLStreamException { | ||
| 0x | consumer.add(createAttribute(attr)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link javax.xml.stream.events.Attribute} event from | ||
| * a DOM4J {@link Attribute}. | ||
| * | ||
| * @param attr The {@link Attribute} from which to construct the event. | ||
| * @return The newly constructed {@link javax.xml.stream.events.Attribute} | ||
| * event. | ||
| */ | ||
| public javax.xml.stream.events.Attribute createAttribute(Attribute attr) { | ||
| 0x | QName attrName = createQName(attr.getQName()); | |
| 0x | String value = attr.getValue(); | |
| 0x | return factory.createAttribute(attrName, value); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Namespace} to the stream. | ||
| * | ||
| * @param ns The {@link Namespace} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeNamespace(Namespace ns) throws XMLStreamException { | ||
| 0x | consumer.add(createNamespace(ns)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link javax.xml.stream.events.Namespace} event from | ||
| * a DOM4J {@link Namespace}. | ||
| * | ||
| * @param ns The {@link Namespace} from which to construct the event. | ||
| * @return The constructed {@link javax.xml.stream.events.Namespace} event. | ||
| */ | ||
| public javax.xml.stream.events.Namespace createNamespace(Namespace ns) { | ||
| 0x | String prefix = ns.getPrefix(); | |
| 0x | String uri = ns.getURI(); | |
| 0x | return factory.createNamespace(prefix, uri); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Text} to the stream. | ||
| * | ||
| * @param text The {@link Text} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeText(Text text) throws XMLStreamException { | ||
| 0x | consumer.add(createCharacters(text)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link Characters} event from a DOM4J {@link Text}. | ||
| * | ||
| * @param text The {@link Text} from which to construct the event. | ||
| * @return The constructed {@link Characters} event. | ||
| */ | ||
| public Characters createCharacters(Text text) { | ||
| 0x | return factory.createCharacters(text.getText()); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link CDATA} to the event stream. | ||
| * | ||
| * @param cdata The {@link CDATA} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeCDATA(CDATA cdata) throws XMLStreamException { | ||
| 0x | consumer.add(createCharacters(cdata)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link Characters} event from a DOM4J {@link CDATA}. | ||
| * | ||
| * @param cdata The {@link CDATA} from which to construct the event. | ||
| * @return The newly constructed {@link Characters} event. | ||
| */ | ||
| public Characters createCharacters(CDATA cdata) { | ||
| 0x | return factory.createCData(cdata.getText()); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Comment} to the stream. | ||
| * | ||
| * @param comment The {@link Comment} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeComment(Comment comment) throws XMLStreamException { | ||
| 0x | consumer.add(createComment(comment)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link javax.xml.stream.events.Comment} event from a | ||
| * DOM4J {@link Comment}. | ||
| * | ||
| * @param comment The {@link Comment} from which to construct the event. | ||
| * @return The constructed {@link javax.xml.stream.events.Comment} event. | ||
| */ | ||
| public javax.xml.stream.events.Comment createComment(Comment comment) { | ||
| 0x | return factory.createComment(comment.getText()); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link ProcessingInstruction} to the stream. | ||
| * | ||
| * @param pi The {@link ProcessingInstruction} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeProcessingInstruction(ProcessingInstruction pi) throws XMLStreamException { | ||
| 0x | consumer.add(createProcessingInstruction(pi)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link javax.xml.stream.events.ProcessingInstruction} | ||
| * event from a DOM4J {@link ProcessingInstruction}. | ||
| * | ||
| * @param pi The {@link ProcessingInstruction} from which to construct the | ||
| * event. | ||
| * @return The constructed | ||
| * {@link javax.xml.stream.events.ProcessingInstruction} event. | ||
| */ | ||
| public javax.xml.stream.events.ProcessingInstruction createProcessingInstruction( | ||
| ProcessingInstruction pi) { | ||
| 0x | String target = pi.getTarget(); | |
| 0x | String data = pi.getText(); | |
| 0x | return factory.createProcessingInstruction(target, data); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Entity} to the stream. | ||
| * | ||
| * @param entity The {@link Entity} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeEntity(Entity entity) throws XMLStreamException { | ||
| 0x | consumer.add(createEntityReference(entity)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link EntityReference} event from a DOM4J | ||
| * {@link Entity}. | ||
| * | ||
| * @param entity The {@link Entity} from which to construct the event. | ||
| * @return The constructed {@link EntityReference} event. | ||
| */ | ||
| private EntityReference createEntityReference(Entity entity) { | ||
| 0x | return factory.createEntityReference(entity.getName(), null); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link DocumentType} to the stream. | ||
| * | ||
| * @param docType The {@link DocumentType} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeDocumentType(DocumentType docType) throws XMLStreamException { | ||
| 0x | consumer.add(createDTD(docType)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link DTD} event from a DOM4J {@link DocumentType}. | ||
| * | ||
| * @param docType The {@link DocumentType} from which to construct the | ||
| * event. | ||
| * @return The constructed {@link DTD} event. | ||
| */ | ||
| public DTD createDTD(DocumentType docType) { | ||
| 0x | StringWriter decl = new StringWriter(); | |
| try { | ||
| 0x | docType.write(decl); | |
| } catch (IOException e) { | ||
| 0x | throw new RuntimeException("Error writing DTD", e); | |
| 0x | } | |
| 0x | return factory.createDTD(decl.toString()); | |
| } | ||
| /** | ||
| * Writes a DOM4J {@link Document} node, and all its contents, to the | ||
| * stream. | ||
| * | ||
| * @param doc The {@link Document} to write to the stream. | ||
| * @throws XMLStreamException If an error occurs writing to the stream. | ||
| */ | ||
| public void writeDocument(Document doc) throws XMLStreamException { | ||
| 0x | consumer.add(createStartDocument(doc)); | |
| 0x | writeChildNodes(doc); | |
| 0x | consumer.add(createEndDocument(doc)); | |
| 0x | } | |
| /** | ||
| * Constructs a STAX {@link StartDocument} event from a DOM4J | ||
| * {@link Document}. | ||
| * | ||
| * @param doc The {@link Document} from which to construct the event. | ||
| * @return The constructed {@link StartDocument} event. | ||
| */ | ||
| public StartDocument createStartDocument(Document doc) { | ||
| 0x | String encoding = doc.getXMLEncoding(); | |
| 0/2 0x | if (encoding != null) { | |
| 0x | return factory.createStartDocument(encoding); | |
| } else { | ||
| 0x | return factory.createStartDocument(); | |
| } | ||
| } | ||