- /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 2001-2004 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) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
- package com.sun.org.apache.xerces.internal.parsers;
- import java.util.Locale;
- import java.util.Stack;
- import com.sun.org.apache.xerces.internal.dom.AttrImpl;
- import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
- import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
- import com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl;
- import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
- import com.sun.org.apache.xerces.internal.dom.DocumentTypeImpl;
- import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
- import com.sun.org.apache.xerces.internal.dom.ElementDefinitionImpl;
- import com.sun.org.apache.xerces.internal.dom.ElementImpl;
- import com.sun.org.apache.xerces.internal.dom.EntityImpl;
- import com.sun.org.apache.xerces.internal.dom.EntityReferenceImpl;
- import com.sun.org.apache.xerces.internal.dom.NodeImpl;
- import com.sun.org.apache.xerces.internal.dom.NotationImpl;
- import com.sun.org.apache.xerces.internal.dom.PSVIAttrNSImpl;
- import com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl;
- import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl;
- import com.sun.org.apache.xerces.internal.dom.TextImpl;
- import com.sun.org.apache.xerces.internal.impl.Constants;
- import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
- import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
- import com.sun.org.apache.xerces.internal.util.TypeInfoImpl;
- 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.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.parser.XMLParserConfiguration;
- 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.CDATASection;
- import org.w3c.dom.Comment;
- import org.w3c.dom.DOMError;
- import org.w3c.dom.Document;
- import org.w3c.dom.DocumentType;
- import org.w3c.dom.Element;
- import org.w3c.dom.EntityReference;
- 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;
- import org.w3c.dom.TypeInfo;
- import org.w3c.dom.ls.LSParserFilter;
- import org.w3c.dom.traversal.NodeFilter;
- /**
- * This is the base class of all DOM parsers. It implements the XNI
- * callback methods to create the DOM tree. After a successful parse of
- * an XML document, the DOM Document object can be queried using the
- * <code>getDocument</code> method. The actual pipeline is defined in
- * parser configuration.
- *
- * @author Arnaud Le Hors, IBM
- * @author Andy Clark, IBM
- * @author Elena Litani, IBM
- *
- * @version $Id: AbstractDOMParser.java,v 1.108 2004/02/17 07:14:48 neeraj Exp $
- */
- public class AbstractDOMParser extends AbstractXMLDocumentParser {
- //
- // Constants
- //
- // feature ids
- /** Feature id: namespace. */
- protected static final String NAMESPACES =
- Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
- /** Feature id: create entity ref nodes. */
- protected static final String CREATE_ENTITY_REF_NODES =
- Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
- /** Feature id: include comments. */
- protected static final String INCLUDE_COMMENTS_FEATURE =
- Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
- /** Feature id: create cdata nodes. */
- protected static final String CREATE_CDATA_NODES_FEATURE =
- Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
- /** Feature id: include ignorable whitespace. */
- protected static final String INCLUDE_IGNORABLE_WHITESPACE =
- Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
- /** Feature id: defer node expansion. */
- protected static final String DEFER_NODE_EXPANSION =
- Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
- /** Recognized features. */
- private static final String[] RECOGNIZED_FEATURES = {
- NAMESPACES,
- CREATE_ENTITY_REF_NODES,
- INCLUDE_COMMENTS_FEATURE,
- CREATE_CDATA_NODES_FEATURE,
- INCLUDE_IGNORABLE_WHITESPACE,
- DEFER_NODE_EXPANSION
- };
- // property ids
- /** Property id: document class name. */
- protected static final String DOCUMENT_CLASS_NAME =
- Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
- protected static final String CURRENT_ELEMENT_NODE=
- Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
- // protected static final String GRAMMAR_POOL =
- // Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
- /** Recognized properties. */
- private static final String[] RECOGNIZED_PROPERTIES = {
- DOCUMENT_CLASS_NAME,
- CURRENT_ELEMENT_NODE,
- };
- // other
- /** Default document class name. */
- protected static final String DEFAULT_DOCUMENT_CLASS_NAME =
- "com.sun.org.apache.xerces.internal.dom.DocumentImpl";
- protected static final String CORE_DOCUMENT_CLASS_NAME =
- "com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl";
- protected static final String PSVI_DOCUMENT_CLASS_NAME =
- "com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl";
- /**
- * If the user stops the process, this exception will be thrown.
- */
- public static final RuntimeException abort = new RuntimeException();
- // debugging
- private static final boolean DEBUG_EVENTS = false;
- private static final boolean DEBUG_BASEURI = false;
- //
- // Data
- //
- /** DOM L3 error handler */
- protected DOMErrorHandlerWrapper fErrorHandler = null;
- /** True if inside DTD. */
- protected boolean fInDTD;
- // features
- /** Create entity reference nodes. */
- protected boolean fCreateEntityRefNodes;
- /** Include ignorable whitespace. */
- protected boolean fIncludeIgnorableWhitespace;
- /** Include Comments. */
- protected boolean fIncludeComments;
- /** Create cdata nodes. */
- protected boolean fCreateCDATANodes;
- // dom information
- /** The document. */
- protected Document fDocument;
- /** The default Xerces document implementation, if used. */
- protected CoreDocumentImpl fDocumentImpl;
- /** Whether to store PSVI information in DOM tree. */
- protected boolean fStorePSVI;
- /** The document class name to use. */
- protected String fDocumentClassName;
- /** The document type node. */
- protected DocumentType fDocumentType;
- /** Current node. */
- protected Node fCurrentNode;
- protected CDATASection fCurrentCDATASection;
- protected EntityImpl fCurrentEntityDecl;
- protected int fDeferredEntityDecl;
- /** Character buffer */
- protected final StringBuffer fStringBuffer = new StringBuffer (50);
- // internal subset
- /** Internal subset buffer. */
- protected StringBuffer fInternalSubset;
- // deferred expansion data
- protected boolean fDeferNodeExpansion;
- protected boolean fNamespaceAware;
- protected DeferredDocumentImpl fDeferredDocumentImpl;
- protected int fDocumentIndex;
- protected int fDocumentTypeIndex;
- protected int fCurrentNodeIndex;
- protected int fCurrentCDATASectionIndex;
- // state
- /** True if inside DTD external subset. */
- protected boolean fInDTDExternalSubset;
- /** Root element name */
- protected QName fRoot = new QName();
- /** True if inside CDATA section. */
- protected boolean fInCDATASection;
- /** True if saw the first chunk of characters*/
- protected boolean fFirstChunk = false;
- /** LSParserFilter: specifies that element with given QNAME and all its children
- must be rejected */
- protected boolean fFilterReject = false;
- // data
- /** Base uri stack*/
- protected Stack fBaseURIStack = new Stack ();
- /** LSParserFilter: the QNAME of rejected element*/
- protected final QName fRejectedElement = new QName ();
- /** LSParserFilter: store qnames of skipped elements*/
- protected Stack fSkippedElemStack = null;
- /** LSParserFilter: true if inside entity reference */
- protected boolean fInEntityRef = false;
- /** Attribute QName. */
- private QName fAttrQName = new QName ();
- // handlers
- protected LSParserFilter fDOMFilter = null;
- //
- // Constructors
- //
- /** Default constructor. */
- protected AbstractDOMParser (XMLParserConfiguration config) {
- super (config);
- // add recognized features
- fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);
- // set default values
- fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, true);
- fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, true);
- fConfiguration.setFeature (DEFER_NODE_EXPANSION, true);
- fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, true);
- fConfiguration.setFeature (CREATE_CDATA_NODES_FEATURE, true);
- // add recognized properties
- fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);
- // set default values
- fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
- DEFAULT_DOCUMENT_CLASS_NAME);
- } // <init>(XMLParserConfiguration)
- /**
- * This method retreives the name of current document class.
- */
- protected String getDocumentClassName() {
- return fDocumentClassName;
- }
- /**
- * This method allows the programmer to decide which document
- * factory to use when constructing the DOM tree. However, doing
- * so will lose the functionality of the default factory. Also,
- * a document class other than the default will lose the ability
- * to defer node expansion on the DOM tree produced.
- *
- * @param documentClassName The fully qualified class name of the
- * document factory to use when constructing
- * the DOM tree.
- *
- * @see #getDocumentClassName
- * @see #DEFAULT_DOCUMENT_CLASS_NAME
- */
- protected void setDocumentClassName (String documentClassName) {
- // normalize class name
- if (documentClassName == null) {
- documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
- }
- if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME) &&
- !documentClassName.equals(PSVI_DOCUMENT_CLASS_NAME)) {
- // verify that this class exists and is of the right type
- try {
- Class _class = ObjectFactory.findProviderClass (documentClassName,
- ObjectFactory.findClassLoader (), true);
- //if (!_class.isAssignableFrom(Document.class)) {
- if (!Document.class.isAssignableFrom (_class)) {
- throw new IllegalArgumentException (
- DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "InvalidDocumentClassName", new Object [] {documentClassName}));
- }
- }
- catch (ClassNotFoundException e) {
- throw new IllegalArgumentException (
- DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "MissingDocumentClassName", new Object [] {documentClassName}));
- }
- }
- // set document class name
- fDocumentClassName = documentClassName;
- if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
- fDeferNodeExpansion = false;
- }
- } // setDocumentClassName(String)
- //
- // Public methods
- //
- /** Returns the DOM document object. */
- public Document getDocument() {
- return fDocument;
- } // getDocument():Document
- //
- // XMLDocumentParser methods
- //
- /**
- * Resets the parser state.
- *
- * @throws SAXException Thrown on initialization error.
- */
- public void reset () throws XNIException {
- super.reset ();
- // get feature state
- fCreateEntityRefNodes =
- fConfiguration.getFeature (CREATE_ENTITY_REF_NODES);
- fIncludeIgnorableWhitespace =
- fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE);
- fDeferNodeExpansion =
- fConfiguration.getFeature (DEFER_NODE_EXPANSION);
- fNamespaceAware = fConfiguration.getFeature (NAMESPACES);
- fIncludeComments = fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE);
- fCreateCDATANodes = fConfiguration.getFeature (CREATE_CDATA_NODES_FEATURE);
- // get property
- setDocumentClassName ((String)
- fConfiguration.getProperty (DOCUMENT_CLASS_NAME));
- // reset dom information
- fDocument = null;
- fDocumentImpl = null;
- fStorePSVI = false;
- fDocumentType = null;
- fDocumentTypeIndex = -1;
- fDeferredDocumentImpl = null;
- fCurrentNode = null;
- // reset string buffer
- fStringBuffer.setLength (0);
- // reset state information
- fRoot.clear();
- fInDTD = false;
- fInDTDExternalSubset = false;
- fInCDATASection = false;
- fFirstChunk = false;
- fCurrentCDATASection = null;
- fCurrentCDATASectionIndex = -1;
- fBaseURIStack.removeAllElements ();
- } // reset()
- /**
- * Set the locale to use for messages.
- *
- * @param locale The locale object to use for localization of messages.
- *
- */
- public void setLocale (Locale locale) {
- fConfiguration.setLocale (locale);
- } // setLocale(Locale)
- //
- // XMLDocumentHandler methods
- //
- /**
- * 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 {
- if (DEBUG_EVENTS) {
- System.out.println("==>startGeneralEntity ("+name+")");
- if (DEBUG_BASEURI) {
- System.out.println(" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId());
- System.out.println(" baseURI:"+ identifier.getBaseSystemId());
- }
- }
- // Always create entity reference nodes to be able to recreate
- // entity as a part of doctype
- if (!fDeferNodeExpansion) {
- if (fFilterReject) {
- return;
- }
- setCharacterData(true);
- EntityReference er = fDocument.createEntityReference(name);
- if (fDocumentImpl != null) {
- // REVISIT: baseURI/actualEncoding
- // remove dependency on our implementation when DOM L3 is REC
- //
- EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
- // set base uri
- erImpl.setBaseURI(identifier.getExpandedSystemId());
- if (fDocumentType != null) {
- // set actual encoding
- NamedNodeMap entities = fDocumentType.getEntities();
- fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name);
- if (fCurrentEntityDecl != null) {
- fCurrentEntityDecl.setInputEncoding(encoding);
- }
- }
- // we don't need synchronization now, because entity ref will be
- // expanded anyway. Synch only needed when user creates entityRef node
- erImpl.needsSyncChildren(false);
- }
- fInEntityRef = true;
- fCurrentNode.appendChild (er);
- fCurrentNode = er;
- }
- else {
- int er =
- fDeferredDocumentImpl.createDeferredEntityReference(name, identifier.getExpandedSystemId());
- if (fDocumentTypeIndex != -1) {
- // find corresponding Entity decl
- int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
- while (node != -1) {
- short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
- if (nodeType == Node.ENTITY_NODE) {
- String nodeName =
- fDeferredDocumentImpl.getNodeName(node, false);
- if (nodeName.equals(name)) {
- fDeferredEntityDecl = node;
- fDeferredDocumentImpl.setInputEncoding(node, encoding);
- break;
- }
- }
- node = fDeferredDocumentImpl.getRealPrevSibling(node, false);
- }
- }
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, er);
- fCurrentNodeIndex = er;
- }
- } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
- /**
- * 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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
- if (fInDTD){
- return;
- }
- if (!fDeferNodeExpansion) {
- if (fCurrentEntityDecl != null && !fFilterReject) {
- fCurrentEntityDecl.setXmlEncoding(encoding);
- if(version != null)
- fCurrentEntityDecl.setXmlVersion(version);
- }
- }
- else {
- if (fDeferredEntityDecl !=-1) {
- fDeferredDocumentImpl.setEntityInfo(fDeferredEntityDecl, version, encoding);
- }
- }
- } // textDecl(String,String)
- /**
- * A comment.
- *
- * @param text The text in the comment.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by application to signal an error.
- */
- public void comment(XMLString text, Augmentations augs) throws XNIException {
- if (fInDTD) {
- if (fInternalSubset != null && !fInDTDExternalSubset) {
- fInternalSubset.append("<!-- ");
- fInternalSubset.append(text.toString());
- fInternalSubset.append(" -->");
- }
- return;
- }
- if (!fIncludeComments || fFilterReject) {
- return;
- }
- if (!fDeferNodeExpansion) {
- Comment comment = fDocument.createComment (text.toString ());
- setCharacterData (false);
- fCurrentNode.appendChild (comment);
- if (fDOMFilter !=null && !fInEntityRef &&
- (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_COMMENT)!= 0) {
- short code = fDOMFilter.acceptNode (comment);
- switch (code) {
- case LSParserFilter.FILTER_INTERRUPT:{
- throw abort;
- }
- case LSParserFilter.FILTER_REJECT:{
- // REVISIT: the constant FILTER_REJECT should be changed when new
- // DOM LS specs gets published
- // fall through to SKIP since comment has no children.
- }
- case LSParserFilter.FILTER_SKIP: {
- // REVISIT: the constant FILTER_SKIP should be changed when new
- // DOM LS specs gets published
- fCurrentNode.removeChild(comment);
- // make sure we don't loose chars if next event is characters()
- fFirstChunk = true;
- return;
- }
- default: {
- // accept node
- }
- }
- }
- }
- else {
- int comment =
- fDeferredDocumentImpl.createDeferredComment(text.toString());
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, comment);
- }
- } // comment(XMLString)
- /**
- * 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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void processingInstruction (String target, XMLString data, Augmentations augs)
- throws XNIException {
- if (fInDTD) {
- if (fInternalSubset != null && !fInDTDExternalSubset) {
- fInternalSubset.append ("<?");
- fInternalSubset.append (target.toString ());
- fInternalSubset.append (' ');
- fInternalSubset.append (data.toString ());
- fInternalSubset.append ("?>");
- }
- return;
- }
- if (DEBUG_EVENTS) {
- System.out.println ("==>processingInstruction ("+target+")");
- }
- if (!fDeferNodeExpansion) {
- if (fFilterReject) {
- return;
- }
- ProcessingInstruction pi =
- fDocument.createProcessingInstruction (target, data.toString ());
- setCharacterData (false);
- fCurrentNode.appendChild (pi);
- if (fDOMFilter !=null && !fInEntityRef &&
- (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
- short code = fDOMFilter.acceptNode (pi);
- switch (code) {
- case LSParserFilter.FILTER_INTERRUPT:{
- throw abort;
- }
- case LSParserFilter.FILTER_REJECT:{
- // fall through to SKIP since PI has no children.
- }
- case LSParserFilter.FILTER_SKIP: {
- fCurrentNode.removeChild(pi);
- // fFirstChunk must be set to true so that data
- // won't be lost in the case where the child before PI is
- // a text node and the next event is characters.
- fFirstChunk = true;
- return;
- }
- default: {
- }
- }
- }
- }
- else {
- int pi = fDeferredDocumentImpl.
- createDeferredProcessingInstruction(target, data.toString());
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
- }
- } // processingInstruction(String,XMLString)
- /**
- * The start of the document.
- *
- * @param locator The system identifier of the entity if the entity
- * is external, null otherwise.
- * @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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startDocument (XMLLocator locator, String encoding,
- NamespaceContext namespaceContext, Augmentations augs)
- throws XNIException {
- if (!fDeferNodeExpansion) {
- if (fDocumentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
- fDocument = new DocumentImpl ();
- fDocumentImpl = (CoreDocumentImpl)fDocument;
- // REVISIT: when DOM Level 3 is REC rely on Document.support
- // instead of specific class
- // set DOM error checking off
- fDocumentImpl.setStrictErrorChecking (false);
- // set actual encoding
- fDocumentImpl.setInputEncoding (encoding);
- // set documentURI
- fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
- }
- else if (fDocumentClassName.equals (PSVI_DOCUMENT_CLASS_NAME)) {
- fDocument = new PSVIDocumentImpl();
- fDocumentImpl = (CoreDocumentImpl)fDocument;
- fStorePSVI = true;
- // REVISIT: when DOM Level 3 is REC rely on Document.support
- // instead of specific class
- // set DOM error checking off
- fDocumentImpl.setStrictErrorChecking (false);
- // set actual encoding
- fDocumentImpl.setInputEncoding (encoding);
- // set documentURI
- fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
- }
- else {
- // use specified document class
- try {
- ClassLoader cl = ObjectFactory.findClassLoader();
- Class documentClass = ObjectFactory.findProviderClass (fDocumentClassName,
- cl, true);
- fDocument = (Document)documentClass.newInstance ();
- // if subclass of our own class that's cool too
- Class defaultDocClass =
- ObjectFactory.findProviderClass (CORE_DOCUMENT_CLASS_NAME,
- cl, true);
- if (defaultDocClass.isAssignableFrom (documentClass)) {
- fDocumentImpl = (CoreDocumentImpl)fDocument;
- Class psviDocClass = ObjectFactory.findProviderClass (PSVI_DOCUMENT_CLASS_NAME,
- cl, true);
- if (psviDocClass.isAssignableFrom (documentClass)) {
- fStorePSVI = true;
- }
- // REVISIT: when DOM Level 3 is REC rely on
- // Document.support instead of specific class
- // set DOM error checking off
- fDocumentImpl.setStrictErrorChecking(false);
- // set actual encoding
- fDocumentImpl.setInputEncoding(encoding);
- // set documentURI
- if (locator != null) {
- fDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
- }
- }
- }
- catch (ClassNotFoundException e) {
- // won't happen we already checked that earlier
- }
- catch (Exception e) {
- throw new RuntimeException (
- DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "CannotCreateDocumentClass",
- new Object [] {fDocumentClassName}));
- }
- }
- fCurrentNode = fDocument;
- }
- else {
- fDeferredDocumentImpl = new DeferredDocumentImpl(fNamespaceAware);
- fDocument = fDeferredDocumentImpl;
- fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument();
- // REVISIT: strict error checking is not implemented in deferred dom.
- // Document.support instead of specific class
- // set actual encoding
- fDeferredDocumentImpl.setInputEncoding(encoding);
- // set documentURI
- fDeferredDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
- fCurrentNodeIndex = fDocumentIndex;
- }
- } // startDocument(String,String)
- /**
- * 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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void xmlDecl(String version, String encoding, String standalone,
- Augmentations augs)
- throws XNIException {
- if (!fDeferNodeExpansion) {
- // REVISIT: when DOM Level 3 is REC rely on Document.support
- // instead of specific class
- if (fDocumentImpl != null) {
- if(version != null)
- fDocumentImpl.setXmlVersion(version);
- fDocumentImpl.setXmlEncoding(encoding);
- fDocumentImpl.setXmlStandalone("yes".equals(standalone));
- }
- }
- else {
- if(version != null)
- fDeferredDocumentImpl.setXmlVersion(version);
- fDeferredDocumentImpl.setXmlEncoding(encoding);
- fDeferredDocumentImpl.setXmlStandalone("yes".equals(standalone));
- }
- } // xmlDecl(String,String,String)
- /**
- * 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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void doctypeDecl (String rootElement,
- String publicId, String systemId, Augmentations augs)
- throws XNIException {
- if (!fDeferNodeExpansion) {
- if (fDocumentImpl != null) {
- fDocumentType = fDocumentImpl.createDocumentType(
- rootElement, publicId, systemId);
- fCurrentNode.appendChild(fDocumentType);
- }
- }
- else {
- fDocumentTypeIndex = fDeferredDocumentImpl.
- createDeferredDocumentType(rootElement, publicId, systemId);
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, fDocumentTypeIndex);
- }
- } // doctypeDecl(String,String,String)
- /**
- * The start of an element. If the document specifies the start element
- * by using an empty tag, then the startElement method will immediately
- * be followed by the endElement method, with no intervening methods.
- *
- * @param element The name of the element.
- * @param attributes The element attributes.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
- throws XNIException {
- if (DEBUG_EVENTS) {
- System.out.println("==>startElement ("+element.rawname+")");
- }
- if (!fDeferNodeExpansion) {
- if (fFilterReject) {
- return;
- }
- Element el = createElementNode(element);
- int attrCount = attributes.getLength();
- for (int i = 0; i < attrCount; i++) {
- attributes.getName (i, fAttrQName);
- Attr attr = createAttrNode (fAttrQName);
- String attrValue = attributes.getValue (i);
- Augmentations aaugs = attributes.getAugmentations(i);
- AttributePSVI attrPSVI =(AttributePSVI) aaugs.getItem(Constants.ATTRIBUTE_PSVI);
- if (fStorePSVI && attrPSVI != null){
- ((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
- }
- attr.setValue(attrValue);
- el.setAttributeNode(attr);
- // NOTE: The specified value MUST be set after you set
- // the node value because that turns the "specified"
- // flag to "true" which may overwrite a "false"
- // value from the attribute list. -Ac
- if (fDocumentImpl != null) {
- AttrImpl attrImpl = (AttrImpl)attr;
- attrImpl.setType(getAttributeType(attributes,aaugs,i));
- if (isIdAttribute(attributes,aaugs,i)) {
- ((ElementImpl)el).setIdAttributeNode(attr, true);
- }
- attrImpl.setSpecified(attributes.isSpecified(i));
- // REVISIT: Handle entities in attribute value.
- }
- }
- setCharacterData (false);
- ((ElementImpl)el).setType(getElementTypeInfoFromAugs(augs));
- // filter nodes
- if (fDOMFilter != null && !fInEntityRef) {
- if (fRoot.rawname == null) {
- // fill value of the root element
- fRoot.setValues(element);
- } else {
- short code = fDOMFilter.startElement(el);
- switch (code) {
- case LSParserFilter.FILTER_INTERRUPT :
- {
- throw abort;
- }
- case LSParserFilter.FILTER_REJECT :
- {
- fFilterReject = true;
- fRejectedElement.setValues(element);
- return;
- }
- case LSParserFilter.FILTER_SKIP :
- {
- fSkippedElemStack.push(new QName(element));
- return;
- }
- default : {}
- }
- }
- }
- fCurrentNode.appendChild (el);
- fCurrentNode = el;
- }
- else {
- int el =
- fDeferredDocumentImpl.createDeferredElement(fNamespaceAware ?
- element.uri : null,
- element.rawname,
- getElementTypeInfoFromAugs(augs));
- int attrCount = attributes.getLength();
- for (int i = 0; i < attrCount; i++) {
- // set type information
- Augmentations aaugs = attributes.getAugmentations(i);
- // create attribute
- fDeferredDocumentImpl.setDeferredAttribute(
- el,
- attributes.getQName(i),
- attributes.getURI(i),
- attributes.getValue(i),
- attributes.isSpecified(i),
- isIdAttribute(attributes,aaugs,i),
- getAttributeType(attributes,aaugs,i));
- }
- fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
- fCurrentNodeIndex = el;
- }
- } // startElement(QName,XMLAttributes)
- /**
- * Returns true if the given attribute is marked as ID.
- */
- private boolean isIdAttribute(XMLAttributes attributes,Augmentations augs, int index) {
- // look for augmentation first.
- Object o = augs.getItem(Constants.ID_ATTRIBUTE);
- if( o instanceof Boolean )
- return ((Boolean)o).booleanValue();
- // otherwise fall back to the DTD mode.
- return "ID".equals(attributes.getType(index));
- }
- /**
- * Returns {@link TypeInfo} for the given attribute.
- */
- private TypeInfo getAttributeType(XMLAttributes attributes,Augmentations augs, int index) {
- // look for augmentation
- TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
- if(type!=null) return type;
- boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (index).getItem (Constants.ATTRIBUTE_DECLARED));
- // otherwise fall back to the DTD mode.
- if (isDeclared )
- return TypeInfoImpl.getDTDTypeInfo(attributes.getType(index));
- else
- return new TypeInfoImpl();
- }
- /**
- * Looks for {@link TypeInfo} object for the element in the augmentation.
- *
- * @return null if not found.
- */
- private TypeInfo getElementTypeInfoFromAugs( Augmentations augs ) {
- //simple fix to handle dtd case.
- if (augs == null) return new TypeInfoImpl();
- // if an external validator is used via JAXP, this would be set.
- TypeInfo ti = (TypeInfo)augs.getItem(Constants.TYPEINFO);
- if(ti!=null) return ti;
- // Xerces native validator would set this.
- ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
- if (elementPSVI == null) return null;
- XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
- if( type!=null ) return type;
- return elementPSVI.getTypeDefinition();
- }
- // /**
- // * Looks for {@link TypeInfo} object for the attribute in the augmentation.
- // */
- // private TypeInfo getAttribtueTypeInfoFromAugs( XMLAttributes atts, int idx ) {
- // Augmentations augs = atts.getAugmentations(idx);
- //
- // // if an external validator is used via JAXP, this would be set.
- // TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
- // if(type!=null) return type;
- //
- // // look for PSVI
- // AttributePSVI attrPSVI =(AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
- // if (attrPSVI != null) {
- // type = attrPSVI.getMemberTypeDefinition();
- // if (type == null)
- // type = attrPSVI.getTypeDefinition();
- //
- // return type;
- // }
- //
- // // if everything else fails, fall back to the DTD type.
- // String typeName = atts.getType(idx);
- // return new TypeInfoImpl(null, typeName);
- // }
- /**
- * An empty element.
- *
- * @param element The name of the element.
- * @param attributes The element attributes.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void emptyElement (QName element, XMLAttributes attributes, Augmentations augs)
- throws XNIException {
- startElement (element, attributes, augs);
- endElement (element, augs);
- } // emptyElement(QName,XMLAttributes)
- /**
- * Character content.
- *
- * @param text The content.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void characters (XMLString text, Augmentations augs) throws XNIException {
- if (DEBUG_EVENTS) {
- System.out.println("==>characters(): "+text.toString());
- }
- if (!fDeferNodeExpansion) {
- if (fFilterReject) {
- return;
- }
- if (fInCDATASection && fCreateCDATANodes) {
- if (fCurrentCDATASection == null) {
- fCurrentCDATASection =
- fDocument.createCDATASection(text.toString());
- fCurrentNode.appendChild(fCurrentCDATASection);
- fCurrentNode = fCurrentCDATASection;
- }
- else {
- fCurrentCDATASection.appendData(text.toString());
- }
- }
- else if (!fInDTD) {
- // if type is union (XML Schema) it is possible that we receive
- // character call with empty data
- if (text.length == 0) {
- return;
- }
- String value = text.toString ();
- Node child = fCurrentNode.getLastChild ();
- if (child != null && child.getNodeType () == Node.TEXT_NODE) {
- // collect all the data into the string buffer.
- if (fFirstChunk) {
- if (fDocumentImpl != null) {
- fStringBuffer.append(((TextImpl)child).removeData());
- } else {
- fStringBuffer.append(((Text)child).getData());
- ((Text)child).setNodeValue(null);
- }
- fFirstChunk = false;
- }
- fStringBuffer.append(value);
- }
- else {
- fFirstChunk = true;
- Text textNode = fDocument.createTextNode(value);
- fCurrentNode.appendChild(textNode);
- }
- }
- }
- else {
- // The Text and CDATASection normalization is taken care of within
- // the DOM in the deferred case.
- if (fInCDATASection && fCreateCDATANodes) {
- if (fCurrentCDATASectionIndex == -1) {
- int cs = fDeferredDocumentImpl.
- createDeferredCDATASection (text.toString ());
- fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, cs);
- fCurrentCDATASectionIndex = cs;
- fCurrentNodeIndex = cs;
- }
- else {
- int txt = fDeferredDocumentImpl.
- createDeferredTextNode(text.toString(), false);
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
- }
- } else if (!fInDTD) {
- // if type is union (XML Schema) it is possible that we receive
- // character call with empty data
- if (text.length == 0) {
- return;
- }
- String value = text.toString ();
- int txt = fDeferredDocumentImpl.
- createDeferredTextNode (value, false);
- fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
- }
- }
- } // characters(XMLString)
- /**
- * 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
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void ignorableWhitespace (XMLString text, Augmentations augs) throws XNIException {
- if (!fIncludeIgnorableWhitespace || fFilterReject) {
- return;
- }
- if (!fDeferNodeExpansion) {
- Node child = fCurrentNode.getLastChild();
- if (child != null && child.getNodeType() == Node.TEXT_NODE) {
- Text textNode = (Text)child;
- textNode.appendData(text.toString());
- }
- else {
- Text textNode = fDocument.createTextNode(text.toString());
- if (fDocumentImpl != null) {
- TextImpl textNodeImpl = (TextImpl)textNode;
- textNodeImpl.setIgnorableWhitespace(true);
- }
- fCurrentNode.appendChild(textNode);
- }
- }
- else {
- // The Text normalization is taken care of within the DOM in the
- // deferred case.
- int txt = fDeferredDocumentImpl.
- createDeferredTextNode(text.toString(), true);
- fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
- }
- } // ignorableWhitespace(XMLString)
- /**
- * The end of an element.
- *
- * @param element The name of the element.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws 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.rawname+")");
- }
- if (!fDeferNodeExpansion) {
- // REVISIT: Should this happen after we call the filter?
- if (fStorePSVI && augs != null) {
- ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
- if (elementPSVI != null) {
- ((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI);
- }
- }
- if (fDOMFilter != null) {
- if (fFilterReject) {
- if (element.equals(fRejectedElement)) {
- fFilterReject = false;
- }
- return;
- }
- if (!fSkippedElemStack.isEmpty()) {
- if (fSkippedElemStack.peek().equals(element)) {
- fSkippedElemStack.pop();
- return;
- }
- }
- setCharacterData (false);
- if (!fRoot.equals(element) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
- short code = fDOMFilter.acceptNode (fCurrentNode);
- switch (code) {
- case LSParserFilter.FILTER_INTERRUPT:{
- throw abort;
- }
- case LSParserFilter.FILTER_REJECT:{
- Node parent = fCurrentNode.getParentNode();
- parent.removeChild(fCurrentNode);
- fCurrentNode = parent;
- return;
- }
- case LSParserFilter.FILTER_SKIP: {
- // make sure that if any char data is available
- // the fFirstChunk is true, so that if the next event
- // is characters(), and the last node is text, we will copy
- // the value already in the text node to fStringBuffer
- // (not to loose it).
- fFirstChunk = true;
- // replace children
- Node parent = fCurrentNode.getParentNode ();
- NodeList ls = fCurrentNode.getChildNodes ();
- int