| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Copyright 1999-2002,2004, 2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.sun.org.apache.xerces.internal.dom; |
| |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.io.StringReader; |
| import java.util.Vector; |
| |
| 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.dtd.DTDGrammar; |
| import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; |
| import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator; |
| import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; |
| import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; |
| import com.sun.org.apache.xerces.internal.parsers.XMLGrammarPreparser; |
| 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.XML11Char; |
| import com.sun.org.apache.xerces.internal.util.XMLChar; |
| import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; |
| 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.grammars.XMLGrammarPool; |
| 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.xni.parser.XMLInputSource; |
| import com.sun.org.apache.xerces.internal.xs.AttributePSVI; |
| import com.sun.org.apache.xerces.internal.xs.ElementPSVI; |
| import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Comment; |
| import org.w3c.dom.DOMError; |
| import org.w3c.dom.DOMErrorHandler; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentType; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Entity; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.ProcessingInstruction; |
| import org.w3c.dom.Text; |
| /** |
| * 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,v 1.9 2010-11-01 04:39:38 joehw Exp $ |
| */ |
| public class DOMNormalizer implements XMLDocumentHandler { |
| |
| // |
| // 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; |
| |
| /** 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 ArrayList fAttributeList = new ArrayList(5); |
| |
| /** 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(); |
| |
| //DTD validator |
| private XMLDTDValidator fDTDValidator; |
| |
| //Check if element content is all "ignorable whitespace" |
| private boolean allWhitespace = false; |
| |
| // Constructor |
| // |
| |
| 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); |
| |
| if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) { |
| String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE); |
| |
| if(schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) { |
| fValidationHandler = |
| CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_SCHEMA); |
| 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; |
| } |
| |
| fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true); |
| |
| // reset ID table |
| fDocument.clearIdentifiers(); |
| |
| if(fValidationHandler != null) |
| // reset schema validator |
| ((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( 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}"); |
| } |
| DocumentTypeImpl docType = (DocumentTypeImpl)node; |
| fDTDValidator = (XMLDTDValidator)CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_DTD); |
| fDTDValidator.setDocumentHandler(this); |
| fConfiguration.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, createGrammarPool(docType)); |
| fDTDValidator.reset(fConfiguration); |
| fDTDValidator.startDocument( |
| new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI, |
| -1, -1 ), fDocument.encoding, fNamespaceContext, null); |
| fDTDValidator.doctypeDecl(docType.getName(), docType.getPublicId(), docType.getSystemId(), null); |
| //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 (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, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version()); |
| if (fDocument.isXMLVersionChanged()){ |
| 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); |
| } |
| |
| if (fDTDValidator != 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 |
| fDTDValidator.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); |
| } |
| |
| if (fDTDValidator != 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; |
| fDTDValidator.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()); |
| } |
| }//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); |
| } |
| |
| if (fDTDValidator != 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; |
| fDTDValidator.startCDATA(null); |
| fDTDValidator.characterData(node.getNodeValue(), null); |
| fDTDValidator.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 (DEBUG_ND) { |
| System.out.println("=====>characterData(),"+nextType); |
| |
| } |
| } |
| if (fDTDValidator != null) { |
| fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; |
| fCurrentNode = node; |
| fDTDValidator.characterData(node.getNodeValue(), null); |
| if (DEBUG_ND) { |
| System.out.println("=====>characterData(),"+nextType); |
| |
| } |
| if(allWhitespace) { |
| allWhitespace = false; |
| ((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 (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()); |
| } |
| }//end case Node.PROCESSING_INSTRUCTION_NODE |
| |
| }//end of switch |
| return null; |
| }//normalizeNode |
| |
| private XMLGrammarPool createGrammarPool(DocumentTypeImpl docType) { |
| |
| XMLGrammarPoolImpl pool = new XMLGrammarPoolImpl(); |
| |
| XMLGrammarPreparser preParser = new XMLGrammarPreparser(fSymbolTable); |
| preParser.registerPreparser(XMLGrammarDescription.XML_DTD, null); |
| preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true); |
| preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, true); |
| preParser.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, pool); |
| |
| String internalSubset = docType.getInternalSubset(); |
| XMLInputSource is = new XMLInputSource(docType.getPublicId(), docType.getSystemId(), null); |
| |
| if(internalSubset != null) |
| is.setCharacterStream(new StringReader(internalSubset)); |
| try { |
| DTDGrammar g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); |
| ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); |
| is.setCharacterStream(null); |
| g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); |
| ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); |
| |
| } catch (XNIException e) { |
| } catch (IOException e) { |
| } |
| |
| return pool; |
| } |
| |
| |
| |
| 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 |
| // <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, 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 (fDocument.errorChecking && ((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 |
| |
| // "namespace-declarations" == false; Discard all namespace declaration attributes |
| if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) { |
| continue; |
| } |
| |
| 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); |
| //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(); |
| |
| // "namespace-declarations" == false? Discard all namespace declaration attributes |
| if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) { |
| // no namespace declaration == no namespace URI, semantics are to keep prefix |
| uri = null; |
| } else 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.get(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 (fDocument.errorChecking && ((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) ) { |
| // 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() |
| |
| } // 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++])){ |
| // 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() |
| |
| } // 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) ) { |
| // 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() |
| |
| } // isCommentWF |
| |
| /** NON-DOM: check if attribute value is well-formed |
| * @param attributes |
| * @param a |
| * @param value |
| */ |
| public static final void isAttrValueWF(DOMErrorHandler errorHandler, DOMErrorImpl error, |
| DOMLocatorImpl locator, NamedNodeMap attributes, Attr a, String value, boolean xml11Version) { |
| 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); |
| } |
| } |
| } |
| } |
| |
| |
| |
| /** |
| * Reports a DOM error to the user handler. |
| * |
| * If the error is fatal, the processing will be always aborted. |
| */ |
| public static final void reportDOMError(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, |
| String message, short severity, String type ) { |
| 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; |
| } |
| |
| protected final void updateQName (Node node, 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; |
| } |
| |
| |
| |
| /* REVISIT: remove this method if DOM does not change spec. |
| * Performs partial XML 1.0 attribute value normalization and replaces |
| * attribute value if the value is changed after the normalization. |
| * DOM defines that normalizeDocument acts as if the document was going |
| * through a save and load cycle, given that serializer will not escape |
| * any '\n' or '\r' characters on load those will be normalized. |
| * Thus during normalize document we need to do the following: |
| * - perform "2.11 End-of-Line Handling" |
| * - replace #xD, #xA, #x9 with #x20 (white space). |
| * Note: This alg. won't attempt to resolve entity references or character entity |
| * references, since '&' will be escaped during serialization and during loading |
| * this won't be recognized as entity reference, i.e. attribute value "&foo;" will |
| * be serialized as "&foo;" and thus after loading will be "&foo;" again. |
| * @param value current attribute value |
| * @param attr current attribute |
| * @return String the value (could be original if normalization did not change |
| * the string) |
| */ |
| final String normalizeAttributeValue(String value, 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 final class XMLAttributesProxy |
| implements XMLAttributes { |
| protected AttributeMap fAttributes; |
| protected CoreDocumentImpl fDocument; |
| protected ElementImpl fElement; |
| |
| protected final Vector fAugmentations = new Vector(5); |
| |
| |
| public void setAttributes(AttributeMap attributes, CoreDocumentImpl doc, ElementImpl elem) { |
| fDocument = doc; |
| fAttributes = attributes; |
| fElement = elem; |
| if (attributes != null) { |
| int length = attributes.getLength(); |
| |
| fAugmentations.setSize(length); |
| // REVISIT: this implementation does not store any value in augmentations |
| // and basically not keeping augs in parallel to attributes map |
| // untill all attributes are added (default attributes) |
| for (int i = 0; i < length; i++) { |
| fAugmentations.setElementAt(new AugmentationsImpl(), i); |
| } |
| } else { |
| fAugmentations.setSize(0); |
| } |
| } |
| |
| |
| /** |
| * This method adds default declarations |
| * @see com.sun.org.apache.xerces.internal.xni.XMLAttributes#addAttribute(QName, String, String) |
| */ |
| public int addAttribute(QName qname, String attrType, String attrValue) { |
| int index = fElement.getXercesAttribute(qname.uri, qname.localpart); |
| // add defaults to the tree |
| if (index < 0) { |
| // the default attribute was removed by a user and needed to |
| // be added back |
| AttrImpl attr = (AttrImpl) |
| ((CoreDocumentImpl) fElement.getOwnerDocument()).createAttributeNS( |
| qname.uri, |
| qname.rawname, |
| qname.localpart); |
| // REVISIT: the following should also update ID table |
| attr.setNodeValue(attrValue); |
| index = fElement.setXercesAttributeNode(attr); |
| fAugmentations.insertElementAt(new AugmentationsImpl(), index); |
| attr.setSpecified(false); |
| } |
| else { |
| // default attribute is in the tree |
| // we don't need to do anything since prefix was already fixed |
| // at the namespace fixup time and value must be same value, otherwise |
| // attribute will be treated as specified and we will never reach |
| // this method. |
| |
| } |
| return index; |
| } |
| |
| |
| public void removeAllAttributes(){ |
| // REVISIT: implement |
| } |
| |
| |
| public void removeAttributeAt(int attrIndex){ |
| // REVISIT: implement |
| } |
| |
| |
| public int getLength(){ |
| return(fAttributes != null)?fAttributes.getLength():0; |
| } |
| |
| |
| public int getIndex(String qName){ |
| // REVISIT: implement |
| return -1; |
| } |
| |
| public int getIndex(String uri, String localPart){ |
| // REVISIT: implement |
| return -1; |
| } |
| |
| public void setName(int attrIndex, QName attrName){ |
| // REVISIT: implement |
| } |
| |
| public void getName(int attrIndex, QName attrName){ |
| if (fAttributes !=null) { |
| updateQName((Node)fAttributes.getItem(attrIndex), attrName); |
| } |
| } |
| |
| public String getPrefix(int index){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| |
| public String getURI(int index){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| |
| public String getLocalName(int index){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| |
| public String getQName(int index){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| public QName getQualifiedName(int index){ |
| //return fAttributes.item(index).ge); |
| return null; |
| } |
| |
| public void setType(int attrIndex, String attrType){ |
| // REVISIT: implement |
| } |
| |
| |
| public String getType(int index){ |
| return "CDATA"; |
| } |
| |
| |
| public String getType(String qName){ |
| return "CDATA"; |
| } |
| |
| |
| public String getType(String uri, String localName){ |
| return "CDATA"; |
| } |
| |
| |
| public void setValue(int attrIndex, String attrValue){ |
| // REVISIT: is this desired behaviour? |
| // The values are updated in the case datatype-normalization is turned on |
| // in this case we need to make sure that specified attributes stay specified |
| |
| if (fAttributes != null){ |
| AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex); |
| boolean specified = attr.getSpecified(); |
| attr.setValue(attrValue); |
| attr.setSpecified(specified); |
| |
| } |
| } |
| |
| public void setValue(int attrIndex, String attrValue, XMLString value){ |
| setValue(attrIndex, value.toString()); |
| } |
| |
| public String getValue(int index){ |
| return (fAttributes !=null)?fAttributes.item(index).getNodeValue():""; |
| |
| } |
| |
| |
| public String getValue(String qName){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| |
| public String getValue(String uri, String localName){ |
| if (fAttributes != null) { |
| Node node = fAttributes.getNamedItemNS(uri, localName); |
| return(node != null)? node.getNodeValue():null; |
| } |
| return null; |
| } |
| |
| |
| public void setNonNormalizedValue(int attrIndex, String attrValue){ |
| // REVISIT: implement |
| |
| } |
| |
| |
| public String getNonNormalizedValue(int attrIndex){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| |
| public void setSpecified(int attrIndex, boolean specified){ |
| AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex); |
| attr.setSpecified(specified); |
| } |
| |
| public boolean isSpecified(int attrIndex){ |
| return((Attr)fAttributes.getItem(attrIndex)).getSpecified(); |
| } |
| |
| public Augmentations getAugmentations (int attributeIndex){ |
| return(Augmentations)fAugmentations.elementAt(attributeIndex); |
| } |
| |
| public Augmentations getAugmentations (String uri, String localPart){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| public Augmentations getAugmentations(String qName){ |
| // REVISIT: implement |
| return null; |
| } |
| |
| /** |
| * Sets the augmentations of the attribute at the specified index. |
| * |
| * @param attrIndex The attribute index. |
| * @param augs The augmentations. |
| */ |
| public void setAugmentations(int attrIndex, Augmentations augs) { |
| fAugmentations.setElementAt(augs, attrIndex); |
| } |
| } |
| |
| // |
| // XMLDocumentHandler methods |
| // |
| |
| /** |
| * 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 <em>strongly</em> |
| * 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. |
| * <p> |
| * Typically, a processing instruction's data will contain a series |
| * of pseudo-attributes. These pseudo-attributes follow the form of |
| * element attributes but are <strong>not</strong> 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); |
| } |
| |
| startElement(element, attributes, augs); |
| endElement(element, augs); |
| } |
| |
| /** |
| * This method notifies the start of a general entity. |
| * <p> |
| * <strong>Note:</strong> 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. |
| * <p> |
| * <strong>Note:</strong> This method will never be called for the |
| * document entity; it is only called for external general entities |
| * referenced in document content. |
| * <p> |
| * <strong>Note:</strong> 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. |
| * <p> |
| * <strong>Note:</strong> 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{ |
| allWhitespace = 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) { |
| 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; |
| } |
| |
| |
| } // DOMNormalizer class |