/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 2002, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * . */ package com.sun.org.apache.xerces.internal.dom; import java.util.Vector; //-- import com.sun.org.apache.xerces.internal.parsers.XMLGrammarPreparser; import com.sun.org.apache.xerces.internal.parsers.IntegratedParserConfiguration; import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; import org.xml.sax.InputSource; //-- import org.w3c.dom.DOMError; import org.w3c.dom.DOMErrorHandler; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.RevalidationHandler; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; import com.sun.org.apache.xerces.internal.util.AugmentationsImpl; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; import com.sun.org.apache.xerces.internal.xni.XMLLocator; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; import com.sun.org.apache.xerces.internal.xs.AttributePSVI; import com.sun.org.apache.xerces.internal.xs.ElementPSVI; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.w3c.dom.ProcessingInstruction; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Entity; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Comment; import com.sun.org.apache.xerces.internal.impl.dtd.*; import java.io.*; /** * 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). * * NOTE: the implementation is experimental and methods, functionality * can be modified or removed in the future. * * @author Elena Litani, IBM * @author Neeraj Bajaj, Sun Microsystems, inc. * @version $Id: DOMNormalizer.java,v 1.54 2004/04/22 20:39:03 mrglavas Exp $ */ public class DOMNormalizer implements XMLDocumentHandler { //-- Added // Constants // // property IDs: /** Property identifier: symbol table. */ public static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; /** Property identifier: grammar pool. */ public static final String GRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; // feature ids /** Namespaces feature id (http://xml.org/sax/features/namespaces). */ protected static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces"; /** Validation feature id (http://xml.org/sax/features/validation). */ protected static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation"; /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */ protected static final String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema"; /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */ protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking"; //-- // // constants // /** Debug normalize document*/ protected final static boolean DEBUG_ND = false; /** Debug namespace fix up algorithm*/ protected final static boolean DEBUG = false; /** Debug document handler events */ protected final static boolean DEBUG_EVENTS = false; /** prefix added by namespace fixup algorithm should follow a pattern "NS" + index*/ protected final static String PREFIX = "NS"; // // Data // protected DOMConfigurationImpl fConfiguration = null; protected CoreDocumentImpl fDocument = null; protected final XMLAttributesProxy fAttrProxy = new XMLAttributesProxy(); protected final QName fQName = new QName(); /** Validation handler represents validator instance. */ protected RevalidationHandler fValidationHandler; protected XMLDTDValidator fDTDValidator; /** symbol table */ protected SymbolTable fSymbolTable; /** error handler. may be null. */ protected DOMErrorHandler fErrorHandler; /** * Cached {@link DOMError} impl. * The same object is re-used to report multiple errors. */ private final DOMErrorImpl fError = new DOMErrorImpl(); // Validation against namespace aware grammar protected boolean fNamespaceValidation = false; // Update PSVI information in the tree protected boolean fPSVI = false; /** The namespace context of this document: stores namespaces in scope */ protected final NamespaceContext fNamespaceContext = new NamespaceSupport(); /** Stores all namespace bindings on the current element */ protected final NamespaceContext fLocalNSBinder = new NamespaceSupport(); /** list of attributes */ protected final Vector fAttributeList = new Vector(5,10); /** DOM Locator - for namespace fixup algorithm */ protected final DOMLocatorImpl fLocator = new DOMLocatorImpl(); /** for setting the PSVI */ protected Node fCurrentNode = null; private QName fAttrQName = new QName(); // attribute value normalization final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0); /** * If the user stops the process, this exception will be thrown. */ public static final RuntimeException abort = new RuntimeException(); // Constructor // public boolean isWhitespace = false; public boolean docTypeFound = false; public DOMNormalizer(){} /** * Normalizes document. * Note: reset() must be called before this method. */ protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) { fDocument = document; fConfiguration = config; // intialize and reset DOMNormalizer component // fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE); // reset namespace context fNamespaceContext.reset(); fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); docTypeFound = false; if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) { String type =(String) fConfiguration.getProperty(fConfiguration.JAXP_SCHEMA_LANGUAGE); if(type != null && type.equals(Constants.NS_XMLSCHEMA)) fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_SCHEMA); fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true); fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, 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; // reset ID table fDocument.clearIdentifiers(); // reset schema validator if(fValidationHandler!=null) ((XMLComponent) fValidationHandler).reset(fConfiguration); } 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); } try { 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); CoreDOMImplementationImpl.singleton.releaseValidator( XMLGrammarDescription.XML_SCHEMA, fValidationHandler); fValidationHandler = null; } } catch (RuntimeException e) { if(DEBUG_ND) e.printStackTrace(); if( e==abort ) return; // processing aborted by the user throw e; // otherwise re-throw. } } /** * * 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 */ protected Node normalizeNode(Node 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}"); } fDTDValidator =(XMLDTDValidator) CoreDOMImplementationImpl.singleton.getDTDValidator(); DocumentTypeImpl docNode = (DocumentTypeImpl)node; if(fDTDValidator != null){ //fix me : fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, false); fDTDValidator.startDocument( new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI, -1, -1 ), fDocument.encoding, fNamespaceContext, null); if (DEBUG_ND) System.out.println("Internal subset is "+docNode.getInternalSubset()); XMLGrammarPoolImpl grammarPool = getGrammarPool(docNode.getSystemId(),docNode.getInternalSubset()); fConfiguration.setProperty(GRAMMAR_POOL, grammarPool); fDTDValidator.setDocumentHandler(this); ((XMLComponent) fDTDValidator).reset(fConfiguration); fDTDValidator.doctypeDecl(docNode.getName(),docNode.getPublicId(),docNode.getSystemId(),null); docTypeFound = true; } //REVISIT: well-formness 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 ( ((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); } else { if ( attributes!=null ) { for ( int i=0; inormalizeNode:{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 ( ((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()); } }//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 ( ((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); } if(fDTDValidator != null){ fCurrentNode = node; fDTDValidator.startCDATA(null); String st = node.getNodeValue(); XMLString str = new XMLString(); if(st!=null) str.setValues(st.toCharArray(),0,st.length()); fDTDValidator.characters(str, null); fDTDValidator.endCDATA(null); } String value = node.getNodeValue(); if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) { int index; Node parent = node.getParentNode(); 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 { // check well-formness 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 ( ((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 (DEBUG_ND) { System.out.println("=====>characterData(),"+nextType); } } if(fDTDValidator != null){ fCurrentNode = node; String st = node.getNodeValue(); XMLString str = new XMLString(); if(st!=null) str.setValues(st.toCharArray(),0,st.length()); fDTDValidator.characters(str, null); if(isWhitespace) ((TextImpl)node).setIgnorableWhitespace(true); } } 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((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()); } }//end case Node.PROCESSING_INSTRUCTION_NODE }//end of switch return null; }//normalizeNode protected final void expandEntityRef(Node parent, Node reference){ Node kid, next; for (kid = reference.getFirstChild(); kid != null; kid = next) { next = kid.getNextSibling(); parent.insertBefore(kid, reference); } } // fix namespaces // normalize attribute values // remove default attributes // check attribute names if the version of the document changed. protected final void namespaceFixUp(ElementImpl element, AttributeMap attributes){ if (DEBUG) { System.out.println("[ns-fixup] element:" +element.getNodeName()+ " uri: "+element.getNamespaceURI()); } // ------------------------------------ // pick up local namespace declarations // // // // // ------------------------------------ String value, name, uri, prefix; if (attributes != null) { // Record all valid local declarations for (int k=0; k < attributes.getLength(); k++) { Attr attr = (Attr)attributes.getItem(k); //do the name check only when version of the document was changed & //application has set the value of well-formed features to true if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && fDocument.isXMLVersionChanged()){ //checkQName does checking based on the version of the document fDocument.checkQName(attr.getPrefix() , attr.getLocalName()) ; } 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 (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); //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: // We create another element body bound to the "http://xsl" namespace // as well as namespace attribute rebounding xsl to another namespace. // // 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, XMLSymbols.EMPTY_STRING); fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); } } } // ----------------------------------------- // 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(); name = attr.getNodeName(); uri = attr.getNamespaceURI(); // make sure that value is never null. if (value == null) { value=XMLSymbols.EMPTY_STRING; } 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; } //--------------------------------------- // check if value of the attribute is namespace well-formed //--------------------------------------- if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){ isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version()); if (fDocument.isXMLVersionChanged()){ boolean wellformed=CoreDocumentImpl.isXMLName(attr.getNodeName() , fDocument.isXML11Version()); if (!wellformed){ String msg = DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "wf-invalid-character-in-node-name", new Object[]{"Attribute", attr.getNodeName()}); reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character-in-node-name"); } } } // --------------------------------------- // 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 name = attr.getNodeName(); // 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 } /** * 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 */ protected final void addNamespaceDecl(String prefix, String uri, ElementImpl element){ 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); } } // // Methods for well-formness checking // /** * Check if CDATA section is well-formed * @param datavalue * @param isXML11Version = true if XML 1.1 */ public static final void isCDataWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, String datavalue, boolean isXML11Version) { 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)){ 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'){ //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) ){ //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'){ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,"CDEndInContent", null); reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); } } } } }//end-else fDocument.isXMLVersion() }//isCDataWF /** * NON-DOM: check for valid XML characters as per the XML version * @param datavalue * @param isXML11Version = true if XML 1.1 */ public static final void isXMLCharWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, String datavalue, boolean isXML11Version) { 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++])){ 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++]) ){ 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() }//isXMLCharWF /** * NON-DOM: check if value of the comment is well-formed * @param datavalue * @param isXML11Version = true if XML 1.1 */ public static final void isCommentWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, String datavalue, boolean isXML11Version) { 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)){ 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 == '-' && istrongly * 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 void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException{ } /** * 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. */ public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException{ } /** * 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 void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException{ } /** * 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 void comment(XMLString text, Augmentations augs) throws XNIException{ } /** * 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 void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException{ } /** * 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. */ public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { 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); 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); } 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. boolean specified = attr.getSpecified(); attr.setValue(attrPSVI.getSchemaNormalizedValue()); if (!specified) { ((AttrImpl) attr).setSpecified(specified); } } } } } /** * 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. */ public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { if (DEBUG_EVENTS) { System.out.println("==>emptyElement: " +element); } if(true) return; startElement(element, attributes, augs); endElement(element, 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 void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException{ } /** * 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. */ public void textDecl(String version, String encoding, Augmentations augs) throws XNIException{ } /** * 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. */ public void endGeneralEntity(String name, Augmentations augs) throws XNIException{ } /** * 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 void characters(XMLString text, Augmentations augs) throws XNIException{ } /** * 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. */ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{ if(docTypeFound){ isWhitespace = true; } } /** * 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. */ public void endElement(QName element, Augmentations augs) throws XNIException { if (DEBUG_EVENTS) { System.out.println("==>endElement: " + element); } if(augs == null) return; ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI); if (elementPSVI != null) { ElementImpl elementNode = (ElementImpl) fCurrentNode; if (fPSVI) { ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI); } // 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); } } } } /** * 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 void startCDATA(Augmentations augs) throws XNIException{ } /** * 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 void endCDATA(Augmentations augs) throws XNIException{ } /** * The end of the document. * * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void endDocument(Augmentations augs) throws XNIException{ } /** Sets the document source. */ public void setDocumentSource(XMLDocumentSource source){ } /** Returns the document source. */ public XMLDocumentSource getDocumentSource(){ return null; } public XMLGrammarPoolImpl getGrammarPool(String systemId, String internalSubset){ try{ XMLGrammarPreparser preparser = new XMLGrammarPreparser(fSymbolTable); XMLGrammarPoolImpl grammarPool = new XMLGrammarPoolImpl(); preparser.registerPreparser(XMLGrammarDescription.XML_DTD, null); preparser.setProperty(GRAMMAR_POOL, grammarPool); preparser.setFeature(NAMESPACES_FEATURE_ID, true); preparser.setFeature(VALIDATION_FEATURE_ID, true); Grammar g = null; if(systemId != null){ g = preparser.preparseGrammar(XMLGrammarDescription.XML_DTD,new XMLInputSource(null, systemId, null)); } if(internalSubset != null && !internalSubset.equals("")){ XMLInputSource xs = new XMLInputSource(null,systemId,null); xs.setCharacterStream(new StringReader(internalSubset)); g = preparser.preparseGrammar(XMLGrammarDescription.XML_DTD,xs); } return grammarPool; }catch(Exception ex){ if(DEBUG_ND) ex.printStackTrace(); } return null; } } // DOMNormalizer class