All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.java.com.ctc.wstx.dom.DOMWrappingWriter Maven / Gradle / Ivy

There is a newer version: 4.0.6
Show newest version
package com.ctc.wstx.dom;

import java.util.*;

import javax.xml.XMLConstants;
import javax.xml.namespace.*;
import javax.xml.stream.*;
import javax.xml.transform.dom.DOMResult;

import org.w3c.dom.*;

import org.codehaus.stax2.XMLStreamLocation2;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.XMLStreamWriter2;
import org.codehaus.stax2.validation.ValidationProblemHandler;
import org.codehaus.stax2.validation.XMLValidationSchema;
import org.codehaus.stax2.validation.XMLValidator;

import com.ctc.wstx.api.WriterConfig;
import com.ctc.wstx.api.WstxOutputProperties;
import com.ctc.wstx.util.EmptyNamespaceContext;

/**
 * This is an adapter class that allows building a DOM tree using
 * {@link XMLStreamWriter} interface.
 *

* Note that the implementation is only to be used for use with * javax.xml.transform.dom.DOMResult. *

* Some notes regarding missing/incomplete functionality: *

    *
* * @author Tatu Saloranta * @author Dan Diephouse */ public class DOMWrappingWriter implements XMLStreamWriter2 { /* //////////////////////////////////////////////////// // Configuration //////////////////////////////////////////////////// */ protected final WriterConfig mConfig; protected final boolean mNsAware; protected final boolean mNsRepairing; /** * This member variable is to keep information about encoding * that seems to be used for the document (or fragment) to output, * if known. */ protected String mEncoding = null; /** * If we are being given info about existing bindings, it'll come * as a NamespaceContet. */ protected NamespaceContext mNsContext; /* //////////////////////////////////////////////////// // State //////////////////////////////////////////////////// */ /** * We need a reference to the document hosting nodes to * be able to create new nodes */ protected final Document mDocument; /** * This element is the current context element, under which * all other nodes are added, until matching end element * is output. Null outside of the main element tree. */ protected Element mParentElem; /** * This element is non-null right after a call to * either writeStartElement and * writeEmptyElement, and can be used to * add attributes and namespace declarations. */ protected Element mOpenElement; /* //////////////////////////////////////////////////// // Life-cycle //////////////////////////////////////////////////// */ private DOMWrappingWriter(WriterConfig cfg, Node treeRoot) throws XMLStreamException { if (treeRoot == null) { throw new IllegalArgumentException("Can not pass null Node for constructing a DOM-based XMLStreamWriter"); } mConfig = cfg; mNsAware = cfg.willSupportNamespaces(); mNsRepairing = mNsAware && cfg.automaticNamespacesEnabled(); /* 15-Sep-2007, TSa: Repairing mode not yet supported, so better * signal that right away */ if (mNsRepairing) { throw new XMLStreamException("Repairing mode not (yet) supported with DOM-backed writer"); } Element elem = null; /* Ok; we need a document node; or an element node; or a document * fragment node. */ switch (treeRoot.getNodeType()) { case Node.DOCUMENT_NODE: // fine mDocument = (Document) treeRoot; /* Should try to find encoding, version and stand-alone * settings... but is there a standard way of doing that? */ break; case Node.ELEMENT_NODE: // can make sub-tree... ok mDocument = treeRoot.getOwnerDocument(); elem = (Element) treeRoot; break; case Node.DOCUMENT_FRAGMENT_NODE: // as with element... mDocument = treeRoot.getOwnerDocument(); // Above types are fine break; default: // other Nodes not usable throw new XMLStreamException("Can not create an XMLStreamWriter for a DOM node of type "+treeRoot.getClass()); } if (mDocument == null) { throw new XMLStreamException("Can not create an XMLStreamWriter for given node (of type "+treeRoot.getClass()+"): did not have owner document"); } mParentElem = mOpenElement = elem; } public static DOMWrappingWriter createFrom(WriterConfig cfg, DOMResult dst) throws XMLStreamException { Node rootNode = dst.getNode(); return new DOMWrappingWriter(cfg, rootNode); } /* //////////////////////////////////////////////////// // XMLStreamWriter API (Stax 1.0) //////////////////////////////////////////////////// */ public void close() { // NOP } public void flush() { // NOP } public NamespaceContext getNamespaceContext() { if (!mNsAware) { return EmptyNamespaceContext.getInstance(); } // !!! TBI: return mNsContext; } public String getPrefix(String uri) { if (!mNsAware) { return null; } // !!! TBI: return null; } public Object getProperty(String name) { // !!! TBI return null; } public void setDefaultNamespace(String uri) { // !!! TBI } public void setNamespaceContext(NamespaceContext context) { mNsContext = context; } public void setPrefix(String prefix, String uri) { // !!! TBI } public void writeAttribute(String localName, String value) { outputAttribute(null, null, localName, value); } public void writeAttribute(String nsURI, String localName, String value) { outputAttribute(nsURI, null, localName, value); } public void writeAttribute(String prefix, String nsURI, String localName, String value) { outputAttribute(nsURI, prefix, localName, value); } public void writeCData(String data) { appendLeaf(mDocument.createCDATASection(data)); } public void writeCharacters(char[] text, int start, int len) { writeCharacters(new String(text, start, len)); } public void writeCharacters(String text) { appendLeaf(mDocument.createTextNode(text)); } public void writeComment(String data) { appendLeaf(mDocument.createCDATASection(data)); } public void writeDefaultNamespace(String nsURI) { writeNamespace(null, nsURI); } public void writeDTD(String dtd) { // Would have to parse, not worth trying... reportUnsupported("writeDTD()"); } public void writeEmptyElement(String localName) { writeEmptyElement(null, localName); } public void writeEmptyElement(String nsURI, String localName) { /* Note: can not just call writeStartElement(), since this * element will only become the open elem, but not a parent elem */ createStartElem(nsURI, null, localName, true); } public void writeEmptyElement(String prefix, String localName, String nsURI) { createStartElem(nsURI, prefix, localName, true); } public void writeEndDocument() { mParentElem = mOpenElement = null; } public void writeEndElement() { // Simple, just need to traverse up... if we can if (mParentElem == null) { throw new IllegalStateException("No open start element to close"); } mOpenElement = null; // just in case it was open Node parent = mParentElem.getParentNode(); mParentElem = (parent == mDocument) ? null : (Element) parent; } public void writeEntityRef(String name) { appendLeaf(mDocument.createEntityReference(name)); } public void writeNamespace(String prefix, String nsURI) { boolean defNS = (prefix == null || prefix.length() == 0); if (!mNsAware) { if (defNS) { outputAttribute(null, null, "xmlns", nsURI); } else { outputAttribute(null, "xmlns", prefix, nsURI); } } else { // !!! TBI /* For now, let's output it (in non-repairing ns-aware * mode), but not keep track of bindings. */ if (defNS) { outputAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, null, "xmlns", nsURI); } else { outputAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", prefix, nsURI); } } } public void writeProcessingInstruction(String target) { writeProcessingInstruction(target, null); } public void writeProcessingInstruction(String target, String data) { appendLeaf(mDocument.createProcessingInstruction(target, data)); } public void writeSpace(char[] text, int start, int len) { writeSpace(new String(text, start, len)); } public void writeSpace(String text) { /* This won't work all that well, given there's no way to * prevent quoting/escaping. But let's do what we can, since * the alternative (throwing an exception) doesn't seem * especially tempting choice. */ writeCharacters(text); } public void writeStartDocument() { writeStartDocument(WstxOutputProperties.DEFAULT_OUTPUT_ENCODING, WstxOutputProperties.DEFAULT_XML_VERSION); } public void writeStartDocument(String version) { writeStartDocument(null, version); } public void writeStartDocument(String encoding, String version) { // Is there anything here we can or should do? No? mEncoding = encoding; } public void writeStartElement(String localName) { writeStartElement(null, localName); } public void writeStartElement(String nsURI, String localName) { createStartElem(nsURI, null, localName, false); } public void writeStartElement(String prefix, String localName, String nsURI) { createStartElem(nsURI, prefix, localName, false); } /* //////////////////////////////////////////////////// // XMLStreamWriter2 API (Stax2 v2.0) //////////////////////////////////////////////////// */ public boolean isPropertySupported(String name) { // !!! TBI: not all these properties are really supported return mConfig.isPropertySupported(name); } public boolean setProperty(String name, Object value) { /* Note: can not call local method, since it'll return false for * recognized but non-mutable properties */ return mConfig.setProperty(name, value); } public XMLValidator validateAgainst(XMLValidationSchema schema) throws XMLStreamException { // !!! TBI return null; } public XMLValidator stopValidatingAgainst(XMLValidationSchema schema) throws XMLStreamException { // !!! TBI return null; } public XMLValidator stopValidatingAgainst(XMLValidator validator) throws XMLStreamException { // !!! TBI return null; } public ValidationProblemHandler setValidationProblemHandler(ValidationProblemHandler h) { // Not implemented by the basic reader return null; } public XMLStreamLocation2 getLocation() { return null; } public String getEncoding() { return mEncoding; } public void writeCData(char[] text, int start, int len) throws XMLStreamException { writeCData(new String(text, start, len)); } public void writeDTD(String rootName, String systemId, String publicId, String internalSubset) throws XMLStreamException { /* Alas: although we can create a DocumentType object, there * doesn't seem to be a way to attach it in DOM-2! */ if (mParentElem != null) { throw new IllegalStateException("Operation only allowed to the document before adding root element"); } reportUnsupported("writeDTD()"); } public void writeFullEndElement() throws XMLStreamException { // No difference with DOM writeEndElement(); } public void writeStartDocument(String version, String encoding, boolean standAlone) throws XMLStreamException { writeStartDocument(encoding, version); } /* /////////////////////////////// // Stax2, pass-through methods /////////////////////////////// */ public void writeRaw(String text) throws XMLStreamException { reportUnsupported("writeRaw()"); } public void writeRaw(String text, int start, int offset) throws XMLStreamException { reportUnsupported("writeRaw()"); } public void writeRaw(char[] text, int offset, int length) throws XMLStreamException { reportUnsupported("writeRaw()"); } public void copyEventFromReader(XMLStreamReader2 r, boolean preserveEventData) throws XMLStreamException { // !!! TBI } /* /////////////////////////////// // Internal methods /////////////////////////////// */ protected void appendLeaf(Node n) throws IllegalStateException { if (mParentElem == null) { // to add to document mDocument.appendChild(n); } else { // Will also close the open element, if any mOpenElement = null; mParentElem.appendChild(n); } } protected void createStartElem(String nsURI, String prefix, String localName, boolean isEmpty) { Element elem; if (mNsAware) { if (mNsRepairing) { /* Need to ensure proper bindings... ugh. * May change prefix */ // !!! TBI } if (prefix != null && prefix.length() > 0) { localName = prefix + ":" + localName; } elem = mDocument.createElementNS(nsURI, localName); } else { // non-ns, simple if (prefix != null && prefix.length() > 0) { localName = prefix + ":" + localName; } elem = mDocument.createElement(localName); } appendLeaf(elem); mOpenElement = elem; if (!isEmpty) { mParentElem = elem; } } protected void outputAttribute(String nsURI, String prefix, String localName, String value) { if (mOpenElement == null) { throw new IllegalStateException("No currently open START_ELEMENT, cannot write attribute"); } if (mNsAware) { if (mNsRepairing) { /* Need to ensure proper bindings... ugh. * May change prefix */ // !!! TBI } if (prefix != null && prefix.length() > 0) { localName = prefix + ":" + localName; } mOpenElement.setAttributeNS(nsURI, localName, value); } else { // non-ns, simple if (prefix != null && prefix.length() > 0) { localName = prefix + ":" + localName; } mOpenElement.setAttribute(localName, value); } } private void reportUnsupported(String operName) { throw new UnsupportedOperationException(operName+" can not be used with DOM-backed writer"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy