aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java')
-rw-r--r--src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java2661
1 files changed, 2661 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java b/src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java
new file mode 100644
index 0000000..b425566
--- /dev/null
+++ b/src/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractDOMParser.java
@@ -0,0 +1,2661 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2001-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.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.DOMMessageFormatter;
+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.ElementDefinitionImpl;
+import com.sun.org.apache.xerces.internal.dom.ElementImpl;
+import com.sun.org.apache.xerces.internal.dom.ElementNSImpl;
+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.impl.dv.XSSimpleType;
+import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
+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 com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
+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.ls.LSParserFilter;
+import org.w3c.dom.traversal.NodeFilter;
+import org.xml.sax.SAXException;
+
+/**
+ * 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.10 2010-11-01 04:40:09 joehw 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.
+ */
+ static final class Abort extends RuntimeException {
+ private static final long serialVersionUID = 1687848994976808490L;
+ static final Abort INSTANCE = new Abort();
+ private Abort() {}
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+ }
+
+ // 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 StringBuilder fStringBuilder = new StringBuilder (50);
+
+ // internal subset
+
+ /** Internal subset buffer. */
+ protected StringBuilder 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 node. */
+ protected Node fRoot;
+
+ /** 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 final Stack fBaseURIStack = new Stack ();
+
+ /** LSParserFilter: tracks the element depth within a rejected subtree. */
+ protected int fRejectedElementDepth = 0;
+
+ /** LSParserFilter: store depth of skipped elements */
+ protected Stack fSkippedElemStack = null;
+
+ /** LSParserFilter: true if inside entity reference */
+ protected boolean fInEntityRef = false;
+
+ /** Attribute QName. */
+ private final QName fAttrQName = new QName();
+
+ /** Document locator. */
+ private XMLLocator fLocator;
+
+ // 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
+
+ /**
+ * Drops all references to the last DOM which was built by this parser.
+ */
+ public final void dropDocumentReferences() {
+ fDocument = null;
+ fDocumentImpl = null;
+ fDeferredDocumentImpl = null;
+ fDocumentType = null;
+ fCurrentNode = null;
+ fCurrentCDATASection = null;
+ fCurrentEntityDecl = null;
+ fRoot = null;
+ } // dropDocumentReferences()
+
+ //
+ // 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
+ fStringBuilder.setLength (0);
+
+ // reset state information
+ fRoot = null;
+ 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 ("<!--");
+ if (text.length > 0) {
+ fInternalSubset.append (text.ch, text.offset, text.length);
+ }
+ 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.INSTANCE;
+ }
+ 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);
+ if (data.length > 0) {
+ fInternalSubset.append (' ').append (data.ch, data.offset, data.length);
+ }
+ 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.INSTANCE;
+ }
+ 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 {
+
+ fLocator = locator;
+ 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) {
+ ++fRejectedElementDepth;
+ return;
+ }
+ Element el = createElementNode (element);
+ int attrCount = attributes.getLength ();
+ boolean seenSchemaDefault = false;
+ for (int i = 0; i < attrCount; i++) {
+ attributes.getName (i, fAttrQName);
+ Attr attr = createAttrNode (fAttrQName);
+
+ String attrValue = attributes.getValue (i);
+
+ AttributePSVI attrPSVI =(AttributePSVI) attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
+ if (fStorePSVI && attrPSVI != null){
+ ((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
+ }
+
+ attr.setValue (attrValue);
+ boolean specified = attributes.isSpecified(i);
+ // Take special care of schema defaulted attributes. Calling the
+ // non-namespace aware setAttributeNode() method could overwrite
+ // another attribute with the same local name.
+ if (!specified && (seenSchemaDefault || (fAttrQName.uri != null &&
+ fAttrQName.uri != NamespaceContext.XMLNS_URI && fAttrQName.prefix == null))) {
+ el.setAttributeNodeNS(attr);
+ seenSchemaDefault = true;
+ }
+ else {
+ 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;
+ Object type = null;
+ boolean id = false;
+
+ // REVISIT: currently it is possible that someone turns off
+ // namespaces and turns on xml schema validation
+ // To avoid classcast exception in AttrImpl check for namespaces
+ // however the correct solution should probably disallow setting
+ // namespaces to false when schema processing is turned on.
+ if (attrPSVI != null && fNamespaceAware) {
+ // XML Schema
+ type = attrPSVI.getMemberTypeDefinition ();
+ if (type == null) {
+ type = attrPSVI.getTypeDefinition ();
+ if (type != null) {
+ id = ((XSSimpleType) type).isIDType ();
+ attrImpl.setType (type);
+ }
+ }
+ else {
+ id = ((XSSimpleType) type).isIDType ();
+ attrImpl.setType (type);
+ }
+ }
+ else {
+ // DTD
+ boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
+ // For DOM Level 3 TypeInfo, the type name must
+ // be null if this attribute has not been declared
+ // in the DTD.
+ if (isDeclared) {
+ type = attributes.getType (i);
+ id = "ID".equals (type);
+ }
+ attrImpl.setType (type);
+ }
+
+ if (id) {
+ ((ElementImpl) el).setIdAttributeNode (attr, true);
+ }
+
+ attrImpl.setSpecified (specified);
+ // REVISIT: Handle entities in attribute value.
+ }
+ }
+ setCharacterData (false);
+
+ if (augs != null) {
+ ElementPSVI elementPSVI = (ElementPSVI)augs.getItem (Constants.ELEMENT_PSVI);
+ if (elementPSVI != null && fNamespaceAware) {
+ XSTypeDefinition type = elementPSVI.getMemberTypeDefinition ();
+ if (type == null) {
+ type = elementPSVI.getTypeDefinition ();
+ }
+ ((ElementNSImpl)el).setType (type);
+ }
+ }
+
+
+ // filter nodes
+ if (fDOMFilter != null && !fInEntityRef) {
+ if (fRoot == null) {
+ // fill value of the root element
+ fRoot = el;
+ } else {
+ short code = fDOMFilter.startElement(el);
+ switch (code) {
+ case LSParserFilter.FILTER_INTERRUPT :
+ {
+ throw Abort.INSTANCE;
+ }
+ case LSParserFilter.FILTER_REJECT :
+ {
+ fFilterReject = true;
+ fRejectedElementDepth = 0;
+ 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 lose it).
+ fFirstChunk = true;
+ fSkippedElemStack.push(Boolean.TRUE);
+ return;
+ }
+ default :
+ {
+ if (!fSkippedElemStack.isEmpty()) {
+ fSkippedElemStack.push(Boolean.FALSE);
+ }
+ }
+ }
+ }
+ }
+ fCurrentNode.appendChild (el);
+ fCurrentNode = el;
+ }
+ else {
+ int el = fDeferredDocumentImpl.createDeferredElement (fNamespaceAware ?
+ element.uri : null, element.rawname);
+ Object type = null;
+ int attrCount = attributes.getLength ();
+ // Need to loop in reverse order so that the attributes
+ // are processed in document order when the DOM is expanded.
+ for (int i = attrCount - 1; i >= 0; --i) {
+
+ // set type information
+ AttributePSVI attrPSVI = (AttributePSVI)attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
+ boolean id = false;
+
+ // REVISIT: currently it is possible that someone turns off
+ // namespaces and turns on xml schema validation
+ // To avoid classcast exception in AttrImpl check for namespaces
+ // however the correct solution should probably disallow setting
+ // namespaces to false when schema processing is turned on.
+ if (attrPSVI != null && fNamespaceAware) {
+ // XML Schema
+ type = attrPSVI.getMemberTypeDefinition ();
+ if (type == null) {
+ type = attrPSVI.getTypeDefinition ();
+ if (type != null){
+ id = ((XSSimpleType) type).isIDType ();
+ }
+ }
+ else {
+ id = ((XSSimpleType) type).isIDType ();
+ }
+ }
+ else {
+ // DTD
+ boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
+ // For DOM Level 3 TypeInfo, the type name must
+ // be null if this attribute has not been declared
+ // in the DTD.
+ if (isDeclared) {
+ type = attributes.getType (i);
+ id = "ID".equals (type);
+ }
+ }
+
+ // create attribute
+ fDeferredDocumentImpl.setDeferredAttribute (
+ el,
+ attributes.getQName (i),
+ attributes.getURI (i),
+ attributes.getValue (i),
+ attributes.isSpecified (i),
+ id,
+ type);
+ }
+
+ fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
+ fCurrentNodeIndex = el;
+ }
+ } // startElement(QName,XMLAttributes)
+
+
+ /**
+ * 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;
+ }
+
+ 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) {
+ fStringBuilder.append (((TextImpl)child).removeData ());
+ } else {
+ fStringBuilder.append (((Text)child).getData ());
+ ((Text)child).setNodeValue (null);
+ }
+ fFirstChunk = false;
+ }
+ if (text.length > 0) {
+ fStringBuilder.append (text.ch, text.offset, text.length);
+ }
+ }
+ else {
+ fFirstChunk = true;
+ Text textNode = fDocument.createTextNode (text.toString());
+ 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 (augs != null && fDocumentImpl != null && (fNamespaceAware || fStorePSVI)) {
+ ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
+ if (elementPSVI != null) {
+ // Updating TypeInfo. If the declared type is a union the
+ // [member type definition] will only be available at the
+ // end of an element.
+ if (fNamespaceAware) {
+ XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
+ if (type == null) {
+ type = elementPSVI.getTypeDefinition();
+ }
+ ((ElementNSImpl)fCurrentNode).setType(type);
+ }
+ if (fStorePSVI) {
+ ((PSVIElementNSImpl)fCurrentNode).setPSVI (elementPSVI);
+ }
+ }
+ }
+
+ if (fDOMFilter != null) {
+ if (fFilterReject) {
+ if (fRejectedElementDepth-- == 0) {
+ fFilterReject = false;
+ }
+ return;
+ }
+ if (!fSkippedElemStack.isEmpty()) {
+ if (fSkippedElemStack.pop() == Boolean.TRUE) {
+ return;
+ }
+ }
+ setCharacterData (false);
+ if ((fCurrentNode != fRoot) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
+ short code = fDOMFilter.acceptNode (fCurrentNode);
+ switch (code) {
+ case LSParserFilter.FILTER_INTERRUPT:{
+ throw Abort.INSTANCE;
+ }
+ 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 lose it).
+ fFirstChunk = true;
+
+ // replace children
+ Node parent = fCurrentNode.getParentNode ();
+ NodeList ls = fCurrentNode.getChildNodes ();
+ int length = ls.getLength ();
+
+ for (int i=0;i<length;i++) {
+ parent.appendChild (ls.item (0));
+ }
+ parent.removeChild (fCurrentNode);
+ fCurrentNode = parent;
+
+ return;
+ }
+
+ default: { }
+ }
+ }
+ fCurrentNode = fCurrentNode.getParentNode ();
+
+ } // end-if DOMFilter
+ else {
+ setCharacterData (false);
+ fCurrentNode = fCurrentNode.getParentNode ();
+ }
+
+ }
+ else {
+ if (augs != null) {
+ ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
+ if (elementPSVI != null) {
+ // Setting TypeInfo. If the declared type is a union the
+ // [member type definition] will only be available at the
+ // end of an element.
+ XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
+ if (type == null) {
+ type = elementPSVI.getTypeDefinition();
+ }
+ fDeferredDocumentImpl.setTypeInfo(fCurrentNodeIndex, type);
+ }
+ }
+ fCurrentNodeIndex =
+ fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
+ }
+
+
+ } // endElement(QName)
+
+
+ /**
+ * The start of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startCDATA (Augmentations augs) throws XNIException {
+
+ fInCDATASection = true;
+ if (!fDeferNodeExpansion) {
+ if (fFilterReject) {
+ return;
+ }
+ if (fCreateCDATANodes) {
+ setCharacterData (false);
+ }
+ }
+ } // startCDATA()
+
+ /**
+ * The end of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endCDATA (Augmentations augs) throws XNIException {
+
+ fInCDATASection = false;
+ if (!fDeferNodeExpansion) {
+
+ if (fFilterReject) {
+ return;
+ }
+
+ if (fCurrentCDATASection !=null) {
+
+ if (fDOMFilter !=null && !fInEntityRef &&
+ (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_CDATA_SECTION)!= 0) {
+ short code = fDOMFilter.acceptNode (fCurrentCDATASection);
+ switch (code) {
+ case LSParserFilter.FILTER_INTERRUPT:{
+ throw Abort.INSTANCE;
+ }
+ case LSParserFilter.FILTER_REJECT:{
+ // fall through to SKIP since CDATA section has no children.
+ }
+ case LSParserFilter.FILTER_SKIP: {
+ Node parent = fCurrentNode.getParentNode ();
+ parent.removeChild (fCurrentCDATASection);
+ fCurrentNode = parent;
+ return;
+ }
+
+ default: {
+ // accept node
+ }
+ }
+ }
+
+ fCurrentNode = fCurrentNode.getParentNode ();
+ fCurrentCDATASection = null;
+ }
+ }
+ else {
+ if (fCurrentCDATASectionIndex !=-1) {
+ fCurrentNodeIndex =
+ fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
+ fCurrentCDATASectionIndex = -1;
+ }
+ }
+
+ } // endCDATA()
+
+ /**
+ * The end of the document.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endDocument (Augmentations augs) throws XNIException {
+
+ if (!fDeferNodeExpansion) {
+ // REVISIT: when DOM Level 3 is REC rely on Document.support
+ // instead of specific class
+ // set the actual encoding and set DOM error checking back on
+ if (fDocumentImpl != null) {
+ if (fLocator != null) {
+ if (fLocator.getEncoding() != null)
+ fDocumentImpl.setInputEncoding (fLocator.getEncoding());
+ }
+ fDocumentImpl.setStrictErrorChecking (true);
+ }
+ fCurrentNode = null;
+ }
+ else {
+ // set the actual encoding
+ if (fLocator != null) {
+ if (fLocator.getEncoding() != null)
+ fDeferredDocumentImpl.setInputEncoding (fLocator.getEncoding());
+ }
+ fCurrentNodeIndex = -1;
+ }
+
+ } // endDocument()
+
+ /**
+ * 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 {
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>endGeneralEntity: ("+name+")");
+ }
+ if (!fDeferNodeExpansion) {
+
+ if (fFilterReject) {
+ return;
+ }
+ setCharacterData (true);
+
+ if (fDocumentType != null) {
+ // get current entity declaration
+ NamedNodeMap entities = fDocumentType.getEntities ();
+ fCurrentEntityDecl = (EntityImpl) entities.getNamedItem (name);
+ if (fCurrentEntityDecl != null) {
+ if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild () == null) {
+ fCurrentEntityDecl.setReadOnly (false, true);
+ Node child = fCurrentNode.getFirstChild ();
+ while (child != null) {
+ Node copy = child.cloneNode (true);
+ fCurrentEntityDecl.appendChild (copy);
+ child = child.getNextSibling ();
+ }
+ fCurrentEntityDecl.setReadOnly (true, true);
+
+ //entities.setNamedItem(fCurrentEntityDecl);
+ }
+ fCurrentEntityDecl = null;
+ }
+
+ }
+ fInEntityRef = false;
+ boolean removeEntityRef = false;
+ if (fCreateEntityRefNodes) {
+ if (fDocumentImpl != null) {
+ // Make entity ref node read only
+ ((NodeImpl)fCurrentNode).setReadOnly (true, true);
+ }
+
+ if (fDOMFilter !=null &&
+ (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) {
+ short code = fDOMFilter.acceptNode (fCurrentNode);
+ switch (code) {
+ case LSParserFilter.FILTER_INTERRUPT:{
+ throw Abort.INSTANCE;
+ }
+ case LSParserFilter.FILTER_REJECT:{
+ Node parent = fCurrentNode.getParentNode ();
+ parent.removeChild (fCurrentNode);
+ fCurrentNode = parent;
+ return;
+
+ }
+ case LSParserFilter.FILTER_SKIP: {
+ // make sure we don't loose chars if next event is characters()
+ fFirstChunk = true;
+ removeEntityRef = true;
+ break;
+ }
+
+ default: {
+ fCurrentNode = fCurrentNode.getParentNode ();
+ }
+ }
+ } else {
+ fCurrentNode = fCurrentNode.getParentNode ();
+ }
+ }
+
+ if (!fCreateEntityRefNodes || removeEntityRef) {
+ // move entity reference children to the list of
+ // siblings of its parent and remove entity reference
+ NodeList children = fCurrentNode.getChildNodes ();
+ Node parent = fCurrentNode.getParentNode ();
+ int length = children.getLength ();
+ if (length > 0) {
+
+ // get previous sibling of the entity reference
+ Node node = fCurrentNode.getPreviousSibling ();
+ // normalize text nodes
+ Node child = children.item (0);
+ if (node != null && node.getNodeType () == Node.TEXT_NODE &&
+ child.getNodeType () == Node.TEXT_NODE) {
+ ((Text)node).appendData (child.getNodeValue ());
+ fCurrentNode.removeChild (child);
+
+ } else {
+ node = parent.insertBefore (child, fCurrentNode);
+ handleBaseURI (node);
+ }
+
+ for (int i=1;i <length;i++) {
+ node = parent.insertBefore (children.item (0), fCurrentNode);
+ handleBaseURI (node);
+ }
+ } // length > 0
+ parent.removeChild (fCurrentNode);
+ fCurrentNode = parent;
+ }
+ }
+ else {
+
+ 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;
+ break;
+ }
+ }
+ node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
+ }
+ }
+
+ if (fDeferredEntityDecl != -1 &&
+ fDeferredDocumentImpl.getLastChild (fDeferredEntityDecl, false) == -1) {
+ // entity definition exists and it does not have any children
+ int prevIndex = -1;
+ int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
+ while (childIndex != -1) {
+ int cloneIndex = fDeferredDocumentImpl.cloneNode (childIndex, true);
+ fDeferredDocumentImpl.insertBefore (fDeferredEntityDecl, cloneIndex, prevIndex);
+ prevIndex = cloneIndex;
+ childIndex = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
+ }
+ }
+ if (fCreateEntityRefNodes) {
+ fCurrentNodeIndex =
+ fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
+ false);
+ } else { //!fCreateEntityRefNodes
+ // move children of entity ref before the entity ref.
+ // remove entity ref.
+
+ // holds a child of entity ref
+ int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
+ int parentIndex =
+ fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
+ false);
+
+ int prevIndex = fCurrentNodeIndex;
+ int lastChild = childIndex;
+ int sibling = -1;
+ while (childIndex != -1) {
+ handleBaseURI (childIndex);
+ sibling = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
+ fDeferredDocumentImpl.insertBefore (parentIndex, childIndex, prevIndex);
+ prevIndex = childIndex;
+ childIndex = sibling;
+ }
+ if(lastChild != -1)
+ fDeferredDocumentImpl.setAsLastChild (parentIndex, lastChild);
+ else{
+ sibling = fDeferredDocumentImpl.getRealPrevSibling (prevIndex, false);
+ fDeferredDocumentImpl.setAsLastChild (parentIndex, sibling);
+ }
+ fCurrentNodeIndex = parentIndex;
+ }
+ fDeferredEntityDecl = -1;
+ }
+
+
+ } // endGeneralEntity(String, Augmentations)
+
+
+ /**
+ * Record baseURI information for the Element (by adding xml:base attribute)
+ * or for the ProcessingInstruction (by setting a baseURI field)
+ * Non deferred DOM.
+ *
+ * @param node
+ */
+ protected final void handleBaseURI (Node node){
+ if (fDocumentImpl != null) {
+ // REVISIT: remove dependency on our implementation when
+ // DOM L3 becomes REC
+
+ String baseURI = null;
+ short nodeType = node.getNodeType ();
+
+ if (nodeType == Node.ELEMENT_NODE) {
+ // if an element already has xml:base attribute
+ // do nothing
+ if (fNamespaceAware) {
+ if (((Element)node).getAttributeNodeNS ("http://www.w3.org/XML/1998/namespace","base")!=null) {
+ return;
+ }
+ } else if (((Element)node).getAttributeNode ("xml:base") != null) {
+ return;
+ }
+ // retrive the baseURI from the entity reference
+ baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
+ if (baseURI !=null && !baseURI.equals (fDocumentImpl.getDocumentURI ())) {
+ if (fNamespaceAware) {
+ ((Element)node).setAttributeNS ("http://www.w3.org/XML/1998/namespace", "xml:base", baseURI);
+ } else {
+ ((Element)node).setAttribute ("xml:base", baseURI);
+ }
+ }
+ }
+ else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+
+ baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
+ if (baseURI !=null && fErrorHandler != null) {
+ DOMErrorImpl error = new DOMErrorImpl ();
+ error.fType = "pi-base-uri-not-preserved";
+ error.fRelatedData = baseURI;
+ error.fSeverity = DOMError.SEVERITY_WARNING;
+ fErrorHandler.getErrorHandler ().handleError (error);
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * Record baseURI information for the Element (by adding xml:base attribute)
+ * or for the ProcessingInstruction (by setting a baseURI field)
+ * Deferred DOM.
+ *
+ * @param node
+ */
+ protected final void handleBaseURI (int node){
+ short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
+
+ if (nodeType == Node.ELEMENT_NODE) {
+ String baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
+ if (baseURI == null) {
+ baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
+ }
+ if (baseURI !=null && !baseURI.equals (fDeferredDocumentImpl.getDocumentURI ())) {
+ fDeferredDocumentImpl.setDeferredAttribute (node,
+ "xml:base",
+ "http://www.w3.org/XML/1998/namespace",
+ baseURI,
+ true);
+ }
+ }
+ else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+
+
+ // retrieve baseURI from the entity reference
+ String baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
+
+ if (baseURI == null) {
+ // try baseURI of the entity declaration
+ baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
+ }
+
+ if (baseURI != null && fErrorHandler != null) {
+ DOMErrorImpl error = new DOMErrorImpl ();
+ error.fType = "pi-base-uri-not-preserved";
+ error.fRelatedData = baseURI;
+ error.fSeverity = DOMError.SEVERITY_WARNING;
+ fErrorHandler.getErrorHandler ().handleError (error);
+ }
+ }
+ }
+
+
+ //
+ // XMLDTDHandler methods
+ //
+
+ /**
+ * The start of the DTD.
+ *
+ * @param locator The document locator, or null if the document
+ * location cannot be reported during the parsing of
+ * the document DTD. However, it is <em>strongly</em>
+ * recommended that a locator be supplied that can
+ * at least report the base system identifier of the
+ * DTD.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startDTD (XMLLocator locator, Augmentations augs) throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>startDTD");
+ if (DEBUG_BASEURI) {
+ System.out.println (" expandedSystemId: "+locator.getExpandedSystemId ());
+ System.out.println (" baseURI:"+ locator.getBaseSystemId ());
+ }
+ }
+
+ fInDTD = true;
+ if (locator != null) {
+ fBaseURIStack.push (locator.getBaseSystemId ());
+ }
+ if (fDeferNodeExpansion || fDocumentImpl != null) {
+ fInternalSubset = new StringBuilder (1024);
+ }
+ } // startDTD(XMLLocator)
+
+
+ /**
+ * The end of the DTD.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endDTD (Augmentations augs) throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>endDTD()");
+ }
+ fInDTD = false;
+ if (!fBaseURIStack.isEmpty ()) {
+ fBaseURIStack.pop ();
+ }
+ String internalSubset = fInternalSubset != null && fInternalSubset.length () > 0
+ ? fInternalSubset.toString () : null;
+ if (fDeferNodeExpansion) {
+ if (internalSubset != null) {
+ fDeferredDocumentImpl.setInternalSubset (fDocumentTypeIndex, internalSubset);
+ }
+ }
+ else if (fDocumentImpl != null) {
+ if (internalSubset != null) {
+ ((DocumentTypeImpl)fDocumentType).setInternalSubset (internalSubset);
+ }
+ }
+ } // endDTD()
+
+ /**
+ * The start of a conditional section.
+ *
+ * @param type The type of the conditional section. This value will
+ * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #CONDITIONAL_INCLUDE
+ * @see #CONDITIONAL_IGNORE
+ */
+ public void startConditional (short type, Augmentations augs) throws XNIException {
+ } // startConditional(short)
+
+ /**
+ * The end of a conditional section.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endConditional (Augmentations augs) throws XNIException {
+ } // endConditional()
+
+
+ /**
+ * The start of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startExternalSubset (XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>startExternalSubset");
+ if (DEBUG_BASEURI) {
+ System.out.println (" expandedSystemId: "+identifier.getExpandedSystemId ());
+ System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
+ }
+ }
+ fBaseURIStack.push (identifier.getBaseSystemId ());
+ fInDTDExternalSubset = true;
+ } // startExternalSubset(Augmentations)
+
+ /**
+ * The end of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endExternalSubset (Augmentations augs) throws XNIException {
+ fInDTDExternalSubset = false;
+ fBaseURIStack.pop ();
+ } // endExternalSubset(Augmentations)
+
+ /**
+ * An internal entity declaration.
+ *
+ * @param name The name of the entity. Parameter entity names start with
+ * '%', whereas the name of a general entity is just the
+ * entity name.
+ * @param text The value of the entity.
+ * @param nonNormalizedText The non-normalized value of the entity. This
+ * value contains the same sequence of characters that was in
+ * the internal entity declaration, without any entity
+ * references expanded.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void internalEntityDecl (String name, XMLString text,
+ XMLString nonNormalizedText,
+ Augmentations augs) throws XNIException {
+
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>internalEntityDecl: "+name);
+ if (DEBUG_BASEURI) {
+ System.out.println (" baseURI:"+ (String)fBaseURIStack.peek ());
+ }
+ }
+ // internal subset string
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!ENTITY ");
+ if (name.startsWith ("%")) {
+ fInternalSubset.append ("% ");
+ fInternalSubset.append (name.substring (1));
+ }
+ else {
+ fInternalSubset.append (name);
+ }
+ fInternalSubset.append (' ');
+ String value = nonNormalizedText.toString ();
+ boolean singleQuote = value.indexOf ('\'') == -1;
+ fInternalSubset.append (singleQuote ? '\'' : '"');
+ fInternalSubset.append (value);
+ fInternalSubset.append (singleQuote ? '\'' : '"');
+ fInternalSubset.append (">\n");
+ }
+
+ // NOTE: We only know how to create these nodes for the Xerces
+ // DOM implementation because DOM Level 2 does not specify
+ // that functionality. -Ac
+
+ // create full node
+ // don't add parameter entities!
+ if(name.startsWith ("%"))
+ return;
+ if (fDocumentType != null) {
+ NamedNodeMap entities = fDocumentType.getEntities ();
+ EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
+ if (entity == null) {
+ entity = (EntityImpl)fDocumentImpl.createEntity (name);
+ entity.setBaseURI ((String)fBaseURIStack.peek ());
+ entities.setNamedItem (entity);
+ }
+ }
+
+ // create deferred node
+ if (fDocumentTypeIndex != -1) {
+ boolean found = false;
+ 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)) {
+ found = true;
+ break;
+ }
+ }
+ node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
+ }
+ if (!found) {
+ int entityIndex =
+ fDeferredDocumentImpl.createDeferredEntity (name, null, null, null, (String)fBaseURIStack.peek ());
+ fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
+ }
+ }
+
+ } // internalEntityDecl(String,XMLString,XMLString)
+
+ /**
+ * An external entity declaration.
+ *
+ * @param name The name of the entity. Parameter entity names start
+ * with '%', whereas the name of a general entity is just
+ * the entity name.
+ * @param identifier An object containing all location information
+ * pertinent to this notation.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void externalEntityDecl (String name, XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+
+
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>externalEntityDecl: "+name);
+ if (DEBUG_BASEURI) {
+ System.out.println (" expandedSystemId:"+ identifier.getExpandedSystemId ());
+ System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
+ }
+ }
+ // internal subset string
+ String publicId = identifier.getPublicId ();
+ String literalSystemId = identifier.getLiteralSystemId ();
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!ENTITY ");
+ if (name.startsWith ("%")) {
+ fInternalSubset.append ("% ");
+ fInternalSubset.append (name.substring (1));
+ }
+ else {
+ fInternalSubset.append (name);
+ }
+ fInternalSubset.append (' ');
+ if (publicId != null) {
+ fInternalSubset.append ("PUBLIC '");
+ fInternalSubset.append (publicId);
+ fInternalSubset.append ("' '");
+ }
+ else {
+ fInternalSubset.append ("SYSTEM '");
+ }
+ fInternalSubset.append (literalSystemId);
+ fInternalSubset.append ("'>\n");
+ }
+
+ // NOTE: We only know how to create these nodes for the Xerces
+ // DOM implementation because DOM Level 2 does not specify
+ // that functionality. -Ac
+
+ // create full node
+ // don't add parameter entities!
+ if(name.startsWith ("%"))
+ return;
+ if (fDocumentType != null) {
+ NamedNodeMap entities = fDocumentType.getEntities ();
+ EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
+ if (entity == null) {
+ entity = (EntityImpl)fDocumentImpl.createEntity (name);
+ entity.setPublicId (publicId);
+ entity.setSystemId (literalSystemId);
+ entity.setBaseURI (identifier.getBaseSystemId ());
+ entities.setNamedItem (entity);
+ }
+ }
+
+ // create deferred node
+ if (fDocumentTypeIndex != -1) {
+ boolean found = false;
+ int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
+ while (nodeIndex != -1) {
+ short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
+ if (nodeType == Node.ENTITY_NODE) {
+ String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
+ if (nodeName.equals (name)) {
+ found = true;
+ break;
+ }
+ }
+ nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
+ }
+ if (!found) {
+ int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
+ name, publicId, literalSystemId, null, identifier.getBaseSystemId ());
+ fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
+ }
+ }
+
+ } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
+
+
+ /**
+ * This method notifies of the start of a parameter entity. The parameter
+ * entity name start with a '%' character.
+ *
+ * @param name The name of the parameter 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 parameter entities).
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startParameterEntity (String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augs) throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>startParameterEntity: "+name);
+ if (DEBUG_BASEURI) {
+ System.out.println (" expandedSystemId: "+identifier.getExpandedSystemId ());
+ System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
+ }
+ }
+ if (augs != null && fInternalSubset != null &&
+ !fInDTDExternalSubset &&
+ Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
+ fInternalSubset.append(name).append(";\n");
+ }
+ fBaseURIStack.push (identifier.getExpandedSystemId ());
+ }
+
+
+ /**
+ * This method notifies the end of a parameter entity. Parameter entity
+ * names begin with a '%' character.
+ *
+ * @param name The name of the parameter entity.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endParameterEntity (String name, Augmentations augs) throws XNIException {
+
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>endParameterEntity: "+name);
+ }
+ fBaseURIStack.pop ();
+ }
+
+ /**
+ * An unparsed entity declaration.
+ *
+ * @param name The name of the entity.
+ * @param identifier An object containing all location information
+ * pertinent to this entity.
+ * @param notation The name of the notation.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void unparsedEntityDecl (String name, XMLResourceIdentifier identifier,
+ String notation, Augmentations augs)
+ throws XNIException {
+
+ if (DEBUG_EVENTS) {
+ System.out.println ("==>unparsedEntityDecl: "+name);
+ if (DEBUG_BASEURI) {
+ System.out.println (" expandedSystemId:"+ identifier.getExpandedSystemId ());
+ System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
+ }
+ }
+ // internal subset string
+ String publicId = identifier.getPublicId ();
+ String literalSystemId = identifier.getLiteralSystemId ();
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!ENTITY ");
+ fInternalSubset.append (name);
+ fInternalSubset.append (' ');
+ if (publicId != null) {
+ fInternalSubset.append ("PUBLIC '");
+ fInternalSubset.append (publicId);
+ if (literalSystemId != null) {
+ fInternalSubset.append ("' '");
+ fInternalSubset.append (literalSystemId);
+ }
+ }
+ else {
+ fInternalSubset.append ("SYSTEM '");
+ fInternalSubset.append (literalSystemId);
+ }
+ fInternalSubset.append ("' NDATA ");
+ fInternalSubset.append (notation);
+ fInternalSubset.append (">\n");
+ }
+
+ // NOTE: We only know how to create these nodes for the Xerces
+ // DOM implementation because DOM Level 2 does not specify
+ // that functionality. -Ac
+
+ // create full node
+ if (fDocumentType != null) {
+ NamedNodeMap entities = fDocumentType.getEntities ();
+ EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
+ if (entity == null) {
+ entity = (EntityImpl)fDocumentImpl.createEntity (name);
+ entity.setPublicId (publicId);
+ entity.setSystemId (literalSystemId);
+ entity.setNotationName (notation);
+ entity.setBaseURI (identifier.getBaseSystemId ());
+ entities.setNamedItem (entity);
+ }
+ }
+
+ // create deferred node
+ if (fDocumentTypeIndex != -1) {
+ boolean found = false;
+ int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
+ while (nodeIndex != -1) {
+ short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
+ if (nodeType == Node.ENTITY_NODE) {
+ String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
+ if (nodeName.equals (name)) {
+ found = true;
+ break;
+ }
+ }
+ nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
+ }
+ if (!found) {
+ int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
+ name, publicId, literalSystemId, notation, identifier.getBaseSystemId ());
+ fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
+ }
+ }
+
+ } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
+
+ /**
+ * A notation declaration
+ *
+ * @param name The name of the notation.
+ * @param identifier An object containing all location information
+ * pertinent to this notation.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void notationDecl (String name, XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+
+ // internal subset string
+ String publicId = identifier.getPublicId ();
+ String literalSystemId = identifier.getLiteralSystemId ();
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!NOTATION ");
+ fInternalSubset.append (name);
+ if (publicId != null) {
+ fInternalSubset.append (" PUBLIC '");
+ fInternalSubset.append (publicId);
+ if (literalSystemId != null) {
+ fInternalSubset.append ("' '");
+ fInternalSubset.append (literalSystemId);
+ }
+ }
+ else {
+ fInternalSubset.append (" SYSTEM '");
+ fInternalSubset.append (literalSystemId);
+ }
+ fInternalSubset.append ("'>\n");
+ }
+
+ // NOTE: We only know how to create these nodes for the Xerces
+ // DOM implementation because DOM Level 2 does not specify
+ // that functionality. -Ac
+
+ // create full node
+ if (fDocumentImpl !=null && fDocumentType != null) {
+ NamedNodeMap notations = fDocumentType.getNotations ();
+ if (notations.getNamedItem (name) == null) {
+ NotationImpl notation = (NotationImpl)fDocumentImpl.createNotation (name);
+ notation.setPublicId (publicId);
+ notation.setSystemId (literalSystemId);
+ notation.setBaseURI (identifier.getBaseSystemId ());
+ notations.setNamedItem (notation);
+ }
+ }
+
+ // create deferred node
+ if (fDocumentTypeIndex != -1) {
+ boolean found = false;
+ int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
+ while (nodeIndex != -1) {
+ short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
+ if (nodeType == Node.NOTATION_NODE) {
+ String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
+ if (nodeName.equals (name)) {
+ found = true;
+ break;
+ }
+ }
+ nodeIndex = fDeferredDocumentImpl.getPrevSibling (nodeIndex, false);
+ }
+ if (!found) {
+ int notationIndex = fDeferredDocumentImpl.createDeferredNotation (
+ name, publicId, literalSystemId, identifier.getBaseSystemId ());
+ fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, notationIndex);
+ }
+ }
+
+ } // notationDecl(String,XMLResourceIdentifier, Augmentations)
+
+ /**
+ * Characters within an IGNORE conditional section.
+ *
+ * @param text The ignored text.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void ignoredCharacters (XMLString text, Augmentations augs) throws XNIException {
+ } // ignoredCharacters(XMLString, Augmentations)
+
+
+ /**
+ * An element declaration.
+ *
+ * @param name The name of the element.
+ * @param contentModel The element content model.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void elementDecl (String name, String contentModel, Augmentations augs)
+ throws XNIException {
+
+ // internal subset string
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!ELEMENT ");
+ fInternalSubset.append (name);
+ fInternalSubset.append (' ');
+ fInternalSubset.append (contentModel);
+ fInternalSubset.append (">\n");
+ }
+
+ } // elementDecl(String,String)
+
+ /**
+ * An attribute declaration.
+ *
+ * @param elementName The name of the element that this attribute
+ * is associated with.
+ * @param attributeName The name of the attribute.
+ * @param type The attribute type. This value will be one of
+ * the following: "CDATA", "ENTITY", "ENTITIES",
+ * "ENUMERATION", "ID", "IDREF", "IDREFS",
+ * "NMTOKEN", "NMTOKENS", or "NOTATION".
+ * @param enumeration If the type has the value "ENUMERATION" or
+ * "NOTATION", this array holds the allowed attribute
+ * values; otherwise, this array is null.
+ * @param defaultType The attribute default type. This value will be
+ * one of the following: "#FIXED", "#IMPLIED",
+ * "#REQUIRED", or null.
+ * @param defaultValue The attribute default value, or null if no
+ * default value is specified.
+ * @param nonNormalizedDefaultValue The attribute default value with no normalization
+ * performed, or null if no default value is specified.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void attributeDecl (String elementName, String attributeName,
+ String type, String[] enumeration,
+ String defaultType, XMLString defaultValue,
+ XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
+
+ // internal subset string
+ if (fInternalSubset != null && !fInDTDExternalSubset) {
+ fInternalSubset.append ("<!ATTLIST ");
+ fInternalSubset.append (elementName);
+ fInternalSubset.append (' ');
+ fInternalSubset.append (attributeName);
+ fInternalSubset.append (' ');
+ if (type.equals ("ENUMERATION")) {
+ fInternalSubset.append ('(');
+ for (int i = 0; i < enumeration.length; i++) {
+ if (i > 0) {
+ fInternalSubset.append ('|');
+ }
+ fInternalSubset.append (enumeration[i]);
+ }
+ fInternalSubset.append (')');
+ }
+ else {
+ fInternalSubset.append (type);
+ }
+ if (defaultType != null) {
+ fInternalSubset.append (' ');
+ fInternalSubset.append (defaultType);
+ }
+ if (defaultValue != null) {
+ fInternalSubset.append (" '");
+ for (int i = 0; i < defaultValue.length; i++) {
+ char c = defaultValue.ch[defaultValue.offset + i];
+ if (c == '\'') {
+ fInternalSubset.append ("&apos;");
+ }
+ else {
+ fInternalSubset.append (c);
+ }
+ }
+ fInternalSubset.append ('\'');
+ }
+ fInternalSubset.append (">\n");
+ }
+ // REVISIT: This code applies to the support of domx/grammar-access
+ // feature in Xerces 1
+
+ // deferred expansion
+ if (fDeferredDocumentImpl != null) {
+
+ // get the default value
+ if (defaultValue != null) {
+
+ // get element definition
+ int elementDefIndex = fDeferredDocumentImpl.lookupElementDefinition (elementName);
+
+ // create element definition if not already there
+ if (elementDefIndex == -1) {
+ elementDefIndex = fDeferredDocumentImpl.createDeferredElementDefinition (elementName);
+ fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, elementDefIndex);
+ }
+ // add default attribute
+ boolean nsEnabled = fNamespaceAware;
+ String namespaceURI = null;
+ if (nsEnabled) {
+ // DOM Level 2 wants all namespace declaration attributes
+ // to be bound to "http://www.w3.org/2000/xmlns/"
+ // So as long as the XML parser doesn't do it, it needs to
+ // done here.
+ if (attributeName.startsWith("xmlns:") ||
+ attributeName.equals("xmlns")) {
+ namespaceURI = NamespaceContext.XMLNS_URI;
+ }
+ else if (attributeName.startsWith("xml:")) {
+ namespaceURI = NamespaceContext.XML_URI;
+ }
+ }
+ int attrIndex = fDeferredDocumentImpl.createDeferredAttribute (
+ attributeName, namespaceURI, defaultValue.toString(), false);
+ if ("ID".equals (type)) {
+ fDeferredDocumentImpl.setIdAttribute (attrIndex);
+ }
+ // REVISIT: set ID type correctly
+ fDeferredDocumentImpl.appendChild (elementDefIndex, attrIndex);
+ }
+
+ } // if deferred
+
+ // full expansion
+ else if (fDocumentImpl != null) {
+
+ // get the default value
+ if (defaultValue != null) {
+
+ // get element definition node
+ NamedNodeMap elements = ((DocumentTypeImpl)fDocumentType).getElements ();
+ ElementDefinitionImpl elementDef = (ElementDefinitionImpl)elements.getNamedItem (elementName);
+ if (elementDef == null) {
+ elementDef = fDocumentImpl.createElementDefinition (elementName);
+ ((DocumentTypeImpl)fDocumentType).getElements ().setNamedItem (elementDef);
+ }
+
+ // REVISIT: Check for uniqueness of element name? -Ac
+
+ // create attribute and set properties
+ boolean nsEnabled = fNamespaceAware;
+ AttrImpl attr;
+ if (nsEnabled) {
+ String namespaceURI = null;
+ // DOM Level 2 wants all namespace declaration attributes
+ // to be bound to "http://www.w3.org/2000/xmlns/"
+ // So as long as the XML parser doesn't do it, it needs to
+ // done here.
+ if (attributeName.startsWith("xmlns:") ||
+ attributeName.equals("xmlns")) {
+ namespaceURI = NamespaceContext.XMLNS_URI;
+ }
+ else if (attributeName.startsWith("xml:")) {
+ namespaceURI = NamespaceContext.XML_URI;
+ }
+ attr = (AttrImpl)fDocumentImpl.createAttributeNS (namespaceURI,
+ attributeName);
+ }
+ else {
+ attr = (AttrImpl)fDocumentImpl.createAttribute (attributeName);
+ }
+ attr.setValue (defaultValue.toString ());
+ attr.setSpecified (false);
+ attr.setIdAttribute ("ID".equals (type));
+
+ // add default attribute to element definition
+ if (nsEnabled){
+ elementDef.getAttributes ().setNamedItemNS (attr);
+ }
+ else {
+ elementDef.getAttributes ().setNamedItem (attr);
+ }
+ }
+
+ } // if NOT defer-node-expansion
+
+ } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
+
+
+ /**
+ * The start of an attribute list.
+ *
+ * @param elementName The name of the element that this attribute
+ * list is associated with.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startAttlist (String elementName, Augmentations augs) throws XNIException {
+ } // startAttlist(String)
+
+
+ /**
+ * The end of an attribute list.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endAttlist (Augmentations augs) throws XNIException {
+ } // endAttlist()
+
+
+ // method to create an element node.
+ // subclasses can override this method to create element nodes in other ways.
+ protected Element createElementNode (QName element) {
+ Element el = null;
+
+ if (fNamespaceAware) {
+ // if we are using xerces DOM implementation, call our
+ // own constructor to reuse the strings we have here.
+ if (fDocumentImpl != null) {
+ el = fDocumentImpl.createElementNS (element.uri, element.rawname,
+ element.localpart);
+ }
+ else {
+ el = fDocument.createElementNS (element.uri, element.rawname);
+ }
+ }
+ else {
+ el = fDocument.createElement (element.rawname);
+ }
+
+ return el;
+ }
+
+ // method to create an attribute node.
+ // subclasses can override this method to create attribute nodes in other ways.
+ protected Attr createAttrNode (QName attrQName) {
+ Attr attr = null;
+
+ if (fNamespaceAware) {
+ if (fDocumentImpl != null) {
+ // if we are using xerces DOM implementation, call our
+ // own constructor to reuse the strings we have here.
+ attr = fDocumentImpl.createAttributeNS (attrQName.uri,
+ attrQName.rawname,
+ attrQName.localpart);
+ }
+ else {
+ attr = fDocument.createAttributeNS (attrQName.uri,
+ attrQName.rawname);
+ }
+ }
+ else {
+ attr = fDocument.createAttribute (attrQName.rawname);
+ }
+
+ return attr;
+ }
+
+ /*
+ * When the first characters() call is received, the data is stored in
+ * a new Text node. If right after the first characters() we receive another chunk of data,
+ * the data from the Text node, following the new characters are appended
+ * to the fStringBuffer and the text node data is set to empty.
+ *
+ * This function is called when the state is changed and the
+ * data must be appended to the current node.
+ *
+ * Note: if DOMFilter is set, you must make sure that if Node is skipped,
+ * or removed fFistChunk must be set to true, otherwise some data can be lost.
+ *
+ */
+ protected void setCharacterData (boolean sawChars){
+
+ // handle character data
+ fFirstChunk = sawChars;
+
+
+ // if we have data in the buffer we must have created
+ // a text node already.
+
+ Node child = fCurrentNode.getLastChild ();
+ if (child != null) {
+ if (fStringBuilder.length () > 0) {
+ // REVISIT: should this check be performed?
+ if (child.getNodeType () == Node.TEXT_NODE) {
+ if (fDocumentImpl != null) {
+ ((TextImpl)child).replaceData (fStringBuilder.toString ());
+ }
+ else {
+ ((Text)child).setData (fStringBuilder.toString ());
+ }
+ }
+ // reset string buffer
+ fStringBuilder.setLength (0);
+ }
+
+ if (fDOMFilter !=null && !fInEntityRef) {
+ if ( (child.getNodeType () == Node.TEXT_NODE ) &&
+ ((fDOMFilter.getWhatToShow () & NodeFilter.SHOW_TEXT)!= 0) ) {
+ short code = fDOMFilter.acceptNode (child);
+ switch (code) {
+ case LSParserFilter.FILTER_INTERRUPT:{
+ throw Abort.INSTANCE;
+ }
+ case LSParserFilter.FILTER_REJECT:{
+ // fall through to SKIP since Comment has no children.
+ }
+ case LSParserFilter.FILTER_SKIP: {
+ fCurrentNode.removeChild (child);
+ return;
+ }
+ default: {
+ // accept node -- do nothing
+ }
+ }
+ }
+ } // end-if fDOMFilter !=null
+
+ } // end-if child !=null
+ }
+
+
+ /**
+ * @see org.w3c.dom.ls.LSParser#abort()
+ */
+ public void abort () {
+ throw Abort.INSTANCE;
+ }
+
+
+} // class AbstractDOMParser