FileDocCategorySizeDatePackage
DOMNormalizer.javaAPI DocApache Xerces 3.0.196244Fri Sep 14 20:33:54 BST 2007org.apache.xerces.dom

DOMNormalizer

public class DOMNormalizer extends Object implements org.apache.xerces.xni.XMLDocumentHandler
This class adds implementation for normalizeDocument method. It acts as if the document was going through a save and load cycle, putting the document in a "normal" form. The actual result depends on the features being set and governing what operations actually take place. See setNormalizationFeature for details. Noticeably this method normalizes Text nodes, makes the document "namespace wellformed", according to the algorithm described below in pseudo code, by adding missing namespace declaration attributes and adding or changing namespace prefixes, updates the replacement tree of EntityReference nodes, normalizes attribute values, etc. Mutation events, when supported, are generated to reflect the changes occuring on the document. See Namespace normalization for details on how namespace declaration attributes and prefixes are normalized. NOTE: There is an initial support for DOM revalidation with XML Schema as a grammar. The tree might not be validated correctly if entityReferences, CDATA sections are present in the tree. The PSVI information is not exposed, normalized data (including element default content is not available).
xerces.experimental
author
Elena Litani, IBM
author
Neeraj Bajaj, Sun Microsystems, inc.
version
$Id: DOMNormalizer.java 541770 2007-05-25 20:17:48Z mrglavas $

Fields Summary
protected static final boolean
DEBUG_ND
Debug normalize document
protected static final boolean
DEBUG
Debug namespace fix up algorithm
protected static final boolean
DEBUG_EVENTS
Debug document handler events
protected static final String
PREFIX
prefix added by namespace fixup algorithm should follow a pattern "NS" + index
protected DOMConfigurationImpl
fConfiguration
protected CoreDocumentImpl
fDocument
protected final XMLAttributesProxy
fAttrProxy
protected final org.apache.xerces.xni.QName
fQName
protected org.apache.xerces.impl.RevalidationHandler
fValidationHandler
Validation handler represents validator instance.
protected org.apache.xerces.util.SymbolTable
fSymbolTable
symbol table
protected DOMErrorHandler
fErrorHandler
error handler. may be null.
private final DOMErrorImpl
fError
Cached {@link DOMError} impl. The same object is re-used to report multiple errors.
protected boolean
fNamespaceValidation
protected boolean
fPSVI
protected final org.apache.xerces.xni.NamespaceContext
fNamespaceContext
The namespace context of this document: stores namespaces in scope
protected final org.apache.xerces.xni.NamespaceContext
fLocalNSBinder
Stores all namespace bindings on the current element
protected final Vector
fAttributeList
list of attributes
protected final DOMLocatorImpl
fLocator
DOM Locator - for namespace fixup algorithm
protected Node
fCurrentNode
for setting the PSVI
private org.apache.xerces.xni.QName
fAttrQName
final org.apache.xerces.xni.XMLString
fNormalizedValue
public static final RuntimeException
abort
If the user stops the process, this exception will be thrown.
public static final org.apache.xerces.xni.XMLString
EMPTY_STRING
Empty string to pass to the validator.
private boolean
fAllWhitespace
Constructors Summary
public DOMNormalizer()

    
    // Constructor
    // 

     
Methods Summary
protected final voidaddNamespaceDecl(java.lang.String prefix, java.lang.String uri, ElementImpl element)
Adds a namespace attribute or replaces the value of existing namespace attribute with the given prefix and value for URI. In case prefix is empty will add/update default namespace declaration.

param
prefix
param
uri
exception
IOException

        if (DEBUG) {
            System.out.println("[ns-fixup] addNamespaceDecl ["+prefix+"]");
        }
        if (prefix == XMLSymbols.EMPTY_STRING) {
            if (DEBUG) {
                System.out.println("=>add xmlns=\""+uri+"\" declaration");
            }
            element.setAttributeNS(NamespaceContext.XMLNS_URI, XMLSymbols.PREFIX_XMLNS, uri);             
        } else {
            if (DEBUG) {
                System.out.println("=>add xmlns:"+prefix+"=\""+uri+"\" declaration");
            }
            element.setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"+prefix, uri); 
        }
    
public voidcharacters(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Character content.

param
text The content.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidcomment(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
A comment.

param
text The text in the comment.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by application to signal an error.

    
public voiddoctypeDecl(java.lang.String rootElement, java.lang.String publicId, java.lang.String systemId, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of the DOCTYPE line in the document.

param
rootElement The name of the root element.
param
publicId The public identifier if an external DTD or null if the external DTD is specified using SYSTEM.
param
systemId The system identifier if an external DTD, null otherwise.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidemptyElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
An empty element.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        if (DEBUG_EVENTS) {
            System.out.println("==>emptyElement: " +element);
        }

		startElement(element, attributes, augs);
        endElement(element, augs);
	
public voidendCDATA(org.apache.xerces.xni.Augmentations augs)
The end of a CDATA section.

param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidendDocument(org.apache.xerces.xni.Augmentations augs)
The end of the document.

param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidendElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs)
The end of an element.

param
element The name of the element.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        if (DEBUG_EVENTS) {
            System.out.println("==>endElement: " + element);
        }

        if (augs != null) {
            ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
            if (elementPSVI != null) {
                ElementImpl elementNode = (ElementImpl) fCurrentNode;
                if (fPSVI) {
                    ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
                }
                // Updating the TypeInfo for this element.
                if (elementNode instanceof ElementNSImpl) {
                    XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
                    if (type == null) {
                        type = elementPSVI.getTypeDefinition();
                    }
                    ((ElementNSImpl) elementNode).setType(type);
                }
                // include element default content (if one is available)
                String normalizedValue = elementPSVI.getSchemaNormalizedValue();
                if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
                    if (normalizedValue !=null)
                        elementNode.setTextContent(normalizedValue);
                }
                else {
                    // NOTE: this is a hack: it is possible that DOM had an empty element
                    // and validator sent default value using characters(), which we don't 
                    // implement. Thus, here we attempt to add the default value.
                    String text = elementNode.getTextContent();
                    if (text.length() == 0) {
                        // default content could be provided
                        if (normalizedValue !=null)
                            elementNode.setTextContent(normalizedValue);
                    }
                }
                return;
            }
        }
        // DTD; elements have no type.
        if (fCurrentNode instanceof ElementNSImpl) { 
            ((ElementNSImpl) fCurrentNode).setType(null);
        }
    
public voidendGeneralEntity(java.lang.String name, org.apache.xerces.xni.Augmentations augs)
This method notifies the end of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the entity.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
protected final voidexpandEntityRef(org.w3c.dom.Node parent, org.w3c.dom.Node reference)

        Node kid, next;
        for (kid = reference.getFirstChild(); kid != null; kid = next) {
            next = kid.getNextSibling();
            parent.insertBefore(kid, reference);
        }
    
public org.apache.xerces.xni.parser.XMLDocumentSourcegetDocumentSource()
Returns the document source.

        return null;
    
public voidignorableWhitespace(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Ignorable whitespace. For this method to be called, the document source must have some way of determining that the text containing only whitespace characters should be considered ignorable. For example, the validator can determine if a length of whitespace characters in the document are ignorable based on the element content model.

param
text The ignorable whitespace.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        fAllWhitespace = true;
    
public static final voidisAttrValueWF(org.w3c.dom.DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, org.w3c.dom.NamedNodeMap attributes, org.w3c.dom.Attr a, java.lang.String value, boolean xml11Version)
NON-DOM: check if attribute value is well-formed

param
attributes
param
a
param
value

        if (a instanceof AttrImpl && ((AttrImpl)a).hasStringValue()) {
            isXMLCharWF(errorHandler, error, locator, value, xml11Version);
        } else {
        	NodeList children = a.getChildNodes(); 
            //check each child node of the attribute's value
            for (int j = 0; j < children.getLength(); j++) {
                Node child = children.item(j);
                //If the attribute's child is an entity refernce
                if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
                    Document owner = a.getOwnerDocument();
                    Entity ent = null;
                    //search for the entity in the docType
                    //of the attribute's ownerDocument
                    if (owner != null) {
                        DocumentType docType = owner.getDoctype();
                        if (docType != null) {
                            NamedNodeMap entities = docType.getEntities();
                            ent = (Entity) entities.getNamedItemNS(
                                    "*",
                                    child.getNodeName());
                        }
                    }
                    //If the entity was not found issue a fatal error
                    if (ent == null) {
                        String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, "UndeclaredEntRefInAttrValue", 
                            new Object[]{a.getNodeName()});
                        reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 
                            "UndeclaredEntRefInAttrValue");
                    }
                }
                else {
                    // Text node
                    isXMLCharWF(errorHandler, error, locator, child.getNodeValue(), xml11Version);
                }
            }
        }
    
public static final voidisCDataWF(org.w3c.dom.DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, java.lang.String datavalue, boolean isXML11Version)
Check if CDATA section is well-formed

param
datavalue
param
isXML11Version = true if XML 1.1

        if (datavalue == null || (datavalue.length() == 0) ) {
            return;
        }
        
        char [] dataarray = datavalue.toCharArray(); 
        int datalength = dataarray.length;
        
        // version of the document is XML 1.1
        if (isXML11Version) {                    
            // we need to check all chracters as per production rules of XML11
            int i = 0;
            while(i < datalength){     
                char c = dataarray[i++];                                      
                if ( XML11Char.isXML11Invalid(c) ) {
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    String msg = DOMMessageFormatter.formatMessage(
                        DOMMessageFormatter.XML_DOMAIN,
                        "InvalidCharInCDSect",
                        new Object[] { Integer.toString(c, 16)});
                    reportDOMError(
                        errorHandler,
                        error,
                        locator,
                        msg,
                        DOMError.SEVERITY_ERROR,
                        "wf-invalid-character");
                }
                else if (c == ']") {
                    int count = i;
                    if (count < datalength && dataarray[count] == ']") {
                        while (++count < datalength && dataarray[count] == ']") {
                            // do nothing
                        }
                        if (count < datalength && dataarray[count] == '>") {
                            // CDEndInContent
                            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
                            reportDOMError(errorHandler, error, locator,msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                        }
                    }
                    
                }
            }
        } // version of the document is XML 1.0
        else {                    
            // we need to check all chracters as per production rules of XML 1.0
            int i = 0;
            while (i < datalength) {   
                char c = dataarray[i++];                         
                if( XMLChar.isInvalid(c) ) {
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    // Note:  The key InvalidCharInCDSect from XMLMessages.properties
                    // is being used to obtain the message and DOM error type
                    // "wf-invalid-character" is used.  Also per DOM it is error but 
                    // as per XML spec. it is fatal error
                    String msg = DOMMessageFormatter.formatMessage(
                        DOMMessageFormatter.XML_DOMAIN, 
                        "InvalidCharInCDSect", 
                        new Object[]{Integer.toString(c, 16)});
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }
                else if (c==']") {
                    int count = i;
                    if ( count< datalength && dataarray[count]==']" ) {
                        while (++count < datalength && dataarray[count]==']" ) {
                            // do nothing
                        }
                        if ( count < datalength && dataarray[count]=='>" ) {
                            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
                            reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                        }
                    }
                    
                }
            }            
        } // end-else fDocument.isXMLVersion()
        
    
public static final voidisCommentWF(org.w3c.dom.DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, java.lang.String datavalue, boolean isXML11Version)
NON-DOM: check if value of the comment is well-formed

param
datavalue
param
isXML11Version = true if XML 1.1

        if ( datavalue == null || (datavalue.length() == 0) ) {
            return;
        }
        
        char [] dataarray = datavalue.toCharArray(); 
        int datalength = dataarray.length ;
        
        // version of the document is XML 1.1
        if (isXML11Version) {                    
            // we need to check all chracters as per production rules of XML11
            int i = 0 ;
            while (i < datalength){   
                char c = dataarray[i++];
                if ( XML11Char.isXML11Invalid(c) ) {
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, 
                        "InvalidCharInComment", 
                        new Object [] {Integer.toString(dataarray[i-1], 16)});
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }
                else if (c == '-" && i < datalength && dataarray[i] == '-") {
                    String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
                        "DashDashInComment", null);
                    // invalid: '--' in comment                   
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }
            }
        } // version of the document is XML 1.0
        else {                    
            // we need to check all chracters as per production rules of XML 1.0
            int i = 0;
            while (i < datalength){ 
                char c = dataarray[i++];                           
                if( XMLChar.isInvalid(c) ){
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
                        "InvalidCharInComment", new Object [] {Integer.toString(dataarray[i-1], 16)});
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }  
                else if (c == '-" && i<datalength && dataarray[i]=='-"){
                    String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
                        "DashDashInComment", null);
                    // invalid: '--' in comment                   
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
                }                                      
            }
            
        } // end-else fDocument.isXMLVersion()
        
    
public static final voidisXMLCharWF(org.w3c.dom.DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, java.lang.String datavalue, boolean isXML11Version)
NON-DOM: check for valid XML characters as per the XML version

param
datavalue
param
isXML11Version = true if XML 1.1

        if ( datavalue == null || (datavalue.length() == 0) ) {
            return;      
        }
        
        char [] dataarray = datavalue.toCharArray(); 
        int datalength = dataarray.length;
        
        // version of the document is XML 1.1
        if(isXML11Version){                    
            //we need to check all characters as per production rules of XML11
            int i = 0 ;
            while (i < datalength) {                            
                if(XML11Char.isXML11Invalid(dataarray[i++])){
                    // check if this is a supplemental character
                    char ch = dataarray[i-1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    String msg = DOMMessageFormatter.formatMessage(
                        DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM", 
                        new Object[]{Integer.toString(dataarray[i-1], 16)});
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 
                    "wf-invalid-character");
                }
            }
        } // version of the document is XML 1.0
        else{                    
            // we need to check all characters as per production rules of XML 1.0
            int i = 0 ;
            while (i < datalength) {                            
                if( XMLChar.isInvalid(dataarray[i++]) ) {
                    // check if this is a supplemental character
                    char ch = dataarray[i-1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2) && 
                            XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    String msg = DOMMessageFormatter.formatMessage(
                        DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM", 
                        new Object[]{Integer.toString(dataarray[i-1], 16)});
                    reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 
                    "wf-invalid-character");
                }
            }            
        } // end-else fDocument.isXMLVersion()
        
    
protected final voidnamespaceFixUp(ElementImpl element, AttributeMap attributes)

        if (DEBUG) {
            System.out.println("[ns-fixup] element:" +element.getNodeName()+
                               " uri: "+element.getNamespaceURI());
        }

        // ------------------------------------
        // pick up local namespace declarations
        // <xsl:stylesheet xmlns:xsl="http://xslt">
        //   <!-- add the following via DOM 
        //          body is bound to http://xslt
        //    -->
        //   <xsl:body xmlns:xsl="http://bound"/>
        //
        // ------------------------------------

        String value, uri, prefix;
        if (attributes != null) {

            // Record all valid local declarations
            for (int k = 0; k < attributes.getLength(); ++k) {
                Attr attr = (Attr)attributes.getItem(k);
                uri = attr.getNamespaceURI();
                if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
                    // namespace attribute
                    value = attr.getNodeValue();
                    if (value == null) {
                        value=XMLSymbols.EMPTY_STRING;
                    }

                    // Check for invalid namespace declaration:
                    if (fDocument.errorChecking && value.equals(NamespaceContext.XMLNS_URI)) {
                    	//A null value for locale is passed to formatMessage, 
                    	//which means that the default locale will be used
                        fLocator.fRelatedNode = attr;
                        String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,"CantBindXMLNS",null );
                        reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, "CantBindXMLNS");
                    } else {
                        // XML 1.0 Attribute value normalization
                        // value = normalizeAttributeValue(value, attr);
                        prefix = attr.getPrefix();
                        prefix = (prefix == null || 
                                  prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
                        String localpart = fSymbolTable.addSymbol( attr.getLocalName());
                        if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix

                            value = fSymbolTable.addSymbol(value);
                            if (value.length() != 0) {
                                fNamespaceContext.declarePrefix(localpart, value);
                            } else {
                                // REVISIT: issue error on invalid declarations
                                //          xmlns:foo = ""

                            }
                            //removeDefault (attr, attributes);
                            continue;
                        } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol)  -- xmlns
                            // empty prefix is always bound ("" or some string)
                            value = fSymbolTable.addSymbol(value);
                            fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? value : null);
                            //removeDefault (attr, attributes);
                            continue;
                        }
                    }  // end-else: valid declaration
                } // end-if: namespace attribute
            }
        }



        // ---------------------------------------------------------
        // Fix up namespaces for element: per DOM L3 
        // Need to consider the following cases:
        //
        // case 1: <xsl:stylesheet xmlns:xsl="http://xsl">
        // We create another element body bound to the "http://xsl" namespace
        // as well as namespace attribute rebounding xsl to another namespace.
        // <xsl:body xmlns:xsl="http://another">
        // Need to make sure that the new namespace decl value is changed to 
        // "http://xsl"
        //
        // ---------------------------------------------------------
        // check if prefix/namespace is correct for current element
        // ---------------------------------------------------------

        uri = element.getNamespaceURI();
        prefix = element.getPrefix();
        if (uri != null) {  // Element has a namespace
            uri = fSymbolTable.addSymbol(uri);
            prefix = (prefix == null || 
                      prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
            if (fNamespaceContext.getURI(prefix) == uri) {
                // The xmlns:prefix=namespace or xmlns="default" was declared at parent.
                // The binder always stores mapping of empty prefix to "".
            } else {
                // the prefix is either undeclared 
                // or
                // conflict: the prefix is bound to another URI
                addNamespaceDecl(prefix, uri, element);
                fLocalNSBinder.declarePrefix(prefix, uri);
                fNamespaceContext.declarePrefix(prefix, uri);
            }
        } else { // Element has no namespace
            if (element.getLocalName() == null) {
            	
                //  Error: DOM Level 1 node!
                if (fNamespaceValidation) {
                    String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", 
                            new Object[]{element.getNodeName()});
                    reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR, 
                    "NullLocalElementName");
                } else {
                    String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", 
                            new Object[]{element.getNodeName()});
                    reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 
                    "NullLocalElementName");
                }
            	
            } else { // uri=null and no colon (DOM L2 node)
                uri = fNamespaceContext.getURI(XMLSymbols.EMPTY_STRING);
                if (uri !=null && uri.length() > 0) {
                    // undeclare default namespace declaration (before that element
                    // bound to non-zero length uir), but adding xmlns="" decl                    
                    addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element);
                    fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, null);
                    fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
                }
            }
        }

        // -----------------------------------------
        // Fix up namespaces for attributes: per DOM L3 
        // check if prefix/namespace is correct the attributes
        // -----------------------------------------
        if (attributes != null) {

            // clone content of the attributes
            attributes.cloneMap(fAttributeList);
            for (int i = 0; i < fAttributeList.size(); i++) {
                Attr attr = (Attr) fAttributeList.elementAt(i);
                fLocator.fRelatedNode = attr;

                if (DEBUG) {
                    System.out.println("==>[ns-fixup] process attribute: "+attr.getNodeName());
                }
                // normalize attribute value
                attr.normalize();                
                value = attr.getValue();           
                uri = attr.getNamespaceURI();

                // make sure that value is never null.
                if (value == null) {
                    value = XMLSymbols.EMPTY_STRING;
                }
                
                //---------------------------------------
                // check if value of the attribute is namespace well-formed
                //---------------------------------------
                if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
                    isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, value, fDocument.isXML11Version());
                    if (fDocument.isXMLVersionChanged()) {
                        boolean wellformed;
                        if (fNamespaceValidation){
                            wellformed = CoreDocumentImpl.isValidQName(attr.getPrefix(), attr.getLocalName(), fDocument.isXML11Version());
                        }
                        else {
                            wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), fDocument.isXML11Version());
                        }
                        if (!wellformed) {
                            String msg = DOMMessageFormatter.formatMessage(
                                    DOMMessageFormatter.DOM_DOMAIN, 
                                    "wf-invalid-character-in-node-name", 
                                    new Object[]{"Attr", attr.getNodeName()});
                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 
                            "wf-invalid-character-in-node-name");
                        }
                    }           
                }

                if (uri != null) {  // attribute has namespace !=null
                    prefix = attr.getPrefix();
                    prefix = (prefix == null || 
                              prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
                    /*String localpart =*/ fSymbolTable.addSymbol( attr.getLocalName());

                    // ---------------------------------------
                    // skip namespace declarations 
                    // ---------------------------------------
                    // REVISIT: can we assume that "uri" is from some symbol
                    // table, and compare by reference? -SG
                    if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
                        continue;
                    }

                    // ---------------------------------------
                    // remove default attributes
                    // ---------------------------------------
                    /* 
                    if (removeDefault(attr, attributes)) {
                        continue;
                    }
                    */
                    // XML 1.0 Attribute value normalization
                    //value = normalizeAttributeValue(value, attr);
                    
                    // reset id-attributes
                    ((AttrImpl)attr).setIdAttribute(false);

                    uri = fSymbolTable.addSymbol(uri);

                    // find if for this prefix a URI was already declared
                    String declaredURI =  fNamespaceContext.getURI(prefix);

                    if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) {
                        // attribute has no prefix (default namespace decl does not apply to attributes) 
                        // OR
                        // attribute prefix is not declared
                        // OR
                        // conflict: attribute has a prefix that conficlicts with a binding
                        //           already active in scope

                        // Find if any prefix for attributes namespace URI is available
                        // in the scope
                        String declaredPrefix = fNamespaceContext.getPrefix(uri);
                        if (declaredPrefix !=null && declaredPrefix !=XMLSymbols.EMPTY_STRING) {

                            // use the prefix that was found (declared previously for this URI
                            prefix = declaredPrefix;
                        } else {
                            if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) {
                                // the current prefix is not null and it has no in scope declaration

                                // use this prefix
                            } else {

                                // find a prefix following the pattern "NS" +index (starting at 1)
                                // make sure this prefix is not declared in the current scope.
                                int counter = 1;
                                prefix = fSymbolTable.addSymbol(PREFIX +counter++);
                                while (fLocalNSBinder.getURI(prefix)!=null) {
                                    prefix = fSymbolTable.addSymbol(PREFIX +counter++);
                                }

                            }
                            // add declaration for the new prefix
                            addNamespaceDecl(prefix, uri, element);
                            value = fSymbolTable.addSymbol(value);
                            fLocalNSBinder.declarePrefix(prefix, value);
                            fNamespaceContext.declarePrefix(prefix, uri);
                        }

                        // change prefix for this attribute
                        attr.setPrefix(prefix);
                    }
                } else { // attribute uri == null

                    // XML 1.0 Attribute value normalization
                    //value = normalizeAttributeValue(value, attr);
                    
                    // reset id-attributes
                    ((AttrImpl)attr).setIdAttribute(false);

                    if (attr.getLocalName() == null) {
                        // It is an error if document has DOM L1 nodes.
                        if (fNamespaceValidation) {
                            String msg = DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN, 
                                "NullLocalAttrName", new Object[]{attr.getNodeName()});
                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR, 
                                "NullLocalAttrName");
                        } else {
                            String msg = DOMMessageFormatter.formatMessage(
                                DOMMessageFormatter.DOM_DOMAIN, 
                                "NullLocalAttrName", new Object[]{attr.getNodeName()});
                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 
                                "NullLocalAttrName");
                        }
                    } else {
                        // uri=null and no colon
                        // no fix up is needed: default namespace decl does not 

                        // ---------------------------------------
                        // remove default attributes
                        // ---------------------------------------
                        // removeDefault(attr, attributes);
                    }
                }
            }
        } // end loop for attributes
    
final java.lang.StringnormalizeAttributeValue(java.lang.String value, org.w3c.dom.Attr attr)

        if (!attr.getSpecified()){
            // specified attributes should already have a normalized form
            // since those were added by validator
            return value;
        }
        int end = value.length();
        // ensure capacity 
        if (fNormalizedValue.ch.length < end) {
            fNormalizedValue.ch = new char[end];
        }
        fNormalizedValue.length = 0;
        boolean normalized = false;
        for (int i = 0; i < end; i++) {
            char c = value.charAt(i);
            if (c==0x0009 || c==0x000A) {
               fNormalizedValue.ch[fNormalizedValue.length++] = ' "; 
               normalized = true;
            }
            else if(c==0x000D){
               normalized = true;
               fNormalizedValue.ch[fNormalizedValue.length++] = ' ";
               int next = i+1;
               if (next < end && value.charAt(next)==0x000A) i=next; // skip following xA
            }
            else {
                fNormalizedValue.ch[fNormalizedValue.length++] = c;
            }
        }
        if (normalized){
           value = fNormalizedValue.toString();
           attr.setValue(value);
        }
        return value;
    
protected voidnormalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config)
Normalizes document. Note: reset() must be called before this method.

        
        fDocument = document;
        fConfiguration = config;
        fAllWhitespace = false;
        fNamespaceValidation = false;
        
        String xmlVersion = fDocument.getXmlVersion();
        String schemaType = null;
        String [] schemaLocations = null;
        
        // intialize and reset DOMNormalizer component
        // 
        fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
        // reset namespace context
        fNamespaceContext.reset();
        fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
        
        if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
            String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
            
            if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
                schemaType = XMLGrammarDescription.XML_SCHEMA;
                fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
                fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true);
                fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true);
                // report fatal error on DOM Level 1 nodes
                fNamespaceValidation = true;              
                
                // check if we need to fill in PSVI
                fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false;       
            }
            else {
                schemaType = XMLGrammarDescription.XML_DTD;
                if (schemaLang != null) {
                    schemaLocations = (String []) fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
                }
                fConfiguration.setDTDValidatorFactory(xmlVersion);
                fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
                fPSVI = false;
            }
            
            fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);       
            
            // reset ID table           
            fDocument.clearIdentifiers();
            
            if (fValidationHandler != null) {
                // reset the validation handler
                ((XMLComponent) fValidationHandler).reset(fConfiguration);
            }
        }
        else {
            fValidationHandler = null;
        }
        
        fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
        if (fValidationHandler != null) {
            fValidationHandler.setDocumentHandler(this);
            fValidationHandler.startDocument(
                    new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
                            -1, -1 ), fDocument.encoding, fNamespaceContext, null);
            fValidationHandler.xmlDecl(fDocument.getXmlVersion(), 
                    fDocument.getXmlEncoding(), fDocument.getXmlStandalone() ? "yes" : "no", null);
        }
        try {
            if (schemaType == XMLGrammarDescription.XML_DTD) {
                processDTD(xmlVersion, schemaLocations != null ? schemaLocations[0] : null);
            }            
            
            Node kid, next;
            for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
                next = kid.getNextSibling();
                kid = normalizeNode(kid);
                if (kid != null) { // don't advance
                    next = kid;
                }
            }
            
            // release resources
            if (fValidationHandler != null) {
                fValidationHandler.endDocument(null);
                fValidationHandler.setDocumentHandler(null);
                CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
                fValidationHandler = null;
            }
        }
        catch (RuntimeException e) {
            // release resources
            if (fValidationHandler != null) {
                fValidationHandler.setDocumentHandler(null);
                CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
                fValidationHandler = null;
            }
            if (e == abort) {
                return; // processing aborted by the user
            }
            throw e; // otherwise re-throw.
        }
    
protected org.w3c.dom.NodenormalizeNode(org.w3c.dom.Node node)
This method acts as if the document was going through a save and load cycle, putting the document in a "normal" form. The actual result depends on the features being set and governing what operations actually take place. See setNormalizationFeature for details. Noticeably this method normalizes Text nodes, makes the document "namespace wellformed", according to the algorithm described below in pseudo code, by adding missing namespace declaration attributes and adding or changing namespace prefixes, updates the replacement tree of EntityReference nodes,normalizes attribute values, etc.

param
node Modified node or null. If node is returned, we need to normalize again starting on the node returned.
return
the normalized Node


        int type = node.getNodeType();
        boolean wellformed;
        fLocator.fRelatedNode=node;
        
        switch (type) {
        case Node.DOCUMENT_TYPE_NODE: {
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode:{doctype}");
                }
                // REVISIT: well-formedness encoding info
                break;
            }

        case Node.ELEMENT_NODE: {  
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode:{element} "+node.getNodeName());
                }
                
                //do the name check only when version of the document was changed &
                //application has set the value of well-formed features to true
                if (fDocument.errorChecking) {
                    if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && 
                            fDocument.isXMLVersionChanged()){
                        if (fNamespaceValidation){
                            wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version());
                        }
                        else {
                            wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
                        }
                        if (!wellformed){
                            String msg = DOMMessageFormatter.formatMessage(
                                    DOMMessageFormatter.DOM_DOMAIN, 
                                    "wf-invalid-character-in-node-name", 
                                    new Object[]{"Element", node.getNodeName()});
                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 
                            "wf-invalid-character-in-node-name");                       
                        }
                    }
                }
                // push namespace context
                fNamespaceContext.pushContext();
                fLocalNSBinder.reset();

                ElementImpl elem = (ElementImpl)node;
                if (elem.needsSyncChildren()) {
                    elem.synchronizeChildren();
                }
                AttributeMap attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null; 

                // fix namespaces and remove default attributes
                if ((fConfiguration.features & DOMConfigurationImpl.NAMESPACES) !=0) {
                    // fix namespaces
                    // normalize attribute values
                    // remove default attributes
                    namespaceFixUp(elem, attributes);
                    
                    if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0 && attributes != null ) {
                        for (int i = 0; i < attributes.getLength(); ++i) {
                            Attr att = (Attr)attributes.getItem(i);
                            if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
                                XMLSymbols.PREFIX_XMLNS.equals(att.getName())) {
                                elem.removeAttributeNode(att);
                                --i;
                            }
                        }
                    }  
                    
                } else {
                    if ( attributes!=null ) {
                        for ( int i=0; i<attributes.getLength(); ++i ) {
                            Attr attr = (Attr)attributes.item(i);
                            //removeDefault(attr, attributes);
                            attr.normalize();
                            if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
                                    isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, attr.getValue(), fDocument.isXML11Version());
                                if (fDocument.isXMLVersionChanged()) {
                                    if (fNamespaceValidation){
                                        wellformed = CoreDocumentImpl.isValidQName(node.getPrefix(), node.getLocalName(), fDocument.isXML11Version());
                                    }
                                    else {
                                        wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), fDocument.isXML11Version());
                                    }
                                    if (!wellformed) {
				                            String msg = DOMMessageFormatter.formatMessage(
				                              DOMMessageFormatter.DOM_DOMAIN, 
				                              "wf-invalid-character-in-node-name", 
				                               new Object[]{"Attr",node.getNodeName()});
				                            reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 
				                                "wf-invalid-character-in-node-name");
                                    }
                                }           
                            }
                        }                                                        
                    }
                }
                
                
                if (fValidationHandler != null) {
                    // REVISIT: possible solutions to discard default content are:
                    //         either we pass some flag to XML Schema validator
                    //         or rely on the PSVI information.
                    fAttrProxy.setAttributes(attributes, fDocument, elem);
                    updateQName(elem, fQName); // updates global qname
                    // set error node in the dom error wrapper
                    // so if error occurs we can report an error node
                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
                    fCurrentNode = node;
                    // call re-validation handler
                    fValidationHandler.startElement(fQName, fAttrProxy, null);
                }

                // normalize children
                Node kid, next;
                for (kid = elem.getFirstChild(); kid != null; kid = next) {
                    next = kid.getNextSibling();
                    kid = normalizeNode(kid);
                    if (kid != null) {
                        next = kid;  // don't advance
                    }
                } 
                if (DEBUG_ND) {
                    // normalized subtree
                    System.out.println("***The children of {"+node.getNodeName()+"} are normalized");
                    for (kid = elem.getFirstChild(); kid != null; kid = next) {
                        next = kid.getNextSibling();
                        System.out.println(kid.getNodeName() +"["+kid.getNodeValue()+"]");
                    }

                }

                if (fValidationHandler != null) {
                    updateQName(elem, fQName); // updates global qname
                    //
                    // set error node in the dom error wrapper
                    // so if error occurs we can report an error node
                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
                    fCurrentNode = node;
                    fValidationHandler.endElement(fQName, null);
                }

                // pop namespace context
                fNamespaceContext.popContext();

                break;
            }

        case Node.COMMENT_NODE: {  
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode:{comments}");
                }

                if ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0) {
                    Node prevSibling = node.getPreviousSibling();
                    Node parent = node.getParentNode();
                    // remove the comment node
                    parent.removeChild(node);
                    if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE) {
                        Node nextSibling = prevSibling.getNextSibling();
                        if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) {
                            ((TextImpl)nextSibling).insertData(0, prevSibling.getNodeValue());
                            parent.removeChild(prevSibling);
                            return nextSibling;
                        }
                    }
                }//if comment node need not be removed
                else {
                    if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
                        String commentdata = ((Comment)node).getData();
                        // check comments for invalid xml chracter as per the version
                        // of the document                            
                        isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version());                        
                    }
                    if (fValidationHandler != null) {
                        // Don't bother filling an XMLString with the text of the comment.
                        // We only send the comment event to the validator handler so that
                        // when  the schema-type is DTD an error will be reported for a
                        // comment appearing in EMPTY content.
                        fValidationHandler.comment(EMPTY_STRING, null);
                    }         
                }//end-else if comment node is not to be removed.
				break;
            }
        case Node.ENTITY_REFERENCE_NODE: { 
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode:{entityRef} "+node.getNodeName());
                }

                if ((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0) {
                    Node prevSibling = node.getPreviousSibling();
                    Node parent = node.getParentNode();
                    ((EntityReferenceImpl)node).setReadOnly(false, true);
                    expandEntityRef (parent, node);
                    parent.removeChild(node);
                    Node next = (prevSibling != null)?prevSibling.getNextSibling():parent.getFirstChild();
                    // The list of children #text -> &ent;
                    // and entity has a first child as a text
                    // we should not advance
                    if (prevSibling != null && next != null && prevSibling.getNodeType() == Node.TEXT_NODE && 
                        next.getNodeType() == Node.TEXT_NODE) {
                        return prevSibling;  // Don't advance                          
                    }
                    return next;
                } else {
                    if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && 
                        fDocument.isXMLVersionChanged()){
                            CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());                    
                    }
                    // REVISIT: traverse entity reference and send appropriate calls to the validator
                    // (no normalization should be performed for the children).
                }
                break;
            }

        case Node.CDATA_SECTION_NODE: {
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode:{cdata}");
                }
                
                if ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) {
                    // convert CDATA to TEXT nodes
                    Node prevSibling = node.getPreviousSibling();
                    if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE){
                        ((Text)prevSibling).appendData(node.getNodeValue());
                        node.getParentNode().removeChild(node);
                        return prevSibling; //don't advance                        
                    }
                    else {
                        Text text = fDocument.createTextNode(node.getNodeValue());
                        Node parent = node.getParentNode();
                        node = parent.replaceChild(text, node);
                        return text;  //don't advance
                        
                    }
                }

                // send characters call for CDATA
                if (fValidationHandler != null) {
                    // set error node in the dom error wrapper
                    // so if error occurs we can report an error node
                    fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
                    fCurrentNode = node;
                    fValidationHandler.startCDATA(null);
                    fValidationHandler.characterData(node.getNodeValue(), null);
                    fValidationHandler.endCDATA(null);
                }
                String value = node.getNodeValue();
                
                if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
                    int index;
                    Node parent = node.getParentNode();
                    if (fDocument.errorChecking) {
                        isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
                    }
                    while ( (index=value.indexOf("]]>")) >= 0 ) {
                        node.setNodeValue(value.substring(0, index+2));
                        value = value.substring(index +2);
                        
                        Node firstSplitNode = node;
                        Node newChild = fDocument.createCDATASection(value);
                        parent.insertBefore(newChild, node.getNextSibling());
                        node = newChild;                      
                        // issue warning
                        fLocator.fRelatedNode = firstSplitNode;
                        String msg = DOMMessageFormatter.formatMessage(
                            DOMMessageFormatter.DOM_DOMAIN, 
                            "cdata-sections-splitted", 
                             null);
                        reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_WARNING, 
                            "cdata-sections-splitted");
                    }

                }
                else if (fDocument.errorChecking) {
                    // check well-formedness
                    isCDataWF(fErrorHandler, fError, fLocator, value, fDocument.isXML11Version());
                }
                break;
            }

        case Node.TEXT_NODE: { 
                if (DEBUG_ND) {
                    System.out.println("==>normalizeNode(text):{"+node.getNodeValue()+"}");
                }
                // If node is a text node, we need to check for one of two
                // conditions:
                //   1) There is an adjacent text node
                //   2) There is no adjacent text node, but node is
                //      an empty text node.
                Node next = node.getNextSibling();
                // If an adjacent text node, merge it with this node
                if ( next!=null && next.getNodeType() == Node.TEXT_NODE ) {
                    ((Text)node).appendData(next.getNodeValue());
                    node.getParentNode().removeChild( next );
                    // We don't need to check well-formness here since we are not yet
                    // done with this node.
                    
                    return node; // Don't advance;                   
                } else if (node.getNodeValue().length()==0) {
                    // If kid is empty, remove it
                    node.getParentNode().removeChild( node );
                } else {                    
                    // validator.characters() call and well-formness
                    // Don't send characters or check well-formness in the following cases:
                    // 1. entities is false, next child is entity reference: expand tree first
                    // 2. comments is false, and next child is comment
                    // 3. cdata is false, and next child is cdata
                  
                    short nextType = (next != null)?next.getNodeType():-1;
                    if (nextType == -1 || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 &&
                            nextType == Node.ENTITY_NODE) ||
                            ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 &&
                                    nextType == Node.COMMENT_NODE) ||
                                    ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) &&
                                    nextType == Node.CDATA_SECTION_NODE)) {
                        if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){
                            isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
                        }                              
                        if (fValidationHandler != null) {
                            fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
                            fCurrentNode = node;
                            fValidationHandler.characterData(node.getNodeValue(), null);
                            if (!fNamespaceValidation) {
                                if (fAllWhitespace) {
                                    fAllWhitespace = false;
                                    ((TextImpl)node).setIgnorableWhitespace(true);
                                }
                                else {
                                    ((TextImpl)node).setIgnorableWhitespace(false);
                                }
                            }
                            if (DEBUG_ND) {
                                System.out.println("=====>characterData(),"+nextType);
                            }
                        }  
                    }
                    else {
                        if (DEBUG_ND) {
                            System.out.println("=====>don't send characters(),"+nextType);

                        }
                    }
                }
                break;
            }        
        case Node.PROCESSING_INSTRUCTION_NODE: {
            
            //do the well-formed valid PI target name , data check when application has set the value of well-formed feature to true
            if (fDocument.errorChecking && (fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0 ) {
                ProcessingInstruction pinode = (ProcessingInstruction)node ;

                String target = pinode.getTarget();
                //1.check PI target name
                if(fDocument.isXML11Version()){
                    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()});
                    reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,  
                        "wf-invalid-character-in-node-name");
                }        
                                
                //2. check PI data
                //processing isntruction data may have certain characters
                //which may not be valid XML character               
                isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version());
            }
            
            if (fValidationHandler != null) {
                // Don't bother filling an XMLString with the data section of the
                // processing instruction. We only send the processing instruction
                // event to the validator handler so that when the schema-type is 
                // DTD an error will be reported for a processing instruction
                // appearing in EMPTY content.
                fValidationHandler.processingInstruction(((ProcessingInstruction) node).getTarget(), EMPTY_STRING, null);
            } 
        }//end case Node.PROCESSING_INSTRUCTION_NODE
        
        }//end of switch
        return null;
    
private voidprocessDTD(java.lang.String xmlVersion, java.lang.String schemaLocation)

        
        String rootName = null;
        String publicId = null;
        String systemId = schemaLocation;
        String baseSystemId = fDocument.getDocumentURI();
        String internalSubset = null;
        
        DocumentType docType = fDocument.getDoctype();
        if (docType != null) {
            rootName = docType.getName();
            publicId = docType.getPublicId();
            if (systemId == null || systemId.length() == 0) {
                systemId = docType.getSystemId();
            }
            internalSubset = docType.getInternalSubset();
        }
        // If the DOM doesn't have a DocumentType node we may still
        // be able to fetch a DTD if the application provided a URI
        else {
            Element elem = fDocument.getDocumentElement();
            if (elem == null) return;
            rootName = elem.getNodeName();
            if (systemId == null || systemId.length() == 0) return;
        }
        
        XMLDTDLoader loader = null;
        try {
            fValidationHandler.doctypeDecl(rootName, publicId, systemId, null);
            loader = CoreDOMImplementationImpl.singleton.getDTDLoader(xmlVersion);
            loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
            loader.setEntityResolver(fConfiguration.getEntityResolver());
            loader.setErrorHandler(fConfiguration.getErrorHandler());
            loader.loadGrammarWithContext((XMLDTDValidator) fValidationHandler, rootName, 
                    publicId, systemId, baseSystemId, internalSubset);
        }
        // REVISIT: Should probably report this exception to the error handler.
        catch (IOException e) {   
        }
        finally {
            if (loader != null) {
                CoreDOMImplementationImpl.singleton.releaseDTDLoader(xmlVersion, loader);
            }
        }
    
public voidprocessingInstruction(java.lang.String target, org.apache.xerces.xni.XMLString data, org.apache.xerces.xni.Augmentations augs)
A processing instruction. Processing instructions consist of a target name and, optionally, text data. The data is only meaningful to the application.

Typically, a processing instruction's data will contain a series of pseudo-attributes. These pseudo-attributes follow the form of element attributes but are not parsed or presented to the application as anything other than text. The application is responsible for parsing the data.

param
target The target.
param
data The data or null if none specified.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public static final voidreportDOMError(org.w3c.dom.DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, java.lang.String message, short severity, java.lang.String type)
Reports a DOM error to the user handler. If the error is fatal, the processing will be always aborted.

        if( errorHandler!=null ) {
            error.reset();
            error.fMessage = message;
            error.fSeverity = severity;
            error.fLocator = locator;
            error.fType = type;
            error.fRelatedData = locator.fRelatedNode;
    
            if(!errorHandler.handleError(error))
                throw abort;
        }
        if( severity==DOMError.SEVERITY_FATAL_ERROR )
            throw abort;
    
public voidsetDocumentSource(org.apache.xerces.xni.parser.XMLDocumentSource source)
Sets the document source.

    
public voidstartCDATA(org.apache.xerces.xni.Augmentations augs)
The start of a CDATA section.

param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidstartDocument(org.apache.xerces.xni.XMLLocator locator, java.lang.String encoding, org.apache.xerces.xni.NamespaceContext namespaceContext, org.apache.xerces.xni.Augmentations augs)
The start of the document.

param
locator The document locator, or null if the document location cannot be reported during the parsing of this document. However, it is strongly recommended that a locator be supplied that can at least report the system identifier of the document.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
param
namespaceContext The namespace context in effect at the start of this document. This object represents the current context. Implementors of this class are responsible for copying the namespace bindings from the the current context (and its parent contexts) if that information is important.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidstartElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
The start of an element.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        Element currentElement = (Element) fCurrentNode;
        int attrCount = attributes.getLength();
        if (DEBUG_EVENTS) {
            System.out.println("==>startElement: " +element+
                    " attrs.length="+attrCount);
        }

        for (int i = 0; i < attrCount; i++) {
            attributes.getName(i, fAttrQName);
            Attr attr = null;

            attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
            if (attr == null) {
                // Must be a non-namespace aware DOM Level 1 node.
                attr = currentElement.getAttributeNode(fAttrQName.rawname);
            }
            AttributePSVI attrPSVI =
                (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);

            if (attrPSVI != null) {
                //REVISIT: instead we should be using augmentations:
                // to set/retrieve Id attributes
                XSTypeDefinition decl = attrPSVI.getMemberTypeDefinition();
                boolean id = false;
                if (decl != null) {
                    id = ((XSSimpleType)decl).isIDType();
                } 
                else {
                    decl = attrPSVI.getTypeDefinition();
                    if (decl != null) {
                        id = ((XSSimpleType)decl).isIDType(); 
                    }
                }
                if (id) {
                    ((ElementImpl)currentElement).setIdAttributeNode(attr, true);
                }

                if (fPSVI) {
                    ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
                }

                // Updating the TypeInfo for this attribute.
                ((AttrImpl) attr).setType(decl);

                if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
                    // datatype-normalization
                    // NOTE: The specified value MUST be set after we set
                    //       the node value because that turns the "specified"
                    //       flag to "true" which may overwrite a "false"
                    //       value from the attribute list.
                    final String normalizedValue = attrPSVI.getSchemaNormalizedValue();
                    if (normalizedValue != null) {
                        boolean specified = attr.getSpecified();
                        attr.setValue(normalizedValue);
                        if (!specified) {
                            ((AttrImpl) attr).setSpecified(specified);
                        }
                    }
                }
            }
            else { // DTD
                String type = null;
                boolean isDeclared = Boolean.TRUE.equals(attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_DECLARED));
                // For DOM Level 3 TypeInfo, the type name must
                // be null if this attribute has not been declared
                // in the DTD.
                if (isDeclared) {
                    type = attributes.getType(i);
                    if ("ID".equals (type)) {
                        ((ElementImpl) currentElement).setIdAttributeNode(attr, true);
                    }
                }
                // Updating the TypeInfo for this attribute.
                ((AttrImpl) attr).setType(type);
            }
        }
    
public voidstartGeneralEntity(java.lang.String name, org.apache.xerces.xni.XMLResourceIdentifier identifier, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
This method notifies the start of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the general entity.
param
identifier The resource identifier.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
public voidtextDecl(java.lang.String version, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of a TextDecl line in an entity. If present, this method will be called immediately following the startEntity call.

Note: This method will never be called for the document entity; it is only called for external general entities referenced in document content.

Note: This method is not called for entity references appearing as part of attribute values.

param
version The XML version, or null if not specified.
param
encoding The IANA encoding name of the entity.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

    
protected final voidupdateQName(org.w3c.dom.Node node, org.apache.xerces.xni.QName qname)


        String prefix    = node.getPrefix();
        String namespace = node.getNamespaceURI();
        String localName = node.getLocalName();
        // REVISIT: the symbols are added too often: start/endElement
        //          and in the namespaceFixup. Should reduce number of calls to symbol table.
        qname.prefix = (prefix!=null && prefix.length()!=0)?fSymbolTable.addSymbol(prefix):null;
        qname.localpart = (localName != null)?fSymbolTable.addSymbol(localName):null;
        qname.rawname = fSymbolTable.addSymbol(node.getNodeName()); 
        qname.uri =  (namespace != null)?fSymbolTable.addSymbol(namespace):null;
    
public voidxmlDecl(java.lang.String version, java.lang.String encoding, java.lang.String standalone, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of an XMLDecl line in the document. If present, this method will be called immediately following the startDocument call.

param
version The XML version.
param
encoding The IANA encoding name of the document, or null if not specified.
param
standalone The standalone value, or null if not specified.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.