| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999-2002 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xerces" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2002, International |
| * Business Machines, Inc., http://www.apache.org. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| |
| |
| package org.apache.xml.serialize; |
| |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.io.OutputStream; |
| import java.io.Writer; |
| import java.io.FileOutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.File; |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.Method; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| |
| import org.apache.xerces.dom.DOMErrorImpl; |
| import org.apache.xerces.dom.DOMMessageFormatter; |
| import org.apache.xerces.dom3.DOMConfiguration; |
| import org.apache.xerces.dom3.DOMError; |
| import org.apache.xerces.dom3.DOMErrorHandler; |
| import org.apache.xerces.dom3.DOMStringList; |
| |
| import org.apache.xerces.impl.Constants; |
| import org.apache.xerces.util.NamespaceSupport; |
| import org.apache.xerces.util.SymbolTable; |
| import org.w3c.dom.DOMException; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentFragment; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.ls.LSSerializer; |
| import org.w3c.dom.ls.LSSerializerFilter; |
| import org.w3c.dom.ls.LSOutput; |
| |
| |
| /** |
| * Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer by delegating serialization |
| * calls to <CODE>XMLSerializer</CODE>. |
| * LSSerializer provides an API for serializing (writing) a DOM document out in an |
| * XML document. The XML data is written to an output stream. |
| * During serialization of XML data, namespace fixup is done when possible as |
| * defined in DOM Level 3 Core, Appendix B. |
| * |
| * @author Elena Litani, IBM |
| * @author Gopal Sharma, Sun Microsystems |
| * @author Arun Yadav, Sun Microsystems |
| * @version $Id$ |
| */ |
| public class DOMSerializerImpl implements LSSerializer, DOMConfiguration { |
| |
| // data |
| // serializer |
| private XMLSerializer serializer; |
| |
| // XML 1.1 serializer |
| private XML11Serializer xml11Serializer; |
| |
| /** |
| * Constructs a new LSSerializer. |
| * The constructor turns on the namespace support in <code>XMLSerializer</code> and |
| * initializes the following fields: fNSBinder, fLocalNSBinder, fSymbolTable, |
| * fEmptySymbol, fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures. |
| */ |
| public DOMSerializerImpl() { |
| serializer = new XMLSerializer(); |
| initSerializer(serializer); |
| } |
| |
| |
| |
| // |
| // LSSerializer methods |
| // |
| |
| public DOMConfiguration getConfig(){ |
| return this; |
| } |
| |
| /** DOM L3-EXPERIMENTAL: |
| * Setter for boolean and object parameters |
| */ |
| public void setParameter(String name, Object value) throws DOMException { |
| if (serializer.fFeatures.containsKey(name)) { |
| // This is a feature |
| if (value instanceof Boolean){ |
| boolean state = ((Boolean)value).booleanValue(); |
| if (name.equals(Constants.DOM_XMLDECL)){ |
| serializer._format.setOmitXMLDeclaration(!state); |
| serializer.fFeatures.put(name, value); |
| } |
| else if (name.equals(Constants.DOM_NAMESPACES)){ |
| serializer.fNamespaces = state; |
| serializer.fFeatures.put(name, value); |
| } |
| else if (name.equals(Constants.DOM_SPLIT_CDATA) |
| || name.equals(Constants.DOM_DISCARD_DEFAULT_CONTENT)){ |
| // both values supported |
| serializer.fFeatures.put(name, value); |
| } |
| else if (name.equals(Constants.DOM_CANONICAL_FORM) |
| || name.equals(Constants.DOM_VALIDATE_IF_SCHEMA) |
| || name.equals(Constants.DOM_VALIDATE) |
| || name.equals(Constants.DOM_CHECK_CHAR_NORMALIZATION) |
| || name.equals(Constants.DOM_DATATYPE_NORMALIZATION) |
| || name.equals(Constants.DOM_FORMAT_PRETTY_PRINT) |
| || name.equals(Constants.DOM_NORMALIZE_CHARACTERS) |
| // REVISIT: these must be supported |
| || name.equals(Constants.DOM_WELLFORMED)) { |
| // true is not supported |
| if (state){ |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_SUPPORTED", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); |
| } |
| } |
| else if (name.equals(Constants.DOM_INFOSET) |
| || name.equals(Constants.DOM_NAMESPACE_DECLARATIONS) |
| || name.equals(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT) |
| || name.equals(Constants.DOM_IGNORE_CHAR_DENORMALIZATION) |
| // REVISIT: these must be supported |
| || name.equals(Constants.DOM_ENTITIES) |
| || name.equals(Constants.DOM_CDATA_SECTIONS) |
| || name.equals(Constants.DOM_COMMENTS)) { |
| // false is not supported |
| if (!state){ |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_SUPPORTED", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); |
| } |
| } |
| else { |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_FOUND", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); |
| } |
| } |
| else { |
| |
| // REVISIT: modify error exception to TYPE_MISMATCH |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "TYPE_MISMATCH_ERR", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_FOUND_ERR, msg); |
| } |
| } |
| else if (name.equals(Constants.DOM_ERROR_HANDLER)) { |
| if (value instanceof DOMErrorHandler) { |
| serializer.fDOMErrorHandler = (DOMErrorHandler) value; |
| } |
| else { |
| // REVISIT: modify error exception to TYPE_MISMATCH |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "TYPE_MISMATCH_ERR", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_FOUND_ERR, msg); |
| } |
| } |
| else if (name.equals(Constants.DOM_RESOURCE_RESOLVER) |
| || name.equals(Constants.DOM_SCHEMA_LOCATION) |
| || name.equals(Constants.DOM_SCHEMA_TYPE)) { |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_SUPPORTED", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); |
| } |
| else { |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_FOUND", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_FOUND_ERR, msg); |
| } |
| } |
| |
| /** DOM L3-EXPERIMENTAL: |
| * Check if parameter can be set |
| */ |
| public boolean canSetParameter(String name, Object state) { |
| if (state instanceof Boolean){ |
| boolean value = ((Boolean)state).booleanValue(); |
| if (name.equals(Constants.DOM_NAMESPACES) |
| || name.equals(Constants.DOM_SPLIT_CDATA) |
| || name.equals(Constants.DOM_DISCARD_DEFAULT_CONTENT) |
| || name.equals(Constants.DOM_XMLDECL)){ |
| // both values supported |
| return true; |
| } |
| else if (name.equals(Constants.DOM_CANONICAL_FORM) |
| || name.equals(Constants.DOM_VALIDATE_IF_SCHEMA) |
| || name.equals(Constants.DOM_VALIDATE) |
| || name.equals(Constants.DOM_CHECK_CHAR_NORMALIZATION) |
| || name.equals(Constants.DOM_DATATYPE_NORMALIZATION) |
| || name.equals(Constants.DOM_FORMAT_PRETTY_PRINT) |
| || name.equals(Constants.DOM_NORMALIZE_CHARACTERS) |
| // REVISIT: these must be supported |
| || name.equals(Constants.DOM_WELLFORMED)) { |
| // true is not supported |
| return !value; |
| } |
| else if (name.equals(Constants.DOM_INFOSET) |
| || name.equals(Constants.DOM_NAMESPACE_DECLARATIONS) |
| || name.equals(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT) |
| || name.equals(Constants.DOM_IGNORE_CHAR_DENORMALIZATION) |
| // REVISIT: these must be supported |
| || name.equals(Constants.DOM_ENTITIES) |
| || name.equals(Constants.DOM_CDATA_SECTIONS) |
| || name.equals(Constants.DOM_COMMENTS)) { |
| // false is not supported |
| return value; |
| } |
| } |
| else if (name.equals(Constants.DOM_ERROR_HANDLER)){ |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * DOM Level 3 Core CR - Experimental. |
| * |
| * The list of the parameters supported by this |
| * <code>DOMConfiguration</code> object and for which at least one value |
| * can be set by the application. Note that this list can also contain |
| * parameter names defined outside this specification. |
| */ |
| public DOMStringList getParameterNames() { |
| //REVISIT |
| return null; |
| } |
| |
| /** DOM L3-EXPERIMENTAL: |
| * Getter for boolean and object parameters |
| */ |
| public Object getParameter(String name) throws DOMException { |
| Object state = serializer.fFeatures.get(name); |
| if (state == null) { |
| if (name.equals(Constants.DOM_ERROR_HANDLER)) { |
| return serializer.fDOMErrorHandler; |
| } |
| else if (name.equals(Constants.DOM_RESOURCE_RESOLVER) |
| || name.equals(Constants.DOM_SCHEMA_LOCATION) |
| || name.equals(Constants.DOM_SCHEMA_TYPE)) { |
| String msg = |
| DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_SUPPORTED", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg); |
| } |
| else { |
| String msg = |
| DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "FEATURE_NOT_FOUND", |
| new Object[] { name }); |
| throw new DOMException(DOMException.NOT_FOUND_ERR, msg); |
| } |
| } |
| |
| return ((Boolean) state); |
| } |
| |
| /** |
| * DOM L3 EXPERIMENTAL: |
| * Serialize the specified node as described above in the description of |
| * <code>LSSerializer</code>. The result of serializing the node is |
| * returned as a string. Writing a Document or Entity node produces a |
| * serialized form that is well formed XML. Writing other node types |
| * produces a fragment of text in a form that is not fully defined by |
| * this document, but that should be useful to a human for debugging or |
| * diagnostic purposes. |
| * @param wnode The node to be written. |
| * @return Returns the serialized data, or <code>null</code> in case a |
| * failure occured and the failure wasn't canceled by the error |
| * handler. |
| * @exception DOMException |
| * DOMSTRING_SIZE_ERR: The resulting string is too long to fit in a |
| * <code>DOMString</code>. |
| */ |
| public String writeToString(Node wnode) |
| throws DOMException { |
| // determine which serializer to use: |
| Document doc = (wnode.getNodeType() == Node.DOCUMENT_NODE)?(Document)wnode:wnode.getOwnerDocument(); |
| Method getVersion = null; |
| XMLSerializer ser = null; |
| String ver = null; |
| // this should run under JDK 1.1.8... |
| try { |
| getVersion = doc.getClass().getMethod("getXmlVersion", new Class[]{}); |
| if(getVersion != null ) { |
| ver = (String)getVersion.invoke(doc, null); |
| } |
| } catch (Exception e) { |
| // no way to test the version... |
| // ignore the exception |
| } |
| if(ver != null && ver.equals("1.1")) { |
| if(xml11Serializer == null) { |
| xml11Serializer = new XML11Serializer(); |
| initSerializer(xml11Serializer); |
| } |
| // copy setting from "main" serializer to XML 1.1 serializer |
| copySettings(serializer, xml11Serializer); |
| ser = xml11Serializer; |
| } else { |
| ser = serializer; |
| } |
| checkAllFeatures(ser); |
| StringWriter destination = new StringWriter(); |
| try { |
| ser.reset(); |
| ser.setOutputCharStream(destination); |
| if (wnode == null) |
| return null; |
| else if (wnode.getNodeType() == Node.DOCUMENT_NODE) |
| ser.serialize((Document)wnode); |
| else if (wnode.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) |
| ser.serialize((DocumentFragment)wnode); |
| else if (wnode.getNodeType() == Node.ELEMENT_NODE) |
| ser.serialize((Element)wnode); |
| else |
| return null; |
| } catch (IOException ioe) { |
| String msg = DOMMessageFormatter.formatMessage( |
| DOMMessageFormatter.DOM_DOMAIN, |
| "STRING_TOO_LONG", |
| new Object[] { ioe.getMessage()}); |
| throw new DOMException(DOMException.DOMSTRING_SIZE_ERR,msg); |
| } |
| return destination.toString(); |
| } |
| |
| /** |
| * DOM L3 EXPERIMENTAL: |
| * The end-of-line sequence of characters to be used in the XML being |
| * written out. The only permitted values are these: |
| * <dl> |
| * <dt><code>null</code></dt> |
| * <dd> |
| * Use a default end-of-line sequence. DOM implementations should choose |
| * the default to match the usual convention for text files in the |
| * environment being used. Implementations must choose a default |
| * sequence that matches one of those allowed by 2.11 "End-of-Line |
| * Handling". </dd> |
| * <dt>CR</dt> |
| * <dd>The carriage-return character (#xD).</dd> |
| * <dt>CR-LF</dt> |
| * <dd> The |
| * carriage-return and line-feed characters (#xD #xA). </dd> |
| * <dt>LF</dt> |
| * <dd> The line-feed |
| * character (#xA). </dd> |
| * </dl> |
| * <br>The default value for this attribute is <code>null</code>. |
| */ |
| public void setNewLine(String newLine) { |
| serializer._format.setLineSeparator(newLine); |
| } |
| |
| |
| /** |
| * DOM L3 EXPERIMENTAL: |
| * The end-of-line sequence of characters to be used in the XML being |
| * written out. The only permitted values are these: |
| * <dl> |
| * <dt><code>null</code></dt> |
| * <dd> |
| * Use a default end-of-line sequence. DOM implementations should choose |
| * the default to match the usual convention for text files in the |
| * environment being used. Implementations must choose a default |
| * sequence that matches one of those allowed by 2.11 "End-of-Line |
| * Handling". </dd> |
| * <dt>CR</dt> |
| * <dd>The carriage-return character (#xD).</dd> |
| * <dt>CR-LF</dt> |
| * <dd> The |
| * carriage-return and line-feed characters (#xD #xA). </dd> |
| * <dt>LF</dt> |
| * <dd> The line-feed |
| * character (#xA). </dd> |
| * </dl> |
| * <br>The default value for this attribute is <code>null</code>. |
| */ |
| public String getNewLine() { |
| return serializer._format.getLineSeparator(); |
| } |
| |
| |
| /** |
| * When the application provides a filter, the serializer will call out |
| * to the filter before serializing each Node. Attribute nodes are never |
| * passed to the filter. The filter implementation can choose to remove |
| * the node from the stream or to terminate the serialization early. |
| */ |
| public LSSerializerFilter getFilter(){ |
| return serializer.fDOMFilter; |
| } |
| /** |
| * When the application provides a filter, the serializer will call out |
| * to the filter before serializing each Node. Attribute nodes are never |
| * passed to the filter. The filter implementation can choose to remove |
| * the node from the stream or to terminate the serialization early. |
| */ |
| public void setFilter(LSSerializerFilter filter){ |
| serializer.fDOMFilter = filter; |
| } |
| |
| |
| private void checkAllFeatures(XMLSerializer ser) { |
| if (getParameter(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT) == Boolean.TRUE) |
| ser._format.setPreserveSpace(true); |
| else |
| ser._format.setPreserveSpace(false); |
| } |
| |
| // this initializes a newly-created serializer |
| private void initSerializer(XMLSerializer ser) { |
| ser.fNamespaces = true; |
| ser.fNSBinder = new NamespaceSupport(); |
| ser.fLocalNSBinder = new NamespaceSupport(); |
| ser.fSymbolTable = new SymbolTable(); |
| ser.fFeatures = new Hashtable(); |
| ser.fFeatures.put(Constants.DOM_NAMESPACES, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_NORMALIZE_CHARACTERS, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_VALIDATE_IF_SCHEMA, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_VALIDATE, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_ENTITIES, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_SPLIT_CDATA, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_CDATA_SECTIONS, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_COMMENTS, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_DISCARD_DEFAULT_CONTENT, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_CANONICAL_FORM, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_FORMAT_PRETTY_PRINT, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_XMLDECL, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_CHECK_CHAR_NORMALIZATION, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_DATATYPE_NORMALIZATION, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_NORMALIZE_CHARACTERS, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_WELLFORMED, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_INFOSET, Boolean.FALSE); |
| ser.fFeatures.put(Constants.DOM_NAMESPACE_DECLARATIONS, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_WHITESPACE_IN_ELEMENT_CONTENT, Boolean.TRUE); |
| ser.fFeatures.put(Constants.DOM_IGNORE_CHAR_DENORMALIZATION, Boolean.TRUE); |
| } |
| |
| // copies all settings that could have been modified |
| // by calls to LSSerializer methods from one serializer to another. |
| // IMPORTANT: if new methods are implemented or more settings of |
| // the serializer are made alterable, this must be |
| // reflected in this method! |
| private void copySettings(XMLSerializer src, XMLSerializer dest) { |
| dest._format.setOmitXMLDeclaration(src._format.getOmitXMLDeclaration()); |
| dest.fNamespaces = src.fNamespaces; |
| dest.fDOMErrorHandler = src.fDOMErrorHandler; |
| dest._format.setEncoding(src._format.getEncoding()); |
| dest._format.setLineSeparator(src._format.getLineSeparator()); |
| dest.fDOMFilter = src.fDOMFilter; |
| // and copy over all the entries in fFeatures: |
| Enumeration keys = src.fFeatures.keys(); |
| while(keys.hasMoreElements()) { |
| Object key = keys.nextElement(); |
| Object val = src.fFeatures.get(key); |
| dest.fFeatures.put(key,val); |
| } |
| }//copysettings |
| |
| /** |
| * Serialize the specified node as described above in the general |
| * description of the <code>LSSerializer</code> interface. The output |
| * is written to the supplied <code>LSOutput</code>. |
| * <br> When writing to a <code>LSOutput</code>, the encoding is found by |
| * looking at the encoding information that is reachable through the |
| * <code>LSOutput</code> and the item to be written (or its owner |
| * document) in this order: |
| * <ol> |
| * <li> <code>LSOutput.encoding</code>, |
| * </li> |
| * <li> |
| * <code>Document.actualEncoding</code>, |
| * </li> |
| * <li> |
| * <code>Document.xmlEncoding</code>. |
| * </li> |
| * </ol> |
| * <br> If no encoding is reachable through the above properties, a |
| * default encoding of "UTF-8" will be used. |
| * <br> If the specified encoding is not supported an |
| * "unsupported-encoding" error is raised. |
| * <br> If no output is specified in the <code>LSOutput</code>, a |
| * "no-output-specified" error is raised. |
| * @param node The node to serialize. |
| * @param destination The destination for the serialized DOM. |
| * @return Returns <code>true</code> if <code>node</code> was |
| * successfully serialized and <code>false</code> in case the node |
| * couldn't be serialized. |
| */ |
| public boolean write(Node node, LSOutput destination) { |
| |
| if (node == null) |
| return false; |
| |
| Method getVersion = null; |
| XMLSerializer ser = null; |
| String ver = null; |
| Document fDocument =(node.getNodeType() == Node.DOCUMENT_NODE) |
| ? (Document) node |
| : node.getOwnerDocument(); |
| // this should run under JDK 1.1.8... |
| try { |
| getVersion = fDocument.getClass().getMethod("getXmlVersion", new Class[] {}); |
| if (getVersion != null) { |
| ver = (String) getVersion.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| //no way to test the version... |
| //ignore the exception |
| } |
| //determine which serializer to use: |
| if (ver != null && ver.equals("1.1")) { |
| if (xml11Serializer == null) { |
| xml11Serializer = new XML11Serializer(); |
| initSerializer(xml11Serializer); |
| } |
| //copy setting from "main" serializer to XML 1.1 serializer |
| copySettings(serializer, xml11Serializer); |
| ser = xml11Serializer; |
| } else { |
| ser = serializer; |
| } |
| checkAllFeatures(ser); |
| |
| String encoding = null; |
| if ((encoding = destination.getEncoding()) == null) { |
| try { |
| Method getEncoding = |
| fDocument.getClass().getMethod("getActualEncoding", new Class[] {}); |
| if (getEncoding != null) { |
| encoding = (String) getEncoding.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| // ignore the exception |
| } |
| if (encoding == null) { |
| try { |
| Method getEncoding = |
| fDocument.getClass().getMethod("getXmlEncoding", new Class[] {}); |
| if (getEncoding != null) { |
| encoding = (String) getEncoding.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| // ignore the exception |
| } |
| if (encoding == null) { |
| encoding = "UTF-8"; |
| } |
| } |
| } |
| try { |
| ser.reset(); |
| serializer._format.setEncoding(encoding); |
| OutputStream outputStream = destination.getByteStream(); |
| Writer writer = destination.getCharacterStream(); |
| String uri = destination.getSystemId(); |
| if (writer == null) { |
| if (outputStream == null) { |
| if (uri == null) { |
| if (ser.fDOMErrorHandler != null) { |
| DOMErrorImpl error = new DOMErrorImpl(); |
| error.fType = "no-output-specified"; |
| error.fMessage = "no-output-specified"; |
| error.fSeverity = DOMError.SEVERITY_FATAL_ERROR; |
| ser.fDOMErrorHandler.handleError(error); |
| } |
| return false; |
| } |
| else { |
| // uri was specified |
| FileOutputStream fileOut = new FileOutputStream(new File(uri)); |
| ser.setOutputCharStream( new OutputStreamWriter(fileOut, encoding)); |
| } |
| } |
| else { |
| // byte stream was specified |
| ser.setOutputByteStream(outputStream); |
| } |
| } |
| else { |
| // character stream is specified |
| ser.setOutputCharStream(writer); |
| } |
| |
| if (node.getNodeType() == Node.DOCUMENT_NODE) |
| ser.serialize((Document) node); |
| else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) |
| ser.serialize((DocumentFragment) node); |
| else if (node.getNodeType() == Node.ELEMENT_NODE) |
| ser.serialize((Element) node); |
| else |
| return false; |
| } catch( UnsupportedEncodingException ue) { |
| if (ser.fDOMErrorHandler != null) { |
| DOMErrorImpl error = new DOMErrorImpl(); |
| error.fException = ue; |
| error.fType = "unsupported-encoding"; |
| error.fMessage = ue.getMessage(); |
| error.fSeverity = DOMError.SEVERITY_FATAL_ERROR; |
| ser.fDOMErrorHandler.handleError(error); |
| } |
| return false; |
| } catch (Exception e) { |
| if (ser.fDOMErrorHandler != null) { |
| DOMErrorImpl error = new DOMErrorImpl(); |
| error.fException = e; |
| error.fMessage = e.getMessage(); |
| error.fSeverity = DOMError.SEVERITY_ERROR; |
| ser.fDOMErrorHandler.handleError(error); |
| |
| } |
| return false; |
| } |
| return true; |
| |
| } //write |
| |
| /** |
| * Serialize the specified node as described above in the general |
| * description of the <code>LSSerializer</code> interface. The output |
| * is written to the supplied URI. |
| * <br> When writing to a URI, the encoding is found by looking at the |
| * encoding information that is reachable through the item to be written |
| * (or its owner document) in this order: |
| * <ol> |
| * <li> |
| * <code>Document.actualEncoding</code>, |
| * </li> |
| * <li> |
| * <code>Document.xmlEncoding</code>. |
| * </li> |
| * </ol> |
| * <br> If no encoding is reachable through the above properties, a |
| * default encoding of "UTF-8" will be used. |
| * <br> If the specified encoding is not supported an |
| * "unsupported-encoding" error is raised. |
| * @param node The node to serialize. |
| * @param URI The URI to write to. |
| * @return Returns <code>true</code> if <code>node</code> was |
| * successfully serialized and <code>false</code> in case the node |
| * couldn't be serialized. |
| */ |
| public boolean writeToURI(Node node, String URI) { |
| if (node == null){ |
| return false; |
| } |
| |
| Method getXmlVersion = null; |
| XMLSerializer ser = null; |
| String ver = null; |
| String encoding = null; |
| |
| Document fDocument =(node.getNodeType() == Node.DOCUMENT_NODE) |
| ? (Document) node |
| : node.getOwnerDocument(); |
| // this should run under JDK 1.1.8... |
| try { |
| getXmlVersion = |
| fDocument.getClass().getMethod("getXmlVersion", new Class[] {}); |
| if (getXmlVersion != null) { |
| ver = (String) getXmlVersion.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| // no way to test the version... |
| // ignore the exception |
| } |
| if (ver != null && ver.equals("1.1")) { |
| if (xml11Serializer == null) { |
| xml11Serializer = new XML11Serializer(); |
| initSerializer(xml11Serializer); |
| } |
| // copy setting from "main" serializer to XML 1.1 serializer |
| copySettings(serializer, xml11Serializer); |
| ser = xml11Serializer; |
| } else { |
| ser = serializer; |
| } |
| checkAllFeatures(ser); |
| |
| try { |
| Method getEncoding = |
| fDocument.getClass().getMethod("getActualEncoding", new Class[] {}); |
| if (getEncoding != null) { |
| encoding = (String) getEncoding.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| // ignore the exception |
| } |
| if (encoding == null) { |
| try { |
| Method getEncoding = |
| fDocument.getClass().getMethod("getXmlEncoding", new Class[] {}); |
| if (getEncoding != null) { |
| encoding = (String) getEncoding.invoke(fDocument, null); |
| } |
| } catch (Exception e) { |
| // ignore the exception |
| } |
| if (encoding == null) { |
| encoding = "UTF-8"; |
| } |
| } |
| |
| try { |
| ser.reset(); |
| FileOutputStream fileOut = new FileOutputStream(new File(URI)); |
| ser.setOutputCharStream(new OutputStreamWriter(fileOut, encoding)); |
| |
| if (node.getNodeType() == Node.DOCUMENT_NODE) |
| ser.serialize((Document) node); |
| else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) |
| ser.serialize((DocumentFragment) node); |
| else if (node.getNodeType() == Node.ELEMENT_NODE) |
| ser.serialize((Element) node); |
| else |
| return false; |
| } catch (Exception e) { |
| if (ser.fDOMErrorHandler != null) { |
| DOMErrorImpl error = new DOMErrorImpl(); |
| error.fException = e; |
| error.fMessage = e.getMessage(); |
| error.fSeverity = DOMError.SEVERITY_ERROR; |
| ser.fDOMErrorHandler.handleError(error); |
| } |
| return false; |
| } |
| return true; |
| } //writeURI |
| |
| }//DOMSerializerImpl |
| |
| |
| |
| |