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

org.codehaus.stax2.ri.dom.DOMWrappingWriter Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
/* Stax2 API extension for Streaming Api for Xml processing (StAX).
 *
 * Copyright (c) 2006- Tatu Saloranta, [email protected]
 *
 * Licensed under the License specified in the file LICENSE which is
 * included with the source code.
 * You may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.codehaus.stax2.ri.dom;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.MessageFormat;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.*;

import org.w3c.dom.*;

import org.codehaus.stax2.XMLStreamLocation2;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.XMLStreamWriter2;
import org.codehaus.stax2.ri.typed.SimpleValueEncoder;
import org.codehaus.stax2.typed.Base64Variant;
import org.codehaus.stax2.typed.Base64Variants;
import org.codehaus.stax2.validation.*;

/**
 * This is an adapter class that partially implements {@link XMLStreamWriter}
 * as a facade on top of  a DOM document or Node, allowing one
 * to basically construct DOM trees via Stax API.
 * It is meant to serve as basis for a full implementation.
 *

* Note that the implementation is only to be used with * javax.xml.transform.dom.DOMResult. It can however be * used for both full documents, and single element root fragments, * depending on what node is passed as the argument. *>p> * One more implementation note: much code is identical to one * used by {@link org.codehaus.stax2.ri.Stax2WriterAdapter}. * Alas it is hard to reuse it without cut'n pasting. * * @author Tatu Saloranta * * @since 3.0 */ public abstract class DOMWrappingWriter implements XMLStreamWriter2 { // // Constants to use as defaults for "writeStartDocument" final static String DEFAULT_OUTPUT_ENCODING = "UTF-8"; final static String DEFAULT_XML_VERSION = "1.0"; /* //////////////////////////////////////////////////// // Configuration //////////////////////////////////////////////////// */ 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 NamespaceContext. */ protected NamespaceContext mNsContext; /* //////////////////////////////////////////////////// // State //////////////////////////////////////////////////// */ /** * We need a reference to the document hosting nodes to * be able to create new nodes */ protected final Document mDocument; /* //////////////////////////////////////////////////// // Helper objects //////////////////////////////////////////////////// */ /** * Encoding of typed values is used the standard encoder * included in RI. */ protected SimpleValueEncoder mValueEncoder; /* //////////////////////////////////////////////////// // Life-cycle //////////////////////////////////////////////////// */ protected DOMWrappingWriter(Node treeRoot, boolean nsAware, boolean nsRepairing) throws XMLStreamException { if (treeRoot == null) { throw new IllegalArgumentException("Can not pass null Node for constructing a DOM-based XMLStreamWriter"); } mNsAware = nsAware; mNsRepairing = nsRepairing; /* 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(); 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"); } } /* //////////////////////////////////////////////////// // Partial XMLStreamWriter API (Stax 1.0) impl //////////////////////////////////////////////////// */ public void close() { // NOP } public void flush() { // NOP } public abstract NamespaceContext getNamespaceContext(); public abstract String getPrefix(String uri); public abstract Object getProperty(String name); public abstract void setDefaultNamespace(String uri); public void setNamespaceContext(NamespaceContext context) { mNsContext = context; } public abstract void setPrefix(String prefix, String uri) throws XMLStreamException; public abstract void writeAttribute(String localName, String value) throws XMLStreamException; public abstract void writeAttribute(String nsURI, String localName, String value) throws XMLStreamException; public abstract void writeAttribute(String prefix, String nsURI, String localName, String value) throws XMLStreamException; public void writeCData(String data) throws XMLStreamException { appendLeaf(mDocument.createCDATASection(data)); } public void writeCharacters(char[] text, int start, int len) throws XMLStreamException { writeCharacters(new String(text, start, len)); } public void writeCharacters(String text) throws XMLStreamException { appendLeaf(mDocument.createTextNode(text)); } public void writeComment(String data) throws XMLStreamException { appendLeaf(mDocument.createComment(data)); } public abstract void writeDefaultNamespace(String nsURI) throws XMLStreamException; public void writeDTD(String dtd) throws XMLStreamException { /* Would need to parse contents, not easy to do via DOM * in any case. */ reportUnsupported("writeDTD()"); } public abstract void writeEmptyElement(String localName) throws XMLStreamException; public abstract void writeEmptyElement(String nsURI, String localName) throws XMLStreamException; public abstract void writeEmptyElement(String prefix, String localName, String nsURI) throws XMLStreamException; public abstract void writeEndDocument() throws XMLStreamException; public void writeEntityRef(String name) throws XMLStreamException { appendLeaf(mDocument.createEntityReference(name)); } public void writeProcessingInstruction(String target) throws XMLStreamException { writeProcessingInstruction(target, null); } public void writeProcessingInstruction(String target, String data) throws XMLStreamException { appendLeaf(mDocument.createProcessingInstruction(target, data)); } public void writeStartDocument() throws XMLStreamException { /* Note: while these defaults are not very intuitive, they * are what Stax 1.0 specification clearly mandates: */ writeStartDocument(DEFAULT_OUTPUT_ENCODING, DEFAULT_XML_VERSION); } public void writeStartDocument(String version) throws XMLStreamException { writeStartDocument(null, version); } public void writeStartDocument(String encoding, String version) throws XMLStreamException { // Is there anything here we can or should do? No? mEncoding = encoding; } /* //////////////////////////////////////////////////// // XMLStreamWriter2 API (Stax2 v3.0): // additional accessors //////////////////////////////////////////////////// */ public XMLStreamLocation2 getLocation() { // !!! TBI return null; } public String getEncoding() { return mEncoding; } public abstract boolean isPropertySupported(String name); public abstract boolean setProperty(String name, Object value); /* //////////////////////////////////////////////////// // XMLStreamWriter2 API (Stax2 v2.0): // extended write methods //////////////////////////////////////////////////// */ public void writeCData(char[] text, int start, int len) throws XMLStreamException { writeCData(new String(text, start, len)); } public abstract void writeDTD(String rootName, String systemId, String publicId, String internalSubset) throws XMLStreamException; //public void writeDTD(String rootName, String systemId, String publicId, String internalSubset) public void writeFullEndElement() throws XMLStreamException { // No difference with DOM writeEndElement(); } public void writeSpace(char[] text, int start, int len) throws XMLStreamException { writeSpace(new String(text, start, len)); } public void writeSpace(String text) throws XMLStreamException { /* 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(String version, String encoding, boolean standAlone) throws XMLStreamException { writeStartDocument(encoding, version); } /* //////////////////////////////////////////////////// // XMLStreamWriter2 API (Stax2 v2.0): validation //////////////////////////////////////////////////// */ 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) { // !!! TBI return null; } /* /////////////////////////////// // 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 } /* /////////////////////////////// // Stax2, output handling /////////////////////////////// */ public void closeCompletely() { // NOP } /* ///////////////////////////////////////////////// // TypedXMLStreamWriter2 implementation // (Typed Access API, Stax v3.0) ///////////////////////////////////////////////// */ // // // Typed element content write methods public void writeBoolean(boolean value) throws XMLStreamException { writeCharacters(value ? "true" : "false"); } public void writeInt(int value) throws XMLStreamException { writeCharacters(String.valueOf(value)); } public void writeLong(long value) throws XMLStreamException { writeCharacters(String.valueOf(value)); } public void writeFloat(float value) throws XMLStreamException { writeCharacters(String.valueOf(value)); } public void writeDouble(double value) throws XMLStreamException { writeCharacters(String.valueOf(value)); } public void writeInteger(BigInteger value) throws XMLStreamException { writeCharacters(value.toString()); } public void writeDecimal(BigDecimal value) throws XMLStreamException { writeCharacters(value.toString()); } public void writeQName(QName name) throws XMLStreamException { writeCharacters(serializeQNameValue(name)); } public void writeIntArray(int[] value, int from, int length) throws XMLStreamException { /* true -> start with space, to allow for multiple consecutive * to be written */ writeCharacters(getValueEncoder().encodeAsString(value, from, length)); } public void writeLongArray(long[] value, int from, int length) throws XMLStreamException { // true -> start with space, for multiple segments writeCharacters(getValueEncoder().encodeAsString(value, from, length)); } public void writeFloatArray(float[] value, int from, int length) throws XMLStreamException { // true -> start with space, for multiple segments writeCharacters(getValueEncoder().encodeAsString(value, from, length)); } public void writeDoubleArray(double[] value, int from, int length) throws XMLStreamException { // true -> start with space, for multiple segments writeCharacters(getValueEncoder().encodeAsString(value, from, length)); } public void writeBinary(byte[] value, int from, int length) throws XMLStreamException { writeBinary(Base64Variants.getDefaultVariant(), value, from, length); } public void writeBinary(Base64Variant v, byte[] value, int from, int length) throws XMLStreamException { writeCharacters(getValueEncoder().encodeAsString(v, value, from, length)); } // // // Typed attribute value write methods public void writeBooleanAttribute(String prefix, String nsURI, String localName, boolean value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, value ? "true" : "false"); } public void writeIntAttribute(String prefix, String nsURI, String localName, int value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, String.valueOf(value)); } public void writeLongAttribute(String prefix, String nsURI, String localName, long value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, String.valueOf(value)); } public void writeFloatAttribute(String prefix, String nsURI, String localName, float value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, String.valueOf(value)); } public void writeDoubleAttribute(String prefix, String nsURI, String localName, double value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, String.valueOf(value)); } public void writeIntegerAttribute(String prefix, String nsURI, String localName, BigInteger value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, value.toString()); } public void writeDecimalAttribute(String prefix, String nsURI, String localName, BigDecimal value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, value.toString()); } public void writeQNameAttribute(String prefix, String nsURI, String localName, QName name) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, serializeQNameValue(name)); } public void writeIntArrayAttribute(String prefix, String nsURI, String localName, int[] value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, getValueEncoder().encodeAsString(value, 0, value.length)); } public void writeLongArrayAttribute(String prefix, String nsURI, String localName, long[] value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, getValueEncoder().encodeAsString(value, 0, value.length)); } public void writeFloatArrayAttribute(String prefix, String nsURI, String localName, float[] value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, getValueEncoder().encodeAsString(value, 0, value.length)); } public void writeDoubleArrayAttribute(String prefix, String nsURI, String localName, double[] value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, getValueEncoder().encodeAsString(value, 0, value.length)); } public void writeBinaryAttribute(String prefix, String nsURI, String localName, byte[] value) throws XMLStreamException { writeBinaryAttribute(Base64Variants.getDefaultVariant(), prefix, nsURI, localName, value); } public void writeBinaryAttribute(Base64Variant v, String prefix, String nsURI, String localName, byte[] value) throws XMLStreamException { writeAttribute(prefix, nsURI, localName, getValueEncoder().encodeAsString(v, value, 0, value.length)); } /* //////////////////////////////////////////////////// // Abstract methods for sub-classes to implement //////////////////////////////////////////////////// */ protected abstract void appendLeaf(Node n) throws IllegalStateException; /* //////////////////////////////////////////////////// // Shared package methods //////////////////////////////////////////////////// */ /** * Method called to serialize given qualified name into valid * String serialization, taking into account existing namespace * bindings. */ protected String serializeQNameValue(QName name) throws XMLStreamException { String prefix; // Ok as is? In repairing mode need to ensure it's properly bound if (mNsRepairing) { String uri = name.getNamespaceURI(); // First: let's see if a valid binding already exists: NamespaceContext ctxt = getNamespaceContext(); prefix = (ctxt == null) ? null : ctxt.getPrefix(uri); if (prefix == null) { // nope: need to (try to) bind String origPrefix = name.getPrefix(); if (origPrefix == null || origPrefix.length() == 0) { prefix = ""; /* note: could cause a namespace conflict... but * there is nothing we can do with just stax1 stream * writer */ writeDefaultNamespace(uri); } else { prefix = origPrefix; writeNamespace(prefix, uri); } } } else { // in non-repairing, good as is prefix = name.getPrefix(); } String local = name.getLocalPart(); if (prefix == null || prefix.length() == 0) { return local; } // Not efficient... but should be ok return prefix + ":" + local; } protected SimpleValueEncoder getValueEncoder() { if (mValueEncoder == null) { mValueEncoder = new SimpleValueEncoder(); } return mValueEncoder; } /* //////////////////////////////////////////////////// // Package methods, basic output problem reporting //////////////////////////////////////////////////// */ protected static void throwOutputError(String msg) throws XMLStreamException { throw new XMLStreamException(msg); } protected static void throwOutputError(String format, Object arg) throws XMLStreamException { String msg = MessageFormat.format(format, new Object[] { arg }); throwOutputError(msg); } protected void reportUnsupported(String operName) { throw new UnsupportedOperationException(operName+" can not be used with DOM-backed writer"); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy