FileDocCategorySizeDatePackage
DOMSerializerImpl.javaAPI DocJava SE 5 API50637Fri Aug 26 14:56:02 BST 2005com.sun.org.apache.xml.internal.serialize

DOMSerializerImpl

public class DOMSerializerImpl extends Object implements LSSerializer, DOMConfiguration
EXPERIMENTAL: Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer by delegating serialization calls to XMLSerializer. 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: DOMSerializerImpl.java,v 1.21 2004/04/22 20:39:04 mrglavas Exp $

Fields Summary
private XMLSerializer
serializer
private XML11Serializer
xml11Serializer
private DOMStringList
fRecognizedParameters
protected short
features
REVISIT: Currently we handle 3 different configurations, would be nice just have one configuration that has different recognized parameters depending if it is used in Core/LS.
protected static final short
NAMESPACES
protected static final short
WELLFORMED
protected static final short
ENTITIES
protected static final short
CDATA
protected static final short
SPLITCDATA
protected static final short
COMMENTS
protected static final short
DISCARDDEFAULT
protected static final short
INFOSET
protected static final short
XMLDECL
protected static final short
NSDECL
protected static final short
DOM_ELEMENT_CONTENT_WHITESPACE
private DOMErrorHandler
fErrorHandler
private final DOMErrorImpl
fError
private final DOMLocatorImpl
fLocator
private static final RuntimeException
abort
Constructors Summary
public DOMSerializerImpl()
Constructs a new LSSerializer. The constructor turns on the namespace support in XMLSerializer and initializes the following fields: fNSBinder, fLocalNSBinder, fSymbolTable, fEmptySymbol, fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures.


                                   
      
        // set default features
        features |= NAMESPACES;
        features |= ENTITIES;
        features |= COMMENTS;
        features |= CDATA;
        features |= SPLITCDATA;
        features |= WELLFORMED;
        features |= NSDECL;
        features |= DOM_ELEMENT_CONTENT_WHITESPACE;
        features |= DISCARDDEFAULT;
        features |= XMLDECL;
             
        serializer = new XMLSerializer();
        initSerializer(serializer);
    
Methods Summary
public booleancanSetParameter(java.lang.String name, java.lang.Object state)
DOM L3-EXPERIMENTAL: Check if parameter can be set

		if (state instanceof Boolean){
			boolean value = ((Boolean)state).booleanValue();
			if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
			|| name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
			|| name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)
			|| name.equalsIgnoreCase(Constants.DOM_XMLDECL)
            || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
            || name.equalsIgnoreCase(Constants.DOM_INFOSET)
            || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
            || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
            || name.equalsIgnoreCase(Constants.DOM_COMMENTS)){
	            // both values supported
				return true;
			}
			else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
			    || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
			    || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
			    || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
			    || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
			    || name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)){
				// true is not supported
				return !value;
			}
			else if(name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)){
				return false;
			}
			else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
			        || name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
			        || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
				// false is not supported
				return value;
			        }
		}
		else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER) &&
				state == null || state instanceof DOMErrorHandler){
			return true;
		}
	    return false;
    
private voidcopySettings(com.sun.org.apache.xml.internal.serialize.XMLSerializer src, com.sun.org.apache.xml.internal.serialize.XMLSerializer dest)

        dest.fDOMErrorHandler = fErrorHandler;
        dest._format.setEncoding(src._format.getEncoding());
        dest._format.setLineSeparator(src._format.getLineSeparator());
        dest.fDOMFilter = src.fDOMFilter;
    
public org.w3c.dom.DOMConfigurationgetDomConfig()

        return this;
    
public org.w3c.dom.ls.LSSerializerFiltergetFilter()
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.

        return serializer.fDOMFilter;
    
public java.lang.StringgetNewLine()
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:
null
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".
CR
The carriage-return character (#xD).
CR-LF
The carriage-return and line-feed characters (#xD #xA).
LF
The line-feed character (#xA).

The default value for this attribute is null.

        return serializer._format.getLineSeparator();
    
public java.lang.ObjectgetParameter(java.lang.String name)
DOM L3-EXPERIMENTAL: Getter for boolean and object parameters

        if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
            return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
		} else if(name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)){
			return null;
        } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
            return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
            return (features & XMLDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
            return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
            return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
            return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
            return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE) ||
                   name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)
                    || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
            return Boolean.TRUE;
        }else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)){
            return ((features & DISCARDDEFAULT)!=0)?Boolean.TRUE:Boolean.FALSE;
        }else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)){
            if ((features & ENTITIES) == 0 &&
                 (features & CDATA) ==0 &&
                 (features & NAMESPACES) !=0 &&
                 (features & WELLFORMED) !=0 &&
                 (features & COMMENTS) !=0){
                     return Boolean.TRUE;
                 }                 
                 return Boolean.FALSE;
        } else if (name.equalsIgnoreCase (Constants.DOM_FORMAT_PRETTY_PRINT)
                || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
                || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
                || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
                || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
                || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
                || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
            return Boolean.FALSE;
        } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
            return fErrorHandler;
        } else if (
            name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
                || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
                || name.equalsIgnoreCase(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);
        }
    
public org.w3c.dom.DOMStringListgetParameterNames()
DOM Level 3 Core CR - Experimental. The list of the parameters supported by this DOMConfiguration 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.

    	
     	if (fRecognizedParameters == null){
			Vector parameters = new Vector();

			//Add DOM recognized parameters
			//REVISIT: Would have been nice to have a list of 
			//recognized parameters.
			parameters.add(Constants.DOM_NAMESPACES);
			parameters.add(Constants.DOM_SPLIT_CDATA);
			parameters.add(Constants.DOM_DISCARD_DEFAULT_CONTENT);
			parameters.add(Constants.DOM_XMLDECL);
			parameters.add(Constants.DOM_CANONICAL_FORM);
			parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
			parameters.add(Constants.DOM_VALIDATE);
			parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
			parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
			parameters.add(Constants.DOM_FORMAT_PRETTY_PRINT);
			//parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
			parameters.add(Constants.DOM_WELLFORMED);
			parameters.add(Constants.DOM_INFOSET);
			parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
			parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
			parameters.add(Constants.DOM_ENTITIES);
			parameters.add(Constants.DOM_CDATA_SECTIONS);
			parameters.add(Constants.DOM_COMMENTS);
			parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
			parameters.add(Constants.DOM_ERROR_HANDLER);
			//parameters.add(Constants.DOM_SCHEMA_LOCATION);
			//parameters.add(Constants.DOM_SCHEMA_TYPE);
			
			//Add recognized xerces features and properties
			
			fRecognizedParameters = new DOMStringListImpl(parameters);		
    		
    	}

    	return fRecognizedParameters; 	
    
private voidinitSerializer(com.sun.org.apache.xml.internal.serialize.XMLSerializer ser)

        ser.fNSBinder = new NamespaceSupport();
        ser.fLocalNSBinder = new NamespaceSupport();
        ser.fSymbolTable = new SymbolTable();	
    
private voidprepareForSerialization(com.sun.org.apache.xml.internal.serialize.XMLSerializer ser, org.w3c.dom.Node node)

        ser.reset();
        ser.features = features;
        ser.fDOMErrorHandler = fErrorHandler;
        ser.fNamespaces = (features & NAMESPACES) !=0;
        ser._format.setOmitComments((features & COMMENTS)==0);
        ser._format.setOmitXMLDeclaration((features & XMLDECL) == 0);   
 
        if ((features & WELLFORMED) != 0) {
            // REVISIT: this is inefficient implementation of well-formness. Instead, we should check
            // well-formness as we serialize the tree
            Node next, root;
            root = node;
            Method versionChanged;
            boolean verifyNames = true;
            Document document =(node.getNodeType() == Node.DOCUMENT_NODE)
                    ? (Document) node
                    : node.getOwnerDocument();
            try {
                versionChanged = document.getClass().getMethod("isXMLVersionChanged()", new Class[] {});
                if (versionChanged != null) {
                    verifyNames = ((Boolean)versionChanged.invoke(document, null)).booleanValue();
                }
            } catch (Exception e) {
                //no way to test the version...
                //ignore the exception
            }
            while (node != null) {
              verify(node, verifyNames, false);
              // Move down to first child
              next = node.getFirstChild();
              // No child nodes, so walk tree
              while (next == null) {
                // Move to sibling if possible.
                next = node.getNextSibling();
                if (next == null){
                    node = node.getParentNode();
                    if (root == node){
                        next = null;
                        break;                   
                    }
                    next = node.getNextSibling();
                }
              }
              node = next;
          }
 

        }
    
public voidsetFilter(org.w3c.dom.ls.LSSerializerFilter filter)
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.

        serializer.fDOMFilter = filter;
    
public voidsetNewLine(java.lang.String 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:
null
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".
CR
The carriage-return character (#xD).
CR-LF
The carriage-return and line-feed characters (#xD #xA).
LF
The line-feed character (#xA).

The default value for this attribute is null.

        serializer._format.setLineSeparator(newLine);
    
public voidsetParameter(java.lang.String name, java.lang.Object value)
DOM L3-EXPERIMENTAL: Setter for boolean and object parameters

        if (value instanceof Boolean) {
            boolean state = ((Boolean) value).booleanValue();
            if (name.equalsIgnoreCase(Constants.DOM_INFOSET)){
                if (state){
                    features &=~ENTITIES;
                    features &=~CDATA;
                    features |=NAMESPACES;
                    features |=WELLFORMED;
                    features |=COMMENTS;                 
                }
                // false does not have any effect
            } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
                features =
                    (short) (state ? features | XMLDECL : features & ~XMLDECL);                
            } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
                features =
                    (short) (state
                        ? features | NAMESPACES
                        : features & ~NAMESPACES);
                serializer.fNamespaces = state;
            } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
                features =
                    (short) (state
                        ? features | SPLITCDATA
                        : features & ~SPLITCDATA);
            } else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)) {
                features =
                    (short) (state
                        ? features | DISCARDDEFAULT
                        : features & ~DISCARDDEFAULT);
            } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
                features =
                    (short) (state
                        ? features | WELLFORMED
                        : features & ~WELLFORMED);
            } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)){
                features =
                    (short) (state
                        ? features | ENTITIES
                        : features & ~ENTITIES);
            }
            else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)){
                features =
                    (short) (state
                        ? features | CDATA
                        : features & ~CDATA);
                        }
            else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)){
                features =
                     (short) (state
                         ? features | COMMENTS
                         : features & ~COMMENTS);
            }
                else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
                    || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
                    || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
                    || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
                    || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
                    || name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)){
                // 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.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
                    || name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
                    || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
                // 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 if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
            if (value == null || value instanceof DOMErrorHandler) {
                fErrorHandler = (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.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
                || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
                || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)
                && value != null) {
            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);
        }
    
private voidverify(org.w3c.dom.Node node, boolean verifyNames, boolean xml11Version)


        int type = node.getNodeType();
        fLocator.fRelatedNode = node;
        boolean wellformed;
        switch (type) { 
            case Node.DOCUMENT_NODE:{
                break;
            }
            case Node.DOCUMENT_TYPE_NODE:{
                break;
            }
            case Node.ELEMENT_NODE:{               
                if (verifyNames){
                    if((features & NAMESPACES) != 0){
                        wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), xml11Version) ;
                    }
                    else{
                        wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , xml11Version);
                    }
                    if (!wellformed){
                            if (!wellformed){
                                if (fErrorHandler != null) {
                                    String msg = DOMMessageFormatter.formatMessage(
                                        DOMMessageFormatter.DOM_DOMAIN, 
                                        "wf-invalid-character-in-node-name", 
                                        new Object[]{"Element", node.getNodeName()});
                                        DOMNormalizer.reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR, 
                                        "wf-invalid-character-in-node-name");
                                }
                        
                            }                       
                    }
                }
                
                AttributeMap attributes = (node.hasAttributes()) ? (AttributeMap) node.getAttributes() : null; 
                if (attributes != null) {
                    for (int i = 0; i < attributes.getLength(); ++i) {
                        Attr attr = (Attr) attributes.item(i);
                        fLocator.fRelatedNode = attr;
                        DOMNormalizer.isAttrValueWF( fErrorHandler, fError, fLocator, 
                                      attributes,(AttrImpl) attr, attr.getValue(), xml11Version);
                        if (verifyNames) {
                            wellformed = CoreDocumentImpl.isXMLName( attr.getNodeName(), xml11Version);
                            if (!wellformed) {
                                    String msg =
                                        DOMMessageFormatter.formatMessage(
                                            DOMMessageFormatter.DOM_DOMAIN,
                                            "wf-invalid-character-in-node-name",
                                            new Object[] { "Attr", node.getNodeName()});
                                    DOMNormalizer.reportDOMError( fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
                                        "wf-invalid-character-in-node-name");
                            }
                        }
                    }

                }
                
                break;
            }
        
        case Node.COMMENT_NODE: {
            // only verify well-formness if comments included in the tree
            if ((features & COMMENTS) != 0)
                DOMNormalizer.isCommentWF(fErrorHandler, fError, fLocator, ((Comment)node).getData(), xml11Version);
            break;
        }
        case Node.ENTITY_REFERENCE_NODE: {
            // only if entity is preserved in the tree
            if (verifyNames && (features & ENTITIES) != 0){
                CoreDocumentImpl.isXMLName(node.getNodeName() , xml11Version);
            }
            break;
            
        }
        case Node.CDATA_SECTION_NODE: {
            // verify content
            DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
            // the ]]> string will be checked during serialization
            break;
        }
        case Node.TEXT_NODE:{
            DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
            break;
        }
        case Node.PROCESSING_INSTRUCTION_NODE:{
            ProcessingInstruction pinode = (ProcessingInstruction)node ;
            String target = pinode.getTarget();
            if (verifyNames) {
                if (xml11Version) {
                    wellformed = XML11Char.isXML11ValidName(target);
                } else {
                    wellformed = XMLChar.isValidName(target);
                }

                if (!wellformed) {
                    String msg =
                        DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN,
                            "wf-invalid-character-in-node-name",
                            new Object[] { "Element", node.getNodeName()});
                    DOMNormalizer.reportDOMError(
                        fErrorHandler,
                        fError,
                        fLocator,
                        msg,
                        DOMError.SEVERITY_FATAL_ERROR,
                        "wf-invalid-character-in-node-name");
                }
            }              
            DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), xml11Version);
            break;
        }        
        }
               
    
public booleanwrite(org.w3c.dom.Node node, org.w3c.dom.ls.LSOutput destination)
Serialize the specified node as described above in the general description of the LSSerializer interface. The output is written to the supplied LSOutput.
When writing to a LSOutput, the encoding is found by looking at the encoding information that is reachable through the LSOutput and the item to be written (or its owner document) in this order:
  1. LSOutput.encoding,
  2. Document.actualEncoding,
  3. Document.xmlEncoding.

If no encoding is reachable through the above properties, a default encoding of "UTF-8" will be used.
If the specified encoding is not supported an "unsupported-encoding" error is raised.
If no output is specified in the LSOutput, a "no-output-specified" error is raised.

param
node The node to serialize.
param
destination The destination for the serialized DOM.
return
Returns true if node was successfully serialized and false in case the node couldn't be serialized.


        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;
        }

        String encoding = null;
        if ((encoding = destination.getEncoding()) == null) {
            try {
                Method getEncoding =
                    fDocument.getClass().getMethod("getInputEncoding", 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 {
            prepareForSerialization(ser, node);
            ser._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);
                        }
                        throw new LSException(LSException.SERIALIZE_ERR, 
                            DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.SERIALIZER_DOMAIN, 
                                "no-output-specified", null));
                    }
                    else {
                        // URI was specified. Handle relative URIs.
                        String expanded = XMLEntityManager.expandSystemId(uri, null, true);
                        URL url = new URL(expanded != null ? expanded : uri);
                        OutputStream out = null;
                        String protocol = url.getProtocol();
                        String host = url.getHost();
                        // Use FileOutputStream if this URI is for a local file.
                        if (protocol.equals("file") 
                            && (host == null || host.length() == 0 || host.equals("localhost"))) {
                            // REVISIT: We have to decode %nn sequences. For
                            // now files containing spaces and other characters
                            // which were escaped in the URI will fail. -- mrglavas
                            out = new FileOutputStream(new File(url.getPath()));
                        }
                        // Try to write to some other kind of URI. Some protocols
                        // won't support this, though HTTP should work.
                        else {
                            URLConnection urlCon = url.openConnection();
                            urlCon.setDoInput(false);
                            urlCon.setDoOutput(true);
                            urlCon.setUseCaches(false); // Enable tunneling.
                            if (urlCon instanceof HttpURLConnection) {
                                // The DOM L3 LS CR says if we are writing to an HTTP URI
                                // it is to be done with an HTTP PUT. 
                                HttpURLConnection httpCon = (HttpURLConnection) urlCon;
                                httpCon.setRequestMethod("PUT");
                            }
                            out = urlCon.getOutputStream();
                        }
                        ser.setOutputByteStream(out);
                    }
                }
                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);
			}
            throw new LSException(LSException.SERIALIZE_ERR, 
                DOMMessageFormatter.formatMessage(
                    DOMMessageFormatter.SERIALIZER_DOMAIN, 
                    "unsupported-encoding", null));			
			//return false;
        } catch (RuntimeException e) {
            if (e == DOMNormalizer.abort){
                // stopped at user request
                return false;
            }
            throw new LSException(LSException.SERIALIZE_ERR, e.toString());            
        } 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);

            }   
            e.printStackTrace();       
            throw new LSException(LSException.SERIALIZE_ERR, e.toString());
        }
        return true;

    
public java.lang.StringwriteToString(org.w3c.dom.Node wnode)
DOM L3 EXPERIMENTAL: Serialize the specified node as described above in the description of LSSerializer. 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 null 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 DOMString.

        // 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;
        }

        StringWriter destination = new StringWriter();
        try {
            prepareForSerialization(ser, wnode);
            ser._format.setEncoding("UTF-16");
            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 (RuntimeException e) {
            if (e == DOMNormalizer.abort){
                // stopped at user request
                return null;
            }
            throw new LSException(LSException.SERIALIZE_ERR, e.toString());            
        } 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();
    
public booleanwriteToURI(org.w3c.dom.Node node, java.lang.String URI)
Serialize the specified node as described above in the general description of the LSSerializer interface. The output is written to the supplied URI.
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:
  1. Document.inputEncoding,
  2. Document.xmlEncoding.

If no encoding is reachable through the above properties, a default encoding of "UTF-8" will be used.
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 true if node was successfully serialized and false in case the node couldn't be serialized.

        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;
        }        

        try {
            Method getEncoding =
                fDocument.getClass().getMethod("getInputEncoding", 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 {
            prepareForSerialization(ser, node);
            ser._format.setEncoding(encoding);
            
            // URI was specified. Handle relative URIs.
            String expanded = XMLEntityManager.expandSystemId(URI, null, true);
            URL url = new URL(expanded != null ? expanded : URI);
            OutputStream out = null;
            String protocol = url.getProtocol();
            String host = url.getHost();
            // Use FileOutputStream if this URI is for a local file.
            if (protocol.equals("file") 
                && (host == null || host.length() == 0 || host.equals("localhost"))) {
                // REVISIT: We have to decode %nn sequences. For
                // now files containing spaces and other characters
                // which were escaped in the URI will fail. -- mrglavas
                out = new FileOutputStream(new File(url.getPath()));
            }
            // Try to write to some other kind of URI. Some protocols
            // won't support this, though HTTP should work.
            else {
                URLConnection urlCon = url.openConnection();
                urlCon.setDoInput(false);
                urlCon.setDoOutput(true);
                urlCon.setUseCaches(false); // Enable tunneling.
                if (urlCon instanceof HttpURLConnection) {
                    // The DOM L3 LS CR says if we are writing to an HTTP URI
                    // it is to be done with an HTTP PUT. 
                    HttpURLConnection httpCon = (HttpURLConnection) urlCon;
                    httpCon.setRequestMethod("PUT");
                }
                out = urlCon.getOutputStream();
            }
            ser.setOutputByteStream(out);

            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 (RuntimeException e) {
            if (e == DOMNormalizer.abort){
                // stopped at user request
                return false;
            }
            throw new LSException(LSException.SERIALIZE_ERR, e.toString());            
        } 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);
            }
            throw new LSException(LSException.SERIALIZE_ERR, e.toString());
        }
        return true;