1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xerces.internal.parsers;
  23 
  24 import java.util.Locale;
  25 import java.util.Stack;
  26 
  27 import com.sun.org.apache.xerces.internal.dom.AttrImpl;
  28 import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
  29 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
  30 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  31 import com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl;
  32 import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
  33 import com.sun.org.apache.xerces.internal.dom.DocumentTypeImpl;
  34 import com.sun.org.apache.xerces.internal.dom.ElementDefinitionImpl;
  35 import com.sun.org.apache.xerces.internal.dom.ElementImpl;
  36 import com.sun.org.apache.xerces.internal.dom.ElementNSImpl;
  37 import com.sun.org.apache.xerces.internal.dom.EntityImpl;
  38 import com.sun.org.apache.xerces.internal.dom.EntityReferenceImpl;
  39 import com.sun.org.apache.xerces.internal.dom.NodeImpl;
  40 import com.sun.org.apache.xerces.internal.dom.NotationImpl;
  41 import com.sun.org.apache.xerces.internal.dom.PSVIAttrNSImpl;
  42 import com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl;
  43 import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl;
  44 import com.sun.org.apache.xerces.internal.dom.TextImpl;
  45 import com.sun.org.apache.xerces.internal.impl.Constants;
  46 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  47 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
  48 import com.sun.org.apache.xerces.internal.xni.Augmentations;
  49 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  50 import com.sun.org.apache.xerces.internal.xni.QName;
  51 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  52 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  53 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  54 import com.sun.org.apache.xerces.internal.xni.XMLString;
  55 import com.sun.org.apache.xerces.internal.xni.XNIException;
  56 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  57 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  58 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  59 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  60 import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
  61 import org.w3c.dom.Attr;
  62 import org.w3c.dom.CDATASection;
  63 import org.w3c.dom.Comment;
  64 import org.w3c.dom.DOMError;
  65 import org.w3c.dom.Document;
  66 import org.w3c.dom.DocumentType;
  67 import org.w3c.dom.Element;
  68 import org.w3c.dom.EntityReference;
  69 import org.w3c.dom.NamedNodeMap;
  70 import org.w3c.dom.Node;
  71 import org.w3c.dom.NodeList;
  72 import org.w3c.dom.ProcessingInstruction;
  73 import org.w3c.dom.Text;
  74 import org.w3c.dom.ls.LSParserFilter;
  75 import org.w3c.dom.traversal.NodeFilter;
  76 import org.xml.sax.SAXException;
  77 
  78 /**
  79  * This is the base class of all DOM parsers. It implements the XNI
  80  * callback methods to create the DOM tree. After a successful parse of
  81  * an XML document, the DOM Document object can be queried using the
  82  * <code>getDocument</code> method. The actual pipeline is defined in
  83  * parser configuration.
  84  *
  85  * @author Arnaud Le Hors, IBM
  86  * @author Andy Clark, IBM
  87  * @author Elena Litani, IBM
  88  *
  89  * @version $Id: AbstractDOMParser.java,v 1.10 2010-11-01 04:40:09 joehw Exp $
  90  */
  91 public class AbstractDOMParser extends AbstractXMLDocumentParser {
  92 
  93     //
  94     // Constants
  95     //
  96 
  97     // feature ids
  98 
  99     /** Feature id: namespace. */
 100     protected static final String NAMESPACES =
 101     Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
 102 
 103     /** Feature id: create entity ref nodes. */
 104     protected static final String CREATE_ENTITY_REF_NODES =
 105     Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
 106 
 107     /** Feature id: include comments. */
 108     protected static final String INCLUDE_COMMENTS_FEATURE =
 109     Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
 110 
 111     /** Feature id: create cdata nodes. */
 112     protected static final String CREATE_CDATA_NODES_FEATURE =
 113     Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
 114 
 115     /** Feature id: include ignorable whitespace. */
 116     protected static final String INCLUDE_IGNORABLE_WHITESPACE =
 117     Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
 118 
 119     /** Feature id: defer node expansion. */
 120     protected static final String DEFER_NODE_EXPANSION =
 121     Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
 122 
 123 
 124     /** Recognized features. */
 125     private static final String[] RECOGNIZED_FEATURES = {
 126         NAMESPACES,
 127         CREATE_ENTITY_REF_NODES,
 128         INCLUDE_COMMENTS_FEATURE,
 129         CREATE_CDATA_NODES_FEATURE,
 130         INCLUDE_IGNORABLE_WHITESPACE,
 131         DEFER_NODE_EXPANSION
 132     };
 133 
 134     // property ids
 135 
 136     /** Property id: document class name. */
 137     protected static final String DOCUMENT_CLASS_NAME =
 138     Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
 139 
 140     protected static final String  CURRENT_ELEMENT_NODE=
 141     Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
 142 
 143     // protected static final String GRAMMAR_POOL =
 144     // Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 145 
 146     /** Recognized properties. */
 147     private static final String[] RECOGNIZED_PROPERTIES = {
 148         DOCUMENT_CLASS_NAME,
 149         CURRENT_ELEMENT_NODE,
 150     };
 151 
 152     // other
 153 
 154     /** Default document class name. */
 155     protected static final String DEFAULT_DOCUMENT_CLASS_NAME =
 156     "com.sun.org.apache.xerces.internal.dom.DocumentImpl";
 157 
 158     protected static final String CORE_DOCUMENT_CLASS_NAME =
 159     "com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl";
 160 
 161     protected static final String PSVI_DOCUMENT_CLASS_NAME =
 162     "com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl";
 163 
 164     /**
 165      * If the user stops the process, this exception will be thrown.
 166      */
 167     static final class Abort extends RuntimeException {
 168         private static final long serialVersionUID = 1687848994976808490L;
 169         static final Abort INSTANCE = new Abort();
 170         private Abort() {}
 171         public Throwable fillInStackTrace() {
 172             return this;
 173         }
 174     }
 175 
 176     // debugging
 177 
 178     private static final boolean DEBUG_EVENTS = false;
 179     private static final boolean DEBUG_BASEURI = false;
 180 
 181     //
 182     // Data
 183     //
 184 
 185     /** DOM L3 error handler */
 186     protected DOMErrorHandlerWrapper fErrorHandler = null;
 187 
 188     /** True if inside DTD. */
 189     protected boolean fInDTD;
 190 
 191     // features
 192 
 193     /** Create entity reference nodes. */
 194     protected boolean fCreateEntityRefNodes;
 195 
 196     /** Include ignorable whitespace. */
 197     protected boolean fIncludeIgnorableWhitespace;
 198 
 199     /** Include Comments. */
 200     protected boolean fIncludeComments;
 201 
 202     /** Create cdata nodes. */
 203     protected boolean fCreateCDATANodes;
 204 
 205     // dom information
 206 
 207     /** The document. */
 208     protected Document fDocument;
 209 
 210     /** The default Xerces document implementation, if used. */
 211     protected CoreDocumentImpl fDocumentImpl;
 212 
 213     /** Whether to store PSVI information in DOM tree. */
 214     protected boolean fStorePSVI;
 215 
 216     /** The document class name to use. */
 217     protected String  fDocumentClassName;
 218 
 219     /** The document type node. */
 220     protected DocumentType fDocumentType;
 221 
 222     /** Current node. */
 223     protected Node fCurrentNode;
 224     protected CDATASection fCurrentCDATASection;
 225     protected EntityImpl fCurrentEntityDecl;
 226     protected int fDeferredEntityDecl;
 227 
 228     /** Character buffer */
 229     protected final StringBuilder fStringBuilder = new StringBuilder (50);
 230 
 231     // internal subset
 232 
 233     /** Internal subset buffer. */
 234     protected StringBuilder fInternalSubset;
 235 
 236     // deferred expansion data
 237 
 238     protected boolean              fDeferNodeExpansion;
 239     protected boolean              fNamespaceAware;
 240     protected DeferredDocumentImpl fDeferredDocumentImpl;
 241     protected int                  fDocumentIndex;
 242     protected int                  fDocumentTypeIndex;
 243     protected int                  fCurrentNodeIndex;
 244     protected int                  fCurrentCDATASectionIndex;
 245 
 246     // state
 247 
 248     /** True if inside DTD external subset. */
 249     protected boolean fInDTDExternalSubset;
 250 
 251     /** Root element node. */
 252     protected Node fRoot;
 253 
 254     /** True if inside CDATA section. */
 255     protected boolean fInCDATASection;
 256 
 257     /** True if saw the first chunk of characters*/
 258     protected boolean fFirstChunk = false;
 259 
 260 
 261     /** LSParserFilter: specifies that element with given QNAME and all its children
 262      * must be rejected */
 263     protected boolean fFilterReject = false;
 264 
 265     // data
 266 
 267     /** Base uri stack*/
 268     protected final Stack fBaseURIStack = new Stack ();
 269 
 270     /** LSParserFilter: tracks the element depth within a rejected subtree. */
 271     protected int fRejectedElementDepth = 0;
 272 
 273     /** LSParserFilter: store depth of skipped elements */
 274     protected Stack fSkippedElemStack = null;
 275 
 276     /** LSParserFilter: true if inside entity reference */
 277     protected boolean fInEntityRef = false;
 278 
 279     /** Attribute QName. */
 280     private final QName fAttrQName = new QName();
 281 
 282     /** Document locator. */
 283     private XMLLocator fLocator;
 284 
 285     // handlers
 286 
 287     protected LSParserFilter fDOMFilter = null;
 288 
 289     //
 290     // Constructors
 291     //
 292 
 293     /** Default constructor. */
 294     protected AbstractDOMParser (XMLParserConfiguration config) {
 295 
 296         super (config);
 297 
 298 
 299         // add recognized features
 300         fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);
 301 
 302         // set default values
 303         fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, true);
 304         fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, true);
 305         fConfiguration.setFeature (DEFER_NODE_EXPANSION, true);
 306         fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, true);
 307         fConfiguration.setFeature (CREATE_CDATA_NODES_FEATURE, true);
 308 
 309         // add recognized properties
 310         fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);
 311 
 312         // set default values
 313         fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
 314         DEFAULT_DOCUMENT_CLASS_NAME);
 315 
 316     } // <init>(XMLParserConfiguration)
 317 
 318     /**
 319      * This method retrieves the name of current document class.
 320      */
 321     protected String getDocumentClassName () {
 322         return fDocumentClassName;
 323     }
 324 
 325     /**
 326      * This method allows the programmer to decide which document
 327      * factory to use when constructing the DOM tree. However, doing
 328      * so will lose the functionality of the default factory. Also,
 329      * a document class other than the default will lose the ability
 330      * to defer node expansion on the DOM tree produced.
 331      *
 332      * @param documentClassName The fully qualified class name of the
 333      *                      document factory to use when constructing
 334      *                      the DOM tree.
 335      *
 336      * @see #getDocumentClassName
 337      * @see #DEFAULT_DOCUMENT_CLASS_NAME
 338      */
 339     protected void setDocumentClassName (String documentClassName) {
 340 
 341         // normalize class name
 342         if (documentClassName == null) {
 343             documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
 344         }
 345 
 346         if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME) &&
 347             !documentClassName.equals(PSVI_DOCUMENT_CLASS_NAME)) {
 348             // verify that this class exists and is of the right type
 349             try {
 350                 Class _class = ObjectFactory.findProviderClass (documentClassName, true);
 351                 //if (!_class.isAssignableFrom(Document.class)) {
 352                 if (!Document.class.isAssignableFrom (_class)) {
 353                     throw new IllegalArgumentException (
 354                         DOMMessageFormatter.formatMessage(
 355                         DOMMessageFormatter.DOM_DOMAIN,
 356                         "InvalidDocumentClassName", new Object [] {documentClassName}));
 357                 }
 358             }
 359             catch (ClassNotFoundException e) {
 360                 throw new IllegalArgumentException (
 361                     DOMMessageFormatter.formatMessage(
 362                     DOMMessageFormatter.DOM_DOMAIN,
 363                     "MissingDocumentClassName", new Object [] {documentClassName}));
 364             }
 365         }
 366 
 367         // set document class name
 368         fDocumentClassName = documentClassName;
 369         if (!documentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
 370             fDeferNodeExpansion = false;
 371         }
 372 
 373     } // setDocumentClassName(String)
 374 
 375     //
 376     // Public methods
 377     //
 378 
 379     /** Returns the DOM document object. */
 380     public Document getDocument () {
 381         return fDocument;
 382     } // getDocument():Document
 383 
 384     /**
 385      * Drops all references to the last DOM which was built by this parser.
 386      */
 387     public final void dropDocumentReferences() {
 388         fDocument = null;
 389         fDocumentImpl = null;
 390         fDeferredDocumentImpl = null;
 391         fDocumentType = null;
 392         fCurrentNode = null;
 393         fCurrentCDATASection = null;
 394         fCurrentEntityDecl = null;
 395         fRoot = null;
 396     } // dropDocumentReferences()
 397 
 398     //
 399     // XMLDocumentParser methods
 400     //
 401 
 402     /**
 403      * Resets the parser state.
 404      *
 405      * @throws SAXException Thrown on initialization error.
 406      */
 407     public void reset () throws XNIException {
 408         super.reset ();
 409 
 410 
 411         // get feature state
 412         fCreateEntityRefNodes =
 413         fConfiguration.getFeature (CREATE_ENTITY_REF_NODES);
 414 
 415         fIncludeIgnorableWhitespace =
 416         fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE);
 417 
 418         fDeferNodeExpansion =
 419         fConfiguration.getFeature (DEFER_NODE_EXPANSION);
 420 
 421         fNamespaceAware = fConfiguration.getFeature (NAMESPACES);
 422 
 423         fIncludeComments = fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE);
 424 
 425         fCreateCDATANodes = fConfiguration.getFeature (CREATE_CDATA_NODES_FEATURE);
 426 
 427         // get property
 428         setDocumentClassName ((String)
 429         fConfiguration.getProperty (DOCUMENT_CLASS_NAME));
 430 
 431         // reset dom information
 432         fDocument = null;
 433         fDocumentImpl = null;
 434         fStorePSVI = false;
 435         fDocumentType = null;
 436         fDocumentTypeIndex = -1;
 437         fDeferredDocumentImpl = null;
 438         fCurrentNode = null;
 439 
 440         // reset string buffer
 441         fStringBuilder.setLength (0);
 442 
 443         // reset state information
 444         fRoot = null;
 445         fInDTD = false;
 446         fInDTDExternalSubset = false;
 447         fInCDATASection = false;
 448         fFirstChunk = false;
 449         fCurrentCDATASection = null;
 450         fCurrentCDATASectionIndex = -1;
 451 
 452         fBaseURIStack.removeAllElements ();
 453 
 454 
 455     } // reset()
 456 
 457     /**
 458      * Set the locale to use for messages.
 459      *
 460      * @param locale The locale object to use for localization of messages.
 461      *
 462      */
 463     public void setLocale (Locale locale) {
 464         fConfiguration.setLocale (locale);
 465 
 466     } // setLocale(Locale)
 467 
 468     //
 469     // XMLDocumentHandler methods
 470     //
 471 
 472     /**
 473      * This method notifies the start of a general entity.
 474      * <p>
 475      * <strong>Note:</strong> This method is not called for entity references
 476      * appearing as part of attribute values.
 477      *
 478      * @param name     The name of the general entity.
 479      * @param identifier The resource identifier.
 480      * @param encoding The auto-detected IANA encoding name of the entity
 481      *                 stream. This value will be null in those situations
 482      *                 where the entity encoding is not auto-detected (e.g.
 483      *                 internal entities or a document entity that is
 484      *                 parsed from a java.io.Reader).
 485      * @param augs     Additional information that may include infoset augmentations
 486      *
 487      * @exception XNIException Thrown by handler to signal an error.
 488      */
 489     public void startGeneralEntity (String name,
 490     XMLResourceIdentifier identifier,
 491     String encoding, Augmentations augs)
 492     throws XNIException {
 493         if (DEBUG_EVENTS) {
 494             System.out.println ("==>startGeneralEntity ("+name+")");
 495             if (DEBUG_BASEURI) {
 496                 System.out.println ("   expandedSystemId( **baseURI): "+identifier.getExpandedSystemId ());
 497                 System.out.println ("   baseURI:"+ identifier.getBaseSystemId ());
 498             }
 499         }
 500 
 501         // Always create entity reference nodes to be able to recreate
 502         // entity as a part of doctype
 503         if (!fDeferNodeExpansion) {
 504             if (fFilterReject) {
 505                 return;
 506             }
 507             setCharacterData (true);
 508             EntityReference er = fDocument.createEntityReference (name);
 509             if (fDocumentImpl != null) {
 510                 // REVISIT: baseURI/actualEncoding
 511                 //         remove dependency on our implementation when DOM L3 is REC
 512                 //
 513 
 514                 EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
 515 
 516                 // set base uri
 517                 erImpl.setBaseURI (identifier.getExpandedSystemId ());
 518                 if (fDocumentType != null) {
 519                     // set actual encoding
 520                     NamedNodeMap entities = fDocumentType.getEntities ();
 521                     fCurrentEntityDecl = (EntityImpl) entities.getNamedItem (name);
 522                     if (fCurrentEntityDecl != null) {
 523                         fCurrentEntityDecl.setInputEncoding (encoding);
 524                     }
 525 
 526                 }
 527                 // we don't need synchronization now, because entity ref will be
 528                 // expanded anyway. Synch only needed when user creates entityRef node
 529                 erImpl.needsSyncChildren (false);
 530             }
 531             fInEntityRef = true;
 532             fCurrentNode.appendChild (er);
 533             fCurrentNode = er;
 534         }
 535         else {
 536 
 537             int er =
 538             fDeferredDocumentImpl.createDeferredEntityReference (name, identifier.getExpandedSystemId ());
 539             if (fDocumentTypeIndex != -1) {
 540                 // find corresponding Entity decl
 541                 int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
 542                 while (node != -1) {
 543                     short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
 544                     if (nodeType == Node.ENTITY_NODE) {
 545                         String nodeName =
 546                         fDeferredDocumentImpl.getNodeName (node, false);
 547                         if (nodeName.equals (name)) {
 548                             fDeferredEntityDecl = node;
 549                             fDeferredDocumentImpl.setInputEncoding (node, encoding);
 550                             break;
 551                         }
 552                     }
 553                     node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
 554                 }
 555             }
 556             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, er);
 557             fCurrentNodeIndex = er;
 558         }
 559 
 560     } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
 561 
 562     /**
 563      * Notifies of the presence of a TextDecl line in an entity. If present,
 564      * this method will be called immediately following the startEntity call.
 565      * <p>
 566      * <strong>Note:</strong> This method will never be called for the
 567      * document entity; it is only called for external general entities
 568      * referenced in document content.
 569      * <p>
 570      * <strong>Note:</strong> This method is not called for entity references
 571      * appearing as part of attribute values.
 572      *
 573      * @param version  The XML version, or null if not specified.
 574      * @param encoding The IANA encoding name of the entity.
 575      * @param augs       Additional information that may include infoset augmentations
 576      *
 577      * @throws XNIException Thrown by handler to signal an error.
 578      */
 579     public void textDecl (String version, String encoding, Augmentations augs) throws XNIException {
 580         if (fInDTD){
 581             return;
 582         }
 583         if (!fDeferNodeExpansion) {
 584             if (fCurrentEntityDecl != null && !fFilterReject) {
 585                 fCurrentEntityDecl.setXmlEncoding (encoding);
 586                 if (version != null)
 587                     fCurrentEntityDecl.setXmlVersion (version);
 588             }
 589         }
 590         else {
 591             if (fDeferredEntityDecl !=-1) {
 592                 fDeferredDocumentImpl.setEntityInfo (fDeferredEntityDecl, version, encoding);
 593             }
 594         }
 595     } // textDecl(String,String)
 596 
 597     /**
 598      * A comment.
 599      *
 600      * @param text The text in the comment.
 601      * @param augs       Additional information that may include infoset augmentations
 602      *
 603      * @throws XNIException Thrown by application to signal an error.
 604      */
 605     public void comment (XMLString text, Augmentations augs) throws XNIException {
 606         if (fInDTD) {
 607             if (fInternalSubset != null && !fInDTDExternalSubset) {
 608                 fInternalSubset.append ("<!--");
 609                 if (text.length > 0) {
 610                     fInternalSubset.append (text.ch, text.offset, text.length);
 611                 }
 612                 fInternalSubset.append ("-->");
 613             }
 614             return;
 615         }
 616         if (!fIncludeComments || fFilterReject) {
 617             return;
 618         }
 619         if (!fDeferNodeExpansion) {
 620             Comment comment = fDocument.createComment (text.toString ());
 621 
 622             setCharacterData (false);
 623             fCurrentNode.appendChild (comment);
 624             if (fDOMFilter !=null && !fInEntityRef &&
 625             (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_COMMENT)!= 0) {
 626                 short code = fDOMFilter.acceptNode (comment);
 627                 switch (code) {
 628                     case LSParserFilter.FILTER_INTERRUPT:{
 629                         throw Abort.INSTANCE;
 630                     }
 631                     case LSParserFilter.FILTER_REJECT:{
 632                         // REVISIT: the constant FILTER_REJECT should be changed when new
 633                         // DOM LS specs gets published
 634 
 635                         // fall through to SKIP since comment has no children.
 636                     }
 637                     case LSParserFilter.FILTER_SKIP: {
 638                         // REVISIT: the constant FILTER_SKIP should be changed when new
 639                         // DOM LS specs gets published
 640                         fCurrentNode.removeChild (comment);
 641                         // make sure we don't loose chars if next event is characters()
 642                         fFirstChunk = true;
 643                         return;
 644                     }
 645 
 646                     default: {
 647                         // accept node
 648                     }
 649                 }
 650             }
 651 
 652         }
 653         else {
 654             int comment =
 655             fDeferredDocumentImpl.createDeferredComment (text.toString ());
 656             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, comment);
 657         }
 658 
 659     } // comment(XMLString)
 660 
 661     /**
 662      * A processing instruction. Processing instructions consist of a
 663      * target name and, optionally, text data. The data is only meaningful
 664      * to the application.
 665      * <p>
 666      * Typically, a processing instruction's data will contain a series
 667      * of pseudo-attributes. These pseudo-attributes follow the form of
 668      * element attributes but are <strong>not</strong> parsed or presented
 669      * to the application as anything other than text. The application is
 670      * responsible for parsing the data.
 671      *
 672      * @param target The target.
 673      * @param data   The data or null if none specified.
 674      * @param augs       Additional information that may include infoset augmentations
 675      *
 676      * @throws XNIException Thrown by handler to signal an error.
 677      */
 678     public void processingInstruction (String target, XMLString data, Augmentations augs)
 679     throws XNIException {
 680 
 681         if (fInDTD) {
 682             if (fInternalSubset != null && !fInDTDExternalSubset) {
 683                 fInternalSubset.append ("<?");
 684                 fInternalSubset.append (target);
 685                 if (data.length > 0) {
 686                     fInternalSubset.append (' ').append (data.ch, data.offset, data.length);
 687                 }
 688                 fInternalSubset.append ("?>");
 689             }
 690             return;
 691         }
 692 
 693         if (DEBUG_EVENTS) {
 694             System.out.println ("==>processingInstruction ("+target+")");
 695         }
 696         if (!fDeferNodeExpansion) {
 697             if (fFilterReject) {
 698                 return;
 699             }
 700             ProcessingInstruction pi =
 701             fDocument.createProcessingInstruction (target, data.toString ());
 702 
 703 
 704             setCharacterData (false);
 705             fCurrentNode.appendChild (pi);
 706             if (fDOMFilter !=null && !fInEntityRef &&
 707             (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
 708                 short code = fDOMFilter.acceptNode (pi);
 709                 switch (code) {
 710                     case LSParserFilter.FILTER_INTERRUPT:{
 711                         throw Abort.INSTANCE;
 712                     }
 713                     case LSParserFilter.FILTER_REJECT:{
 714                         // fall through to SKIP since PI has no children.
 715                     }
 716                     case LSParserFilter.FILTER_SKIP: {
 717                         fCurrentNode.removeChild (pi);
 718                         // fFirstChunk must be set to true so that data
 719                         // won't be lost in the case where the child before PI is
 720                         // a text node and the next event is characters.
 721                         fFirstChunk = true;
 722                         return;
 723                     }
 724                     default: {
 725                     }
 726                 }
 727             }
 728         }
 729         else {
 730             int pi = fDeferredDocumentImpl.
 731             createDeferredProcessingInstruction (target, data.toString ());
 732             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, pi);
 733         }
 734 
 735     } // processingInstruction(String,XMLString)
 736 
 737     /**
 738      * The start of the document.
 739      *
 740      * @param locator The system identifier of the entity if the entity
 741      *                 is external, null otherwise.
 742      * @param encoding The auto-detected IANA encoding name of the entity
 743      *                 stream. This value will be null in those situations
 744      *                 where the entity encoding is not auto-detected (e.g.
 745      *                 internal entities or a document entity that is
 746      *                 parsed from a java.io.Reader).
 747      * @param namespaceContext
 748      *                 The namespace context in effect at the
 749      *                 start of this document.
 750      *                 This object represents the current context.
 751      *                 Implementors of this class are responsible
 752      *                 for copying the namespace bindings from the
 753      *                 the current context (and its parent contexts)
 754      *                 if that information is important.
 755      * @param augs     Additional information that may include infoset augmentations
 756      *
 757      * @throws XNIException Thrown by handler to signal an error.
 758      */
 759     public void startDocument (XMLLocator locator, String encoding,
 760     NamespaceContext namespaceContext, Augmentations augs)
 761     throws XNIException {
 762 
 763         fLocator = locator;
 764         if (!fDeferNodeExpansion) {
 765             if (fDocumentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
 766                 fDocument = new DocumentImpl ();
 767                 fDocumentImpl = (CoreDocumentImpl)fDocument;
 768                 // REVISIT: when DOM Level 3 is REC rely on Document.support
 769                 //          instead of specific class
 770                 // set DOM error checking off
 771                 fDocumentImpl.setStrictErrorChecking (false);
 772                 // set actual encoding
 773                 fDocumentImpl.setInputEncoding (encoding);
 774                 // set documentURI
 775                 fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
 776             }
 777             else if (fDocumentClassName.equals (PSVI_DOCUMENT_CLASS_NAME)) {
 778                 fDocument = new PSVIDocumentImpl();
 779                 fDocumentImpl = (CoreDocumentImpl)fDocument;
 780                 fStorePSVI = true;
 781                 // REVISIT: when DOM Level 3 is REC rely on Document.support
 782                 //          instead of specific class
 783                 // set DOM error checking off
 784                 fDocumentImpl.setStrictErrorChecking (false);
 785                 // set actual encoding
 786                 fDocumentImpl.setInputEncoding (encoding);
 787                 // set documentURI
 788                 fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
 789             }
 790             else {
 791                 // use specified document class
 792                 try {
 793                     Class documentClass = ObjectFactory.findProviderClass (fDocumentClassName, true);
 794                     fDocument = (Document)documentClass.newInstance ();
 795 
 796                     // if subclass of our own class that's cool too
 797                     Class defaultDocClass =
 798                     ObjectFactory.findProviderClass (CORE_DOCUMENT_CLASS_NAME, true);
 799                     if (defaultDocClass.isAssignableFrom (documentClass)) {
 800                         fDocumentImpl = (CoreDocumentImpl)fDocument;
 801 
 802                         Class psviDocClass = ObjectFactory.findProviderClass (PSVI_DOCUMENT_CLASS_NAME, true);
 803                         if (psviDocClass.isAssignableFrom (documentClass)) {
 804                             fStorePSVI = true;
 805                         }
 806 
 807                         // REVISIT: when DOM Level 3 is REC rely on
 808                         //          Document.support instead of specific class
 809                         // set DOM error checking off
 810                         fDocumentImpl.setStrictErrorChecking (false);
 811                         // set actual encoding
 812                         fDocumentImpl.setInputEncoding (encoding);
 813                         // set documentURI
 814                         if (locator != null) {
 815                             fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
 816                         }
 817                     }
 818                 }
 819                 catch (ClassNotFoundException e) {
 820                     // won't happen we already checked that earlier
 821                 }
 822                 catch (Exception e) {
 823                     throw new RuntimeException (
 824                         DOMMessageFormatter.formatMessage(
 825                         DOMMessageFormatter.DOM_DOMAIN,
 826                         "CannotCreateDocumentClass",
 827                         new Object [] {fDocumentClassName}));
 828                 }
 829             }
 830             fCurrentNode = fDocument;
 831         }
 832         else {
 833             fDeferredDocumentImpl = new DeferredDocumentImpl (fNamespaceAware);
 834             fDocument = fDeferredDocumentImpl;
 835             fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument ();
 836             // REVISIT: strict error checking is not implemented in deferred dom.
 837             //          Document.support instead of specific class
 838 
 839             // set actual encoding
 840             fDeferredDocumentImpl.setInputEncoding (encoding);
 841             // set documentURI
 842             fDeferredDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
 843             fCurrentNodeIndex = fDocumentIndex;
 844 
 845         }
 846 
 847     } // startDocument(String,String)
 848 
 849     /**
 850      * Notifies of the presence of an XMLDecl line in the document. If
 851      * present, this method will be called immediately following the
 852      * startDocument call.
 853      *
 854      * @param version    The XML version.
 855      * @param encoding   The IANA encoding name of the document, or null if
 856      *                   not specified.
 857      * @param standalone The standalone value, or null if not specified.
 858      * @param augs       Additional information that may include infoset augmentations
 859      *
 860      * @throws XNIException Thrown by handler to signal an error.
 861      */
 862     public void xmlDecl (String version, String encoding, String standalone,
 863     Augmentations augs)
 864     throws XNIException {
 865         if (!fDeferNodeExpansion) {
 866             // REVISIT: when DOM Level 3 is REC rely on Document.support
 867             //          instead of specific class
 868             if (fDocumentImpl != null) {
 869                 if (version != null)
 870                     fDocumentImpl.setXmlVersion (version);
 871                 fDocumentImpl.setXmlEncoding (encoding);
 872                 fDocumentImpl.setXmlStandalone ("yes".equals (standalone));
 873             }
 874         }
 875         else {
 876             if (version != null)
 877                 fDeferredDocumentImpl.setXmlVersion (version);
 878             fDeferredDocumentImpl.setXmlEncoding (encoding);
 879             fDeferredDocumentImpl.setXmlStandalone ("yes".equals (standalone));
 880         }
 881     } // xmlDecl(String,String,String)
 882 
 883     /**
 884      * Notifies of the presence of the DOCTYPE line in the document.
 885      *
 886      * @param rootElement The name of the root element.
 887      * @param publicId    The public identifier if an external DTD or null
 888      *                    if the external DTD is specified using SYSTEM.
 889      * @param systemId    The system identifier if an external DTD, null
 890      *                    otherwise.
 891      * @param augs     Additional information that may include infoset augmentations
 892      *
 893      * @throws XNIException Thrown by handler to signal an error.
 894      */
 895     public void doctypeDecl (String rootElement,
 896     String publicId, String systemId, Augmentations augs)
 897     throws XNIException {
 898 
 899         if (!fDeferNodeExpansion) {
 900             if (fDocumentImpl != null) {
 901                 fDocumentType = fDocumentImpl.createDocumentType (
 902                 rootElement, publicId, systemId);
 903                 fCurrentNode.appendChild (fDocumentType);
 904             }
 905         }
 906         else {
 907             fDocumentTypeIndex = fDeferredDocumentImpl.
 908             createDeferredDocumentType (rootElement, publicId, systemId);
 909             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, fDocumentTypeIndex);
 910         }
 911 
 912     } // doctypeDecl(String,String,String)
 913 
 914     /**
 915      * The start of an element. If the document specifies the start element
 916      * by using an empty tag, then the startElement method will immediately
 917      * be followed by the endElement method, with no intervening methods.
 918      *
 919      * @param element    The name of the element.
 920      * @param attributes The element attributes.
 921      * @param augs     Additional information that may include infoset augmentations
 922      *
 923      * @throws XNIException Thrown by handler to signal an error.
 924      */
 925     public void startElement (QName element, XMLAttributes attributes, Augmentations augs)
 926     throws XNIException {
 927         if (DEBUG_EVENTS) {
 928             System.out.println ("==>startElement ("+element.rawname+")");
 929         }
 930         if (!fDeferNodeExpansion) {
 931             if (fFilterReject) {
 932                 ++fRejectedElementDepth;
 933                 return;
 934             }
 935             Element el = createElementNode (element);
 936             int attrCount = attributes.getLength ();
 937             boolean seenSchemaDefault = false;
 938             for (int i = 0; i < attrCount; i++) {
 939                 attributes.getName (i, fAttrQName);
 940                 Attr attr = createAttrNode (fAttrQName);
 941 
 942                 String attrValue = attributes.getValue (i);
 943 
 944                 AttributePSVI attrPSVI =(AttributePSVI) attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
 945                 if (fStorePSVI && attrPSVI != null){
 946                     ((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
 947                 }
 948 
 949                 attr.setValue (attrValue);
 950                 boolean specified = attributes.isSpecified(i);
 951                 // Take special care of schema defaulted attributes. Calling the
 952                 // non-namespace aware setAttributeNode() method could overwrite
 953                 // another attribute with the same local name.
 954                 if (!specified && (seenSchemaDefault || (fAttrQName.uri != null &&
 955                     fAttrQName.uri != NamespaceContext.XMLNS_URI && fAttrQName.prefix == null))) {
 956                     el.setAttributeNodeNS(attr);
 957                     seenSchemaDefault = true;
 958                 }
 959                 else {
 960                     el.setAttributeNode(attr);
 961                 }
 962                 // NOTE: The specified value MUST be set after you set
 963                 //       the node value because that turns the "specified"
 964                 //       flag to "true" which may overwrite a "false"
 965                 //       value from the attribute list. -Ac
 966                 if (fDocumentImpl != null) {
 967                     AttrImpl attrImpl = (AttrImpl) attr;
 968                     Object type = null;
 969                     boolean id = false;
 970 
 971                     // REVISIT: currently it is possible that someone turns off
 972                     // namespaces and turns on xml schema validation
 973                     // To avoid classcast exception in AttrImpl check for namespaces
 974                     // however the correct solution should probably disallow setting
 975                     // namespaces to false when schema processing is turned on.
 976                     if (attrPSVI != null && fNamespaceAware) {
 977                         // XML Schema
 978                         type = attrPSVI.getMemberTypeDefinition ();
 979                         if (type == null) {
 980                             type = attrPSVI.getTypeDefinition ();
 981                             if (type != null) {
 982                                 id = ((XSSimpleType) type).isIDType ();
 983                                 attrImpl.setType (type);
 984                             }
 985                         }
 986                         else {
 987                             id = ((XSSimpleType) type).isIDType ();
 988                             attrImpl.setType (type);
 989                         }
 990                     }
 991                     else {
 992                         // DTD
 993                         boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
 994                         // For DOM Level 3 TypeInfo, the type name must
 995                         // be null if this attribute has not been declared
 996                         // in the DTD.
 997                         if (isDeclared) {
 998                             type = attributes.getType (i);
 999                             id = "ID".equals (type);
1000                         }
1001                         attrImpl.setType (type);
1002                     }
1003 
1004                     if (id) {
1005                         ((ElementImpl) el).setIdAttributeNode (attr, true);
1006                     }
1007 
1008                     attrImpl.setSpecified (specified);
1009                     // REVISIT: Handle entities in attribute value.
1010                 }
1011             }
1012             setCharacterData (false);
1013 
1014             if (augs != null) {
1015                 ElementPSVI elementPSVI = (ElementPSVI)augs.getItem (Constants.ELEMENT_PSVI);
1016                 if (elementPSVI != null && fNamespaceAware) {
1017                     XSTypeDefinition type = elementPSVI.getMemberTypeDefinition ();
1018                     if (type == null) {
1019                         type = elementPSVI.getTypeDefinition ();
1020                     }
1021                     ((ElementNSImpl)el).setType (type);
1022                 }
1023             }
1024 
1025 
1026             // filter nodes
1027             if (fDOMFilter != null && !fInEntityRef) {
1028                 if (fRoot == null) {
1029                     // fill value of the root element
1030                     fRoot = el;
1031                 } else {
1032                     short code = fDOMFilter.startElement(el);
1033                     switch (code) {
1034                         case LSParserFilter.FILTER_INTERRUPT :
1035                             {
1036                                 throw Abort.INSTANCE;
1037                             }
1038                         case LSParserFilter.FILTER_REJECT :
1039                             {
1040                                 fFilterReject = true;
1041                                 fRejectedElementDepth = 0;
1042                                 return;
1043                             }
1044                         case LSParserFilter.FILTER_SKIP :
1045                             {
1046                                 // make sure that if any char data is available
1047                                 // the fFirstChunk is true, so that if the next event
1048                                 // is characters(), and the last node is text, we will copy
1049                                 // the value already in the text node to fStringBuffer
1050                                 // (not to lose it).
1051                                 fFirstChunk = true;
1052                                 fSkippedElemStack.push(Boolean.TRUE);
1053                                 return;
1054                             }
1055                         default :
1056                             {
1057                                 if (!fSkippedElemStack.isEmpty()) {
1058                                     fSkippedElemStack.push(Boolean.FALSE);
1059                                 }
1060                             }
1061                     }
1062                 }
1063             }
1064             fCurrentNode.appendChild (el);
1065             fCurrentNode = el;
1066         }
1067         else {
1068             int el = fDeferredDocumentImpl.createDeferredElement (fNamespaceAware ?
1069                     element.uri : null, element.rawname);
1070             Object type = null;
1071             int attrCount = attributes.getLength ();
1072             // Need to loop in reverse order so that the attributes
1073             // are processed in document order when the DOM is expanded.
1074             for (int i = attrCount - 1; i >= 0; --i) {
1075 
1076                 // set type information
1077                 AttributePSVI attrPSVI = (AttributePSVI)attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
1078                 boolean id = false;
1079 
1080                 // REVISIT: currently it is possible that someone turns off
1081                 // namespaces and turns on xml schema validation
1082                 // To avoid classcast exception in AttrImpl check for namespaces
1083                 // however the correct solution should probably disallow setting
1084                 // namespaces to false when schema processing is turned on.
1085                 if (attrPSVI != null && fNamespaceAware) {
1086                     // XML Schema
1087                     type = attrPSVI.getMemberTypeDefinition ();
1088                     if (type == null) {
1089                         type = attrPSVI.getTypeDefinition ();
1090                         if (type != null){
1091                             id = ((XSSimpleType) type).isIDType ();
1092                         }
1093                     }
1094                     else {
1095                         id = ((XSSimpleType) type).isIDType ();
1096                     }
1097                 }
1098                 else {
1099                     // DTD
1100                     boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
1101                     // For DOM Level 3 TypeInfo, the type name must
1102                     // be null if this attribute has not been declared
1103                     // in the DTD.
1104                     if (isDeclared) {
1105                         type = attributes.getType (i);
1106                         id = "ID".equals (type);
1107                     }
1108                 }
1109 
1110                 // create attribute
1111                 fDeferredDocumentImpl.setDeferredAttribute (
1112                 el,
1113                 attributes.getQName (i),
1114                 attributes.getURI (i),
1115                 attributes.getValue (i),
1116                 attributes.isSpecified (i),
1117                 id,
1118                 type);
1119             }
1120 
1121             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
1122             fCurrentNodeIndex = el;
1123         }
1124     } // startElement(QName,XMLAttributes)
1125 
1126 
1127     /**
1128      * An empty element.
1129      *
1130      * @param element    The name of the element.
1131      * @param attributes The element attributes.
1132      * @param augs   Additional information that may include infoset augmentations
1133      *
1134      * @throws XNIException Thrown by handler to signal an error.
1135      */
1136     public void emptyElement (QName element, XMLAttributes attributes, Augmentations augs)
1137     throws XNIException {
1138 
1139         startElement (element, attributes, augs);
1140         endElement (element, augs);
1141 
1142     } // emptyElement(QName,XMLAttributes)
1143 
1144     /**
1145      * Character content.
1146      *
1147      * @param text The content.
1148      * @param augs     Additional information that may include infoset augmentations
1149      *
1150      * @throws XNIException Thrown by handler to signal an error.
1151      */
1152     public void characters (XMLString text, Augmentations augs) throws XNIException {
1153 
1154         if (DEBUG_EVENTS) {
1155             System.out.println ("==>characters(): "+text.toString ());
1156         }
1157 
1158         if (!fDeferNodeExpansion) {
1159 
1160             if (fFilterReject) {
1161                 return;
1162             }
1163             if (fInCDATASection && fCreateCDATANodes) {
1164                 if (fCurrentCDATASection == null) {
1165                     fCurrentCDATASection =
1166                     fDocument.createCDATASection (text.toString ());
1167                     fCurrentNode.appendChild (fCurrentCDATASection);
1168                     fCurrentNode = fCurrentCDATASection;
1169                 }
1170                 else {
1171                     fCurrentCDATASection.appendData (text.toString ());
1172                 }
1173             }
1174             else if (!fInDTD) {
1175                 // if type is union (XML Schema) it is possible that we receive
1176                 // character call with empty data
1177                 if (text.length == 0) {
1178                     return;
1179                 }
1180 
1181                 Node child = fCurrentNode.getLastChild ();
1182                 if (child != null && child.getNodeType () == Node.TEXT_NODE) {
1183                     // collect all the data into the string buffer.
1184                     if (fFirstChunk) {
1185                         if (fDocumentImpl != null) {
1186                             fStringBuilder.append (((TextImpl)child).removeData ());
1187                         } else {
1188                             fStringBuilder.append (((Text)child).getData ());
1189                             ((Text)child).setNodeValue (null);
1190                         }
1191                         fFirstChunk = false;
1192                     }
1193                     if (text.length > 0) {
1194                         fStringBuilder.append (text.ch, text.offset, text.length);
1195                     }
1196                 }
1197                 else {
1198                     fFirstChunk = true;
1199                     Text textNode = fDocument.createTextNode (text.toString());
1200                     fCurrentNode.appendChild (textNode);
1201                 }
1202 
1203             }
1204         }
1205         else {
1206             // The Text and CDATASection normalization is taken care of within
1207             // the DOM in the deferred case.
1208             if (fInCDATASection && fCreateCDATANodes) {
1209                 if (fCurrentCDATASectionIndex == -1) {
1210                     int cs = fDeferredDocumentImpl.
1211                     createDeferredCDATASection (text.toString ());
1212 
1213                     fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, cs);
1214                     fCurrentCDATASectionIndex = cs;
1215                     fCurrentNodeIndex = cs;
1216                 }
1217                 else {
1218                     int txt = fDeferredDocumentImpl.
1219                     createDeferredTextNode (text.toString (), false);
1220                     fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1221                 }
1222             } else if (!fInDTD) {
1223                 // if type is union (XML Schema) it is possible that we receive
1224                 // character call with empty data
1225                 if (text.length == 0) {
1226                     return;
1227                 }
1228 
1229                 String value = text.toString ();
1230                 int txt = fDeferredDocumentImpl.
1231                 createDeferredTextNode (value, false);
1232                 fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1233 
1234             }
1235         }
1236     } // characters(XMLString)
1237 
1238     /**
1239      * Ignorable whitespace. For this method to be called, the document
1240      * source must have some way of determining that the text containing
1241      * only whitespace characters should be considered ignorable. For
1242      * example, the validator can determine if a length of whitespace
1243      * characters in the document are ignorable based on the element
1244      * content model.
1245      *
1246      * @param text The ignorable whitespace.
1247      * @param augs     Additional information that may include infoset augmentations
1248      *
1249      * @throws XNIException Thrown by handler to signal an error.
1250      */
1251     public void ignorableWhitespace (XMLString text, Augmentations augs) throws XNIException {
1252 
1253         if (!fIncludeIgnorableWhitespace || fFilterReject) {
1254             return;
1255         }
1256         if (!fDeferNodeExpansion) {
1257             Node child = fCurrentNode.getLastChild ();
1258             if (child != null && child.getNodeType () == Node.TEXT_NODE) {
1259                 Text textNode = (Text)child;
1260                 textNode.appendData (text.toString ());
1261             }
1262             else {
1263                 Text textNode = fDocument.createTextNode (text.toString ());
1264                 if (fDocumentImpl != null) {
1265                     TextImpl textNodeImpl = (TextImpl)textNode;
1266                     textNodeImpl.setIgnorableWhitespace (true);
1267                 }
1268                 fCurrentNode.appendChild (textNode);
1269             }
1270         }
1271         else {
1272             // The Text normalization is taken care of within the DOM in the
1273             // deferred case.
1274             int txt = fDeferredDocumentImpl.
1275             createDeferredTextNode (text.toString (), true);
1276             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1277         }
1278 
1279     } // ignorableWhitespace(XMLString)
1280 
1281     /**
1282      * The end of an element.
1283      *
1284      * @param element The name of the element.
1285      * @param augs     Additional information that may include infoset augmentations
1286      *
1287      * @throws XNIException Thrown by handler to signal an error.
1288      */
1289     public void endElement (QName element, Augmentations augs) throws XNIException {
1290         if (DEBUG_EVENTS) {
1291             System.out.println ("==>endElement ("+element.rawname+")");
1292         }
1293         if (!fDeferNodeExpansion) {
1294 
1295             // REVISIT: Should this happen after we call the filter?
1296             if (augs != null && fDocumentImpl != null && (fNamespaceAware || fStorePSVI)) {
1297                 ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
1298                 if (elementPSVI != null) {
1299                     // Updating TypeInfo. If the declared type is a union the
1300                     // [member type definition] will only be available at the
1301                     // end of an element.
1302                     if (fNamespaceAware) {
1303                         XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
1304                         if (type == null) {
1305                             type = elementPSVI.getTypeDefinition();
1306                         }
1307                         ((ElementNSImpl)fCurrentNode).setType(type);
1308                     }
1309                     if (fStorePSVI) {
1310                         ((PSVIElementNSImpl)fCurrentNode).setPSVI (elementPSVI);
1311                     }
1312                 }
1313             }
1314 
1315             if (fDOMFilter != null) {
1316                 if (fFilterReject) {
1317                     if (fRejectedElementDepth-- == 0) {
1318                         fFilterReject = false;
1319                     }
1320                     return;
1321                 }
1322                 if (!fSkippedElemStack.isEmpty()) {
1323                     if (fSkippedElemStack.pop() == Boolean.TRUE) {
1324                         return;
1325                     }
1326                 }
1327                 setCharacterData (false);
1328                 if ((fCurrentNode != fRoot) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
1329                     short code = fDOMFilter.acceptNode (fCurrentNode);
1330                     switch (code) {
1331                         case LSParserFilter.FILTER_INTERRUPT:{
1332                             throw Abort.INSTANCE;
1333                         }
1334                         case LSParserFilter.FILTER_REJECT:{
1335                             Node parent = fCurrentNode.getParentNode ();
1336                             parent.removeChild (fCurrentNode);
1337                             fCurrentNode = parent;
1338                             return;
1339                         }
1340                         case LSParserFilter.FILTER_SKIP: {
1341                             // make sure that if any char data is available
1342                             // the fFirstChunk is true, so that if the next event
1343                             // is characters(), and the last node is text, we will copy
1344                             // the value already in the text node to fStringBuffer
1345                             // (not to lose it).
1346                             fFirstChunk = true;
1347 
1348                             // replace children
1349                             Node parent = fCurrentNode.getParentNode ();
1350                             NodeList ls = fCurrentNode.getChildNodes ();
1351                             int length = ls.getLength ();
1352 
1353                             for (int i=0;i<length;i++) {
1354                                 parent.appendChild (ls.item (0));
1355                             }
1356                             parent.removeChild (fCurrentNode);
1357                             fCurrentNode = parent;
1358 
1359                             return;
1360                         }
1361 
1362                         default: { }
1363                     }
1364                 }
1365                 fCurrentNode = fCurrentNode.getParentNode ();
1366 
1367             } // end-if DOMFilter
1368             else {
1369                 setCharacterData (false);
1370                 fCurrentNode = fCurrentNode.getParentNode ();
1371             }
1372 
1373         }
1374         else {
1375             if (augs != null) {
1376                 ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
1377                 if (elementPSVI != null) {
1378                     // Setting TypeInfo. If the declared type is a union the
1379                     // [member type definition] will only be available at the
1380                     // end of an element.
1381                     XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
1382                     if (type == null) {
1383                         type = elementPSVI.getTypeDefinition();
1384                     }
1385                     fDeferredDocumentImpl.setTypeInfo(fCurrentNodeIndex, type);
1386                 }
1387             }
1388             fCurrentNodeIndex =
1389                 fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
1390         }
1391 
1392 
1393     } // endElement(QName)
1394 
1395 
1396     /**
1397      * The start of a CDATA section.
1398      * @param augs     Additional information that may include infoset augmentations
1399      *
1400      * @throws XNIException Thrown by handler to signal an error.
1401      */
1402     public void startCDATA (Augmentations augs) throws XNIException {
1403 
1404         fInCDATASection = true;
1405         if (!fDeferNodeExpansion) {
1406             if (fFilterReject) {
1407                 return;
1408             }
1409             if (fCreateCDATANodes) {
1410                 setCharacterData (false);
1411             }
1412         }
1413     } // startCDATA()
1414 
1415     /**
1416      * The end of a CDATA section.
1417      * @param augs     Additional information that may include infoset augmentations
1418      *
1419      * @throws XNIException Thrown by handler to signal an error.
1420      */
1421     public void endCDATA (Augmentations augs) throws XNIException {
1422 
1423         fInCDATASection = false;
1424         if (!fDeferNodeExpansion) {
1425 
1426             if (fFilterReject) {
1427                 return;
1428             }
1429 
1430             if (fCurrentCDATASection !=null) {
1431 
1432                 if (fDOMFilter !=null && !fInEntityRef &&
1433                 (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_CDATA_SECTION)!= 0) {
1434                     short code = fDOMFilter.acceptNode (fCurrentCDATASection);
1435                     switch (code) {
1436                         case LSParserFilter.FILTER_INTERRUPT:{
1437                             throw Abort.INSTANCE;
1438                         }
1439                         case LSParserFilter.FILTER_REJECT:{
1440                             // fall through to SKIP since CDATA section has no children.
1441                         }
1442                         case LSParserFilter.FILTER_SKIP: {
1443                             Node parent = fCurrentNode.getParentNode ();
1444                             parent.removeChild (fCurrentCDATASection);
1445                             fCurrentNode = parent;
1446                             return;
1447                         }
1448 
1449                         default: {
1450                             // accept node
1451                         }
1452                     }
1453                 }
1454 
1455                 fCurrentNode = fCurrentNode.getParentNode ();
1456                 fCurrentCDATASection = null;
1457             }
1458         }
1459         else {
1460             if (fCurrentCDATASectionIndex !=-1) {
1461                 fCurrentNodeIndex =
1462                 fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
1463                 fCurrentCDATASectionIndex = -1;
1464             }
1465         }
1466 
1467     } // endCDATA()
1468 
1469     /**
1470      * The end of the document.
1471      * @param augs     Additional information that may include infoset augmentations
1472      *
1473      * @throws XNIException Thrown by handler to signal an error.
1474      */
1475     public void endDocument (Augmentations augs) throws XNIException {
1476 
1477         if (!fDeferNodeExpansion) {
1478             // REVISIT: when DOM Level 3 is REC rely on Document.support
1479             //          instead of specific class
1480             // set the actual encoding and set DOM error checking back on
1481             if (fDocumentImpl != null) {
1482                 if (fLocator != null) {
1483                     if (fLocator.getEncoding() != null)
1484                         fDocumentImpl.setInputEncoding (fLocator.getEncoding());
1485                 }
1486                 fDocumentImpl.setStrictErrorChecking (true);
1487             }
1488             fCurrentNode = null;
1489         }
1490         else {
1491             // set the actual encoding
1492             if (fLocator != null) {
1493                 if (fLocator.getEncoding() != null)
1494                     fDeferredDocumentImpl.setInputEncoding (fLocator.getEncoding());
1495             }
1496             fCurrentNodeIndex = -1;
1497         }
1498 
1499     } // endDocument()
1500 
1501     /**
1502      * This method notifies the end of a general entity.
1503      * <p>
1504      * <strong>Note:</strong> This method is not called for entity references
1505      * appearing as part of attribute values.
1506      *
1507      * @param name   The name of the entity.
1508      * @param augs   Additional information that may include infoset augmentations
1509      *
1510      * @exception XNIException
1511      *                   Thrown by handler to signal an error.
1512      */
1513     public void endGeneralEntity (String name, Augmentations augs) throws XNIException {
1514         if (DEBUG_EVENTS) {
1515             System.out.println ("==>endGeneralEntity: ("+name+")");
1516         }
1517         if (!fDeferNodeExpansion) {
1518 
1519             if (fFilterReject) {
1520                 return;
1521             }
1522             setCharacterData (true);
1523 
1524             if (fDocumentType != null) {
1525                 // get current entity declaration
1526                 NamedNodeMap entities = fDocumentType.getEntities ();
1527                 fCurrentEntityDecl = (EntityImpl) entities.getNamedItem (name);
1528                 if (fCurrentEntityDecl != null) {
1529                     if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild () == null) {
1530                         fCurrentEntityDecl.setReadOnly (false, true);
1531                         Node child = fCurrentNode.getFirstChild ();
1532                         while (child != null) {
1533                             Node copy = child.cloneNode (true);
1534                             fCurrentEntityDecl.appendChild (copy);
1535                             child = child.getNextSibling ();
1536                         }
1537                         fCurrentEntityDecl.setReadOnly (true, true);
1538 
1539                         //entities.setNamedItem(fCurrentEntityDecl);
1540                     }
1541                     fCurrentEntityDecl = null;
1542                 }
1543 
1544             }
1545             fInEntityRef = false;
1546             boolean removeEntityRef = false;
1547             if (fCreateEntityRefNodes) {
1548                 if (fDocumentImpl != null) {
1549                     // Make entity ref node read only
1550                     ((NodeImpl)fCurrentNode).setReadOnly (true, true);
1551                 }
1552 
1553                 if (fDOMFilter !=null &&
1554                 (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) {
1555                     short code = fDOMFilter.acceptNode (fCurrentNode);
1556                     switch (code) {
1557                         case LSParserFilter.FILTER_INTERRUPT:{
1558                             throw Abort.INSTANCE;
1559                         }
1560                         case LSParserFilter.FILTER_REJECT:{
1561                             Node parent = fCurrentNode.getParentNode ();
1562                             parent.removeChild (fCurrentNode);
1563                             fCurrentNode = parent;
1564                             return;
1565 
1566                         }
1567                         case LSParserFilter.FILTER_SKIP: {
1568                             // make sure we don't loose chars if next event is characters()
1569                             fFirstChunk = true;
1570                             removeEntityRef = true;
1571                             break;
1572                         }
1573 
1574                         default: {
1575                             fCurrentNode = fCurrentNode.getParentNode ();
1576                         }
1577                     }
1578                 } else {
1579                     fCurrentNode = fCurrentNode.getParentNode ();
1580                 }
1581             }
1582 
1583             if (!fCreateEntityRefNodes || removeEntityRef) {
1584                 // move entity reference children to the list of
1585                 // siblings of its parent and remove entity reference
1586                 NodeList children = fCurrentNode.getChildNodes ();
1587                 Node parent = fCurrentNode.getParentNode ();
1588                 int length = children.getLength ();
1589                 if (length > 0) {
1590 
1591                     // get previous sibling of the entity reference
1592                     Node node = fCurrentNode.getPreviousSibling ();
1593                     // normalize text nodes
1594                     Node child = children.item (0);
1595                     if (node != null && node.getNodeType () == Node.TEXT_NODE &&
1596                     child.getNodeType () == Node.TEXT_NODE) {
1597                         ((Text)node).appendData (child.getNodeValue ());
1598                         fCurrentNode.removeChild (child);
1599 
1600                     } else {
1601                         node = parent.insertBefore (child, fCurrentNode);
1602                         handleBaseURI (node);
1603                     }
1604 
1605                     for (int i=1;i <length;i++) {
1606                         node = parent.insertBefore (children.item (0), fCurrentNode);
1607                         handleBaseURI (node);
1608                     }
1609                 } // length > 0
1610                 parent.removeChild (fCurrentNode);
1611                 fCurrentNode = parent;
1612             }
1613         }
1614         else {
1615 
1616             if (fDocumentTypeIndex != -1) {
1617                 // find corresponding Entity decl
1618                 int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
1619                 while (node != -1) {
1620                     short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1621                     if (nodeType == Node.ENTITY_NODE) {
1622                         String nodeName =
1623                         fDeferredDocumentImpl.getNodeName (node, false);
1624                         if (nodeName.equals (name)) {
1625                             fDeferredEntityDecl = node;
1626                             break;
1627                         }
1628                     }
1629                     node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
1630                 }
1631             }
1632 
1633             if (fDeferredEntityDecl != -1 &&
1634             fDeferredDocumentImpl.getLastChild (fDeferredEntityDecl, false) == -1) {
1635                 // entity definition exists and it does not have any children
1636                 int prevIndex = -1;
1637                 int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
1638                 while (childIndex != -1) {
1639                     int cloneIndex = fDeferredDocumentImpl.cloneNode (childIndex, true);
1640                     fDeferredDocumentImpl.insertBefore (fDeferredEntityDecl, cloneIndex, prevIndex);
1641                     prevIndex = cloneIndex;
1642                     childIndex = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
1643                 }
1644             }
1645             if (fCreateEntityRefNodes) {
1646                 fCurrentNodeIndex =
1647                 fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
1648                 false);
1649             } else { //!fCreateEntityRefNodes
1650                 // move children of entity ref before the entity ref.
1651                 // remove entity ref.
1652 
1653                 // holds a child of entity ref
1654                 int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
1655                 int parentIndex =
1656                 fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
1657                 false);
1658 
1659                 int prevIndex = fCurrentNodeIndex;
1660                 int lastChild = childIndex;
1661                 int sibling = -1;
1662                 while (childIndex != -1) {
1663                     handleBaseURI (childIndex);
1664                     sibling = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
1665                     fDeferredDocumentImpl.insertBefore (parentIndex, childIndex, prevIndex);
1666                     prevIndex = childIndex;
1667                     childIndex = sibling;
1668                 }
1669                 if(lastChild != -1)
1670                     fDeferredDocumentImpl.setAsLastChild (parentIndex, lastChild);
1671                 else{
1672                     sibling = fDeferredDocumentImpl.getRealPrevSibling (prevIndex, false);
1673                     fDeferredDocumentImpl.setAsLastChild (parentIndex, sibling);
1674                 }
1675                 fCurrentNodeIndex = parentIndex;
1676             }
1677             fDeferredEntityDecl = -1;
1678         }
1679 
1680 
1681     } // endGeneralEntity(String, Augmentations)
1682 
1683 
1684     /**
1685      * Record baseURI information for the Element (by adding xml:base attribute)
1686      * or for the ProcessingInstruction (by setting a baseURI field)
1687      * Non deferred DOM.
1688      *
1689      * @param node
1690      */
1691     protected final void handleBaseURI (Node node){
1692         if (fDocumentImpl != null) {
1693             // REVISIT: remove dependency on our implementation when
1694             //          DOM L3 becomes REC
1695 
1696             String baseURI = null;
1697             short nodeType = node.getNodeType ();
1698 
1699             if (nodeType == Node.ELEMENT_NODE) {
1700                 // if an element already has xml:base attribute
1701                 // do nothing
1702                 if (fNamespaceAware) {
1703                     if (((Element)node).getAttributeNodeNS ("http://www.w3.org/XML/1998/namespace","base")!=null) {
1704                         return;
1705                     }
1706                 } else if (((Element)node).getAttributeNode ("xml:base") != null) {
1707                     return;
1708                 }
1709                 // retrive the baseURI from the entity reference
1710                 baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
1711                 if (baseURI !=null && !baseURI.equals (fDocumentImpl.getDocumentURI ())) {
1712                     if (fNamespaceAware) {
1713                         ((Element)node).setAttributeNS ("http://www.w3.org/XML/1998/namespace", "xml:base", baseURI);
1714                     } else {
1715                         ((Element)node).setAttribute ("xml:base", baseURI);
1716                     }
1717                 }
1718             }
1719             else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1720 
1721                 baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
1722                 if (baseURI !=null && fErrorHandler != null) {
1723                     DOMErrorImpl error = new DOMErrorImpl ();
1724                     error.fType = "pi-base-uri-not-preserved";
1725                     error.fRelatedData = baseURI;
1726                     error.fSeverity = DOMError.SEVERITY_WARNING;
1727                     fErrorHandler.getErrorHandler ().handleError (error);
1728                 }
1729             }
1730         }
1731     }
1732 
1733     /**
1734      *
1735      * Record baseURI information for the Element (by adding xml:base attribute)
1736      * or for the ProcessingInstruction (by setting a baseURI field)
1737      * Deferred DOM.
1738      *
1739      * @param node
1740      */
1741     protected final void handleBaseURI (int node){
1742         short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1743 
1744         if (nodeType == Node.ELEMENT_NODE) {
1745             String baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
1746             if (baseURI == null) {
1747                 baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
1748             }
1749             if (baseURI !=null && !baseURI.equals (fDeferredDocumentImpl.getDocumentURI ())) {
1750                 fDeferredDocumentImpl.setDeferredAttribute (node,
1751                 "xml:base",
1752                 "http://www.w3.org/XML/1998/namespace",
1753                 baseURI,
1754                 true);
1755             }
1756         }
1757         else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1758 
1759 
1760             // retrieve baseURI from the entity reference
1761             String baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
1762 
1763             if (baseURI == null) {
1764                 // try baseURI of the entity declaration
1765                 baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
1766             }
1767 
1768             if (baseURI != null && fErrorHandler != null) {
1769                 DOMErrorImpl error = new DOMErrorImpl ();
1770                 error.fType = "pi-base-uri-not-preserved";
1771                 error.fRelatedData = baseURI;
1772                 error.fSeverity = DOMError.SEVERITY_WARNING;
1773                 fErrorHandler.getErrorHandler ().handleError (error);
1774             }
1775         }
1776     }
1777 
1778 
1779     //
1780     // XMLDTDHandler methods
1781     //
1782 
1783     /**
1784      * The start of the DTD.
1785      *
1786      * @param locator  The document locator, or null if the document
1787      *                 location cannot be reported during the parsing of
1788      *                 the document DTD. However, it is <em>strongly</em>
1789      *                 recommended that a locator be supplied that can
1790      *                 at least report the base system identifier of the
1791      *                 DTD.
1792      * @param augs Additional information that may include infoset
1793      *                      augmentations.
1794      *
1795      * @throws XNIException Thrown by handler to signal an error.
1796      */
1797     public void startDTD (XMLLocator locator, Augmentations augs) throws XNIException {
1798         if (DEBUG_EVENTS) {
1799             System.out.println ("==>startDTD");
1800             if (DEBUG_BASEURI) {
1801                 System.out.println ("   expandedSystemId: "+locator.getExpandedSystemId ());
1802                 System.out.println ("   baseURI:"+ locator.getBaseSystemId ());
1803             }
1804         }
1805 
1806         fInDTD = true;
1807         if (locator != null) {
1808             fBaseURIStack.push (locator.getBaseSystemId ());
1809         }
1810         if (fDeferNodeExpansion || fDocumentImpl != null) {
1811             fInternalSubset = new StringBuilder (1024);
1812         }
1813     } // startDTD(XMLLocator)
1814 
1815 
1816     /**
1817      * The end of the DTD.
1818      *
1819      * @param augs Additional information that may include infoset
1820      *                      augmentations.
1821      *
1822      * @throws XNIException Thrown by handler to signal an error.
1823      */
1824     public void endDTD (Augmentations augs) throws XNIException {
1825         if (DEBUG_EVENTS) {
1826             System.out.println ("==>endDTD()");
1827         }
1828         fInDTD = false;
1829         if (!fBaseURIStack.isEmpty ()) {
1830             fBaseURIStack.pop ();
1831         }
1832         String internalSubset = fInternalSubset != null && fInternalSubset.length () > 0
1833         ? fInternalSubset.toString () : null;
1834         if (fDeferNodeExpansion) {
1835             if (internalSubset != null) {
1836                 fDeferredDocumentImpl.setInternalSubset (fDocumentTypeIndex, internalSubset);
1837             }
1838         }
1839         else if (fDocumentImpl != null) {
1840             if (internalSubset != null) {
1841                 ((DocumentTypeImpl)fDocumentType).setInternalSubset (internalSubset);
1842             }
1843         }
1844     } // endDTD()
1845 
1846     /**
1847      * The start of a conditional section.
1848      *
1849      * @param type The type of the conditional section. This value will
1850      *             either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1851      * @param augs Additional information that may include infoset
1852      *                      augmentations.
1853      *
1854      * @throws XNIException Thrown by handler to signal an error.
1855      *
1856      * @see #CONDITIONAL_INCLUDE
1857      * @see #CONDITIONAL_IGNORE
1858      */
1859     public void startConditional (short type, Augmentations augs) throws XNIException  {
1860     } // startConditional(short)
1861 
1862     /**
1863      * The end of a conditional section.
1864      *
1865      * @param augs Additional information that may include infoset
1866      *                      augmentations.
1867      *
1868      * @throws XNIException Thrown by handler to signal an error.
1869      */
1870     public void endConditional (Augmentations augs) throws XNIException {
1871     } // endConditional()
1872 
1873 
1874     /**
1875      * The start of the DTD external subset.
1876      *
1877      * @param augs Additional information that may include infoset
1878      *                      augmentations.
1879      *
1880      * @throws XNIException Thrown by handler to signal an error.
1881      */
1882     public void startExternalSubset (XMLResourceIdentifier identifier,
1883     Augmentations augs) throws XNIException {
1884         if (DEBUG_EVENTS) {
1885             System.out.println ("==>startExternalSubset");
1886             if (DEBUG_BASEURI) {
1887                 System.out.println ("   expandedSystemId: "+identifier.getExpandedSystemId ());
1888                 System.out.println ("   baseURI:"+ identifier.getBaseSystemId ());
1889             }
1890         }
1891         fBaseURIStack.push (identifier.getBaseSystemId ());
1892         fInDTDExternalSubset = true;
1893     } // startExternalSubset(Augmentations)
1894 
1895     /**
1896      * The end of the DTD external subset.
1897      *
1898      * @param augs Additional information that may include infoset
1899      *                      augmentations.
1900      *
1901      * @throws XNIException Thrown by handler to signal an error.
1902      */
1903     public void endExternalSubset (Augmentations augs) throws XNIException {
1904         fInDTDExternalSubset = false;
1905         fBaseURIStack.pop ();
1906     } // endExternalSubset(Augmentations)
1907 
1908     /**
1909      * An internal entity declaration.
1910      *
1911      * @param name The name of the entity. Parameter entity names start with
1912      *             '%', whereas the name of a general entity is just the
1913      *             entity name.
1914      * @param text The value of the entity.
1915      * @param nonNormalizedText The non-normalized value of the entity. This
1916      *             value contains the same sequence of characters that was in
1917      *             the internal entity declaration, without any entity
1918      *             references expanded.
1919      * @param augs Additional information that may include infoset
1920      *                      augmentations.
1921      *
1922      * @throws XNIException Thrown by handler to signal an error.
1923      */
1924     public void internalEntityDecl (String name, XMLString text,
1925     XMLString nonNormalizedText,
1926     Augmentations augs) throws XNIException {
1927 
1928         if (DEBUG_EVENTS) {
1929             System.out.println ("==>internalEntityDecl: "+name);
1930             if (DEBUG_BASEURI) {
1931                 System.out.println ("   baseURI:"+ (String)fBaseURIStack.peek ());
1932             }
1933         }
1934         // internal subset string
1935         if (fInternalSubset != null && !fInDTDExternalSubset) {
1936             fInternalSubset.append ("<!ENTITY ");
1937             if (name.startsWith ("%")) {
1938                 fInternalSubset.append ("% ");
1939                 fInternalSubset.append (name.substring (1));
1940             }
1941             else {
1942                 fInternalSubset.append (name);
1943             }
1944             fInternalSubset.append (' ');
1945             String value = nonNormalizedText.toString ();
1946             boolean singleQuote = value.indexOf ('\'') == -1;
1947             fInternalSubset.append (singleQuote ? '\'' : '"');
1948             fInternalSubset.append (value);
1949             fInternalSubset.append (singleQuote ? '\'' : '"');
1950             fInternalSubset.append (">\n");
1951         }
1952 
1953         // NOTE: We only know how to create these nodes for the Xerces
1954         //       DOM implementation because DOM Level 2 does not specify
1955         //       that functionality. -Ac
1956 
1957         // create full node
1958         // don't add parameter entities!
1959         if(name.startsWith ("%"))
1960             return;
1961         if (fDocumentType != null) {
1962             NamedNodeMap entities = fDocumentType.getEntities ();
1963             EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
1964             if (entity == null) {
1965                 entity = (EntityImpl)fDocumentImpl.createEntity (name);
1966                 entity.setBaseURI ((String)fBaseURIStack.peek ());
1967                 entities.setNamedItem (entity);
1968             }
1969         }
1970 
1971         // create deferred node
1972         if (fDocumentTypeIndex != -1) {
1973             boolean found = false;
1974             int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
1975             while (node != -1) {
1976                 short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1977                 if (nodeType == Node.ENTITY_NODE) {
1978                     String nodeName = fDeferredDocumentImpl.getNodeName (node, false);
1979                     if (nodeName.equals (name)) {
1980                         found = true;
1981                         break;
1982                     }
1983                 }
1984                 node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
1985             }
1986             if (!found) {
1987                 int entityIndex =
1988                 fDeferredDocumentImpl.createDeferredEntity (name, null, null, null, (String)fBaseURIStack.peek ());
1989                 fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
1990             }
1991         }
1992 
1993     } // internalEntityDecl(String,XMLString,XMLString)
1994 
1995     /**
1996      * An external entity declaration.
1997      *
1998      * @param name     The name of the entity. Parameter entity names start
1999      *                 with '%', whereas the name of a general entity is just
2000      *                 the entity name.
2001      * @param identifier    An object containing all location information
2002      *                      pertinent to this notation.
2003      * @param augs Additional information that may include infoset
2004      *                      augmentations.
2005      *
2006      * @throws XNIException Thrown by handler to signal an error.
2007      */
2008     public void externalEntityDecl (String name, XMLResourceIdentifier identifier,
2009     Augmentations augs) throws XNIException {
2010 
2011 
2012         if (DEBUG_EVENTS) {
2013             System.out.println ("==>externalEntityDecl: "+name);
2014             if (DEBUG_BASEURI) {
2015                 System.out.println ("   expandedSystemId:"+ identifier.getExpandedSystemId ());
2016                 System.out.println ("   baseURI:"+ identifier.getBaseSystemId ());
2017             }
2018         }
2019         // internal subset string
2020         String publicId = identifier.getPublicId ();
2021         String literalSystemId = identifier.getLiteralSystemId ();
2022         if (fInternalSubset != null && !fInDTDExternalSubset) {
2023             fInternalSubset.append ("<!ENTITY ");
2024             if (name.startsWith ("%")) {
2025                 fInternalSubset.append ("% ");
2026                 fInternalSubset.append (name.substring (1));
2027             }
2028             else {
2029                 fInternalSubset.append (name);
2030             }
2031             fInternalSubset.append (' ');
2032             if (publicId != null) {
2033                 fInternalSubset.append ("PUBLIC '");
2034                 fInternalSubset.append (publicId);
2035                 fInternalSubset.append ("' '");
2036             }
2037             else {
2038                 fInternalSubset.append ("SYSTEM '");
2039             }
2040             fInternalSubset.append (literalSystemId);
2041             fInternalSubset.append ("'>\n");
2042         }
2043 
2044         // NOTE: We only know how to create these nodes for the Xerces
2045         //       DOM implementation because DOM Level 2 does not specify
2046         //       that functionality. -Ac
2047 
2048         // create full node
2049         // don't add parameter entities!
2050         if(name.startsWith ("%"))
2051             return;
2052         if (fDocumentType != null) {
2053             NamedNodeMap entities = fDocumentType.getEntities ();
2054             EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
2055             if (entity == null) {
2056                 entity = (EntityImpl)fDocumentImpl.createEntity (name);
2057                 entity.setPublicId (publicId);
2058                 entity.setSystemId (literalSystemId);
2059                 entity.setBaseURI (identifier.getBaseSystemId ());
2060                 entities.setNamedItem (entity);
2061             }
2062         }
2063 
2064         // create deferred node
2065         if (fDocumentTypeIndex != -1) {
2066             boolean found = false;
2067             int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2068             while (nodeIndex != -1) {
2069                 short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2070                 if (nodeType == Node.ENTITY_NODE) {
2071                     String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2072                     if (nodeName.equals (name)) {
2073                         found = true;
2074                         break;
2075                     }
2076                 }
2077                 nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
2078             }
2079             if (!found) {
2080                 int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
2081                 name, publicId, literalSystemId, null, identifier.getBaseSystemId ());
2082                 fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
2083             }
2084         }
2085 
2086     } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
2087 
2088 
2089     /**
2090      * This method notifies of the start of a parameter entity. The parameter
2091      * entity name start with a '%' character.
2092      *
2093      * @param name     The name of the parameter entity.
2094      * @param identifier The resource identifier.
2095      * @param encoding The auto-detected IANA encoding name of the entity
2096      *                 stream. This value will be null in those situations
2097      *                 where the entity encoding is not auto-detected (e.g.
2098      *                 internal parameter entities).
2099      * @param augs Additional information that may include infoset
2100      *                      augmentations.
2101      *
2102      * @throws XNIException Thrown by handler to signal an error.
2103      */
2104     public void startParameterEntity (String name,
2105     XMLResourceIdentifier identifier,
2106     String encoding,
2107     Augmentations augs) throws XNIException {
2108         if (DEBUG_EVENTS) {
2109             System.out.println ("==>startParameterEntity: "+name);
2110             if (DEBUG_BASEURI) {
2111                 System.out.println ("   expandedSystemId: "+identifier.getExpandedSystemId ());
2112                 System.out.println ("   baseURI:"+ identifier.getBaseSystemId ());
2113             }
2114         }
2115         if (augs != null && fInternalSubset != null &&
2116             !fInDTDExternalSubset &&
2117             Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
2118             fInternalSubset.append(name).append(";\n");
2119         }
2120         fBaseURIStack.push (identifier.getExpandedSystemId ());
2121     }
2122 
2123 
2124     /**
2125      * This method notifies the end of a parameter entity. Parameter entity
2126      * names begin with a '%' character.
2127      *
2128      * @param name The name of the parameter entity.
2129      * @param augs Additional information that may include infoset
2130      *                      augmentations.
2131      *
2132      * @throws XNIException Thrown by handler to signal an error.
2133      */
2134     public void endParameterEntity (String name, Augmentations augs) throws XNIException {
2135 
2136         if (DEBUG_EVENTS) {
2137             System.out.println ("==>endParameterEntity: "+name);
2138         }
2139         fBaseURIStack.pop ();
2140     }
2141 
2142     /**
2143      * An unparsed entity declaration.
2144      *
2145      * @param name     The name of the entity.
2146      * @param identifier    An object containing all location information
2147      *                      pertinent to this entity.
2148      * @param notation The name of the notation.
2149      * @param augs Additional information that may include infoset
2150      *                      augmentations.
2151      *
2152      * @throws XNIException Thrown by handler to signal an error.
2153      */
2154     public void unparsedEntityDecl (String name, XMLResourceIdentifier identifier,
2155     String notation, Augmentations augs)
2156     throws XNIException {
2157 
2158         if (DEBUG_EVENTS) {
2159             System.out.println ("==>unparsedEntityDecl: "+name);
2160             if (DEBUG_BASEURI) {
2161                 System.out.println ("   expandedSystemId:"+ identifier.getExpandedSystemId ());
2162                 System.out.println ("   baseURI:"+ identifier.getBaseSystemId ());
2163             }
2164         }
2165         // internal subset string
2166         String publicId = identifier.getPublicId ();
2167         String literalSystemId = identifier.getLiteralSystemId ();
2168         if (fInternalSubset != null && !fInDTDExternalSubset) {
2169             fInternalSubset.append ("<!ENTITY ");
2170             fInternalSubset.append (name);
2171             fInternalSubset.append (' ');
2172             if (publicId != null) {
2173                 fInternalSubset.append ("PUBLIC '");
2174                 fInternalSubset.append (publicId);
2175                 if (literalSystemId != null) {
2176                     fInternalSubset.append ("' '");
2177                     fInternalSubset.append (literalSystemId);
2178                 }
2179             }
2180             else {
2181                 fInternalSubset.append ("SYSTEM '");
2182                 fInternalSubset.append (literalSystemId);
2183             }
2184             fInternalSubset.append ("' NDATA ");
2185             fInternalSubset.append (notation);
2186             fInternalSubset.append (">\n");
2187         }
2188 
2189         // NOTE: We only know how to create these nodes for the Xerces
2190         //       DOM implementation because DOM Level 2 does not specify
2191         //       that functionality. -Ac
2192 
2193         // create full node
2194         if (fDocumentType != null) {
2195             NamedNodeMap entities = fDocumentType.getEntities ();
2196             EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
2197             if (entity == null) {
2198                 entity = (EntityImpl)fDocumentImpl.createEntity (name);
2199                 entity.setPublicId (publicId);
2200                 entity.setSystemId (literalSystemId);
2201                 entity.setNotationName (notation);
2202                 entity.setBaseURI (identifier.getBaseSystemId ());
2203                 entities.setNamedItem (entity);
2204             }
2205         }
2206 
2207         // create deferred node
2208         if (fDocumentTypeIndex != -1) {
2209             boolean found = false;
2210             int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2211             while (nodeIndex != -1) {
2212                 short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2213                 if (nodeType == Node.ENTITY_NODE) {
2214                     String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2215                     if (nodeName.equals (name)) {
2216                         found = true;
2217                         break;
2218                     }
2219                 }
2220                 nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
2221             }
2222             if (!found) {
2223                 int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
2224                 name, publicId, literalSystemId, notation, identifier.getBaseSystemId ());
2225                 fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
2226             }
2227         }
2228 
2229     } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
2230 
2231     /**
2232      * A notation declaration
2233      *
2234      * @param name     The name of the notation.
2235      * @param identifier    An object containing all location information
2236      *                      pertinent to this notation.
2237      * @param augs Additional information that may include infoset
2238      *                      augmentations.
2239      *
2240      * @throws XNIException Thrown by handler to signal an error.
2241      */
2242     public void notationDecl (String name, XMLResourceIdentifier identifier,
2243     Augmentations augs) throws XNIException {
2244 
2245         // internal subset string
2246         String publicId = identifier.getPublicId ();
2247         String literalSystemId = identifier.getLiteralSystemId ();
2248         if (fInternalSubset != null && !fInDTDExternalSubset) {
2249             fInternalSubset.append ("<!NOTATION ");
2250             fInternalSubset.append (name);
2251             if (publicId != null) {
2252                 fInternalSubset.append (" PUBLIC '");
2253                 fInternalSubset.append (publicId);
2254                 if (literalSystemId != null) {
2255                     fInternalSubset.append ("' '");
2256                     fInternalSubset.append (literalSystemId);
2257                 }
2258             }
2259             else {
2260                 fInternalSubset.append (" SYSTEM '");
2261                 fInternalSubset.append (literalSystemId);
2262             }
2263             fInternalSubset.append ("'>\n");
2264         }
2265 
2266         // NOTE: We only know how to create these nodes for the Xerces
2267         //       DOM implementation because DOM Level 2 does not specify
2268         //       that functionality. -Ac
2269 
2270         // create full node
2271         if (fDocumentImpl !=null && fDocumentType != null) {
2272             NamedNodeMap notations = fDocumentType.getNotations ();
2273             if (notations.getNamedItem (name) == null) {
2274                 NotationImpl notation = (NotationImpl)fDocumentImpl.createNotation (name);
2275                 notation.setPublicId (publicId);
2276                 notation.setSystemId (literalSystemId);
2277                 notation.setBaseURI (identifier.getBaseSystemId ());
2278                 notations.setNamedItem (notation);
2279             }
2280         }
2281 
2282         // create deferred node
2283         if (fDocumentTypeIndex != -1) {
2284             boolean found = false;
2285             int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2286             while (nodeIndex != -1) {
2287                 short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2288                 if (nodeType == Node.NOTATION_NODE) {
2289                     String nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2290                     if (nodeName.equals (name)) {
2291                         found = true;
2292                         break;
2293                     }
2294                 }
2295                 nodeIndex = fDeferredDocumentImpl.getPrevSibling (nodeIndex, false);
2296             }
2297             if (!found) {
2298                 int notationIndex = fDeferredDocumentImpl.createDeferredNotation (
2299                 name, publicId, literalSystemId, identifier.getBaseSystemId ());
2300                 fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, notationIndex);
2301             }
2302         }
2303 
2304     } // notationDecl(String,XMLResourceIdentifier, Augmentations)
2305 
2306     /**
2307      * Characters within an IGNORE conditional section.
2308      *
2309      * @param text The ignored text.
2310      * @param augs Additional information that may include infoset
2311      *                      augmentations.
2312      *
2313      * @throws XNIException Thrown by handler to signal an error.
2314      */
2315     public void ignoredCharacters (XMLString text, Augmentations augs) throws XNIException {
2316     } // ignoredCharacters(XMLString, Augmentations)
2317 
2318 
2319     /**
2320      * An element declaration.
2321      *
2322      * @param name         The name of the element.
2323      * @param contentModel The element content model.
2324      * @param augs Additional information that may include infoset
2325      *                      augmentations.
2326      *
2327      * @throws XNIException Thrown by handler to signal an error.
2328      */
2329     public void elementDecl (String name, String contentModel, Augmentations augs)
2330     throws XNIException {
2331 
2332         // internal subset string
2333         if (fInternalSubset != null && !fInDTDExternalSubset) {
2334             fInternalSubset.append ("<!ELEMENT ");
2335             fInternalSubset.append (name);
2336             fInternalSubset.append (' ');
2337             fInternalSubset.append (contentModel);
2338             fInternalSubset.append (">\n");
2339         }
2340 
2341     } // elementDecl(String,String)
2342 
2343     /**
2344      * An attribute declaration.
2345      *
2346      * @param elementName   The name of the element that this attribute
2347      *                      is associated with.
2348      * @param attributeName The name of the attribute.
2349      * @param type          The attribute type. This value will be one of
2350      *                      the following: "CDATA", "ENTITY", "ENTITIES",
2351      *                      "ENUMERATION", "ID", "IDREF", "IDREFS",
2352      *                      "NMTOKEN", "NMTOKENS", or "NOTATION".
2353      * @param enumeration   If the type has the value "ENUMERATION" or
2354      *                      "NOTATION", this array holds the allowed attribute
2355      *                      values; otherwise, this array is null.
2356      * @param defaultType   The attribute default type. This value will be
2357      *                      one of the following: "#FIXED", "#IMPLIED",
2358      *                      "#REQUIRED", or null.
2359      * @param defaultValue  The attribute default value, or null if no
2360      *                      default value is specified.
2361      * @param nonNormalizedDefaultValue  The attribute default value with no normalization
2362      *                      performed, or null if no default value is specified.
2363      * @param augs Additional information that may include infoset
2364      *                      augmentations.
2365      *
2366      * @throws XNIException Thrown by handler to signal an error.
2367      */
2368     public void attributeDecl (String elementName, String attributeName,
2369     String type, String[] enumeration,
2370     String defaultType, XMLString defaultValue,
2371     XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
2372 
2373         // internal subset string
2374         if (fInternalSubset != null && !fInDTDExternalSubset) {
2375             fInternalSubset.append ("<!ATTLIST ");
2376             fInternalSubset.append (elementName);
2377             fInternalSubset.append (' ');
2378             fInternalSubset.append (attributeName);
2379             fInternalSubset.append (' ');
2380             if (type.equals ("ENUMERATION")) {
2381                 fInternalSubset.append ('(');
2382                 for (int i = 0; i < enumeration.length; i++) {
2383                     if (i > 0) {
2384                         fInternalSubset.append ('|');
2385                     }
2386                     fInternalSubset.append (enumeration[i]);
2387                 }
2388                 fInternalSubset.append (')');
2389             }
2390             else {
2391                 fInternalSubset.append (type);
2392             }
2393             if (defaultType != null) {
2394                 fInternalSubset.append (' ');
2395                 fInternalSubset.append (defaultType);
2396             }
2397             if (defaultValue != null) {
2398                 fInternalSubset.append (" '");
2399                 for (int i = 0; i < defaultValue.length; i++) {
2400                     char c = defaultValue.ch[defaultValue.offset + i];
2401                     if (c == '\'') {
2402                         fInternalSubset.append ("&apos;");
2403                     }
2404                     else {
2405                         fInternalSubset.append (c);
2406                     }
2407                 }
2408                 fInternalSubset.append ('\'');
2409             }
2410             fInternalSubset.append (">\n");
2411         }
2412         // REVISIT: This code applies to the support of domx/grammar-access
2413         // feature in Xerces 1
2414 
2415         // deferred expansion
2416         if (fDeferredDocumentImpl != null) {
2417 
2418             // get the default value
2419             if (defaultValue != null) {
2420 
2421                 // get element definition
2422                 int elementDefIndex  = fDeferredDocumentImpl.lookupElementDefinition (elementName);
2423 
2424                 // create element definition if not already there
2425                 if (elementDefIndex == -1) {
2426                     elementDefIndex = fDeferredDocumentImpl.createDeferredElementDefinition (elementName);
2427                     fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, elementDefIndex);
2428                 }
2429                 // add default attribute
2430                 boolean nsEnabled = fNamespaceAware;
2431                 String namespaceURI = null;
2432                 if (nsEnabled) {
2433                     // DOM Level 2 wants all namespace declaration attributes
2434                     // to be bound to "http://www.w3.org/2000/xmlns/"
2435                     // So as long as the XML parser doesn't do it, it needs to
2436                     // done here.
2437                     if (attributeName.startsWith("xmlns:") ||
2438                         attributeName.equals("xmlns")) {
2439                         namespaceURI = NamespaceContext.XMLNS_URI;
2440                     }
2441                     else if (attributeName.startsWith("xml:")) {
2442                         namespaceURI = NamespaceContext.XML_URI;
2443                     }
2444                 }
2445                 int attrIndex = fDeferredDocumentImpl.createDeferredAttribute (
2446                         attributeName, namespaceURI, defaultValue.toString(), false);
2447                 if ("ID".equals (type)) {
2448                     fDeferredDocumentImpl.setIdAttribute (attrIndex);
2449                 }
2450                 // REVISIT: set ID type correctly
2451                 fDeferredDocumentImpl.appendChild (elementDefIndex, attrIndex);
2452             }
2453 
2454         } // if deferred
2455 
2456         // full expansion
2457         else if (fDocumentImpl != null) {
2458 
2459             // get the default value
2460             if (defaultValue != null) {
2461 
2462                 // get element definition node
2463                 NamedNodeMap elements = ((DocumentTypeImpl)fDocumentType).getElements ();
2464                 ElementDefinitionImpl elementDef = (ElementDefinitionImpl)elements.getNamedItem (elementName);
2465                 if (elementDef == null) {
2466                     elementDef = fDocumentImpl.createElementDefinition (elementName);
2467                     ((DocumentTypeImpl)fDocumentType).getElements ().setNamedItem (elementDef);
2468                 }
2469 
2470                 // REVISIT: Check for uniqueness of element name? -Ac
2471 
2472                 // create attribute and set properties
2473                 boolean nsEnabled = fNamespaceAware;
2474                 AttrImpl attr;
2475                 if (nsEnabled) {
2476                     String namespaceURI = null;
2477                     // DOM Level 2 wants all namespace declaration attributes
2478                     // to be bound to "http://www.w3.org/2000/xmlns/"
2479                     // So as long as the XML parser doesn't do it, it needs to
2480                     // done here.
2481                     if (attributeName.startsWith("xmlns:") ||
2482                         attributeName.equals("xmlns")) {
2483                         namespaceURI = NamespaceContext.XMLNS_URI;
2484                     }
2485                     else if (attributeName.startsWith("xml:")) {
2486                         namespaceURI = NamespaceContext.XML_URI;
2487                     }
2488                     attr = (AttrImpl)fDocumentImpl.createAttributeNS (namespaceURI,
2489                     attributeName);
2490                 }
2491                 else {
2492                     attr = (AttrImpl)fDocumentImpl.createAttribute (attributeName);
2493                 }
2494                 attr.setValue (defaultValue.toString ());
2495                 attr.setSpecified (false);
2496                 attr.setIdAttribute ("ID".equals (type));
2497 
2498                 // add default attribute to element definition
2499                 if (nsEnabled){
2500                     elementDef.getAttributes ().setNamedItemNS (attr);
2501                 }
2502                 else {
2503                     elementDef.getAttributes ().setNamedItem (attr);
2504                 }
2505             }
2506 
2507         } // if NOT defer-node-expansion
2508 
2509     } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
2510 
2511 
2512     /**
2513      * The start of an attribute list.
2514      *
2515      * @param elementName The name of the element that this attribute
2516      *                    list is associated with.
2517      * @param augs Additional information that may include infoset
2518      *                      augmentations.
2519      *
2520      * @throws XNIException Thrown by handler to signal an error.
2521      */
2522     public void startAttlist (String elementName, Augmentations augs) throws XNIException {
2523     } // startAttlist(String)
2524 
2525 
2526     /**
2527      * The end of an attribute list.
2528      *
2529      * @param augs Additional information that may include infoset
2530      *                      augmentations.
2531      *
2532      * @throws XNIException Thrown by handler to signal an error.
2533      */
2534     public void endAttlist (Augmentations augs) throws XNIException {
2535     } // endAttlist()
2536 
2537 
2538     // method to create an element node.
2539     // subclasses can override this method to create element nodes in other ways.
2540     protected Element createElementNode (QName element) {
2541         Element el = null;
2542 
2543         if (fNamespaceAware) {
2544             // if we are using xerces DOM implementation, call our
2545             // own constructor to reuse the strings we have here.
2546             if (fDocumentImpl != null) {
2547                 el = fDocumentImpl.createElementNS (element.uri, element.rawname,
2548                 element.localpart);
2549             }
2550             else {
2551                 el = fDocument.createElementNS (element.uri, element.rawname);
2552             }
2553         }
2554         else {
2555             el = fDocument.createElement (element.rawname);
2556         }
2557 
2558         return el;
2559     }
2560 
2561     // method to create an attribute node.
2562     // subclasses can override this method to create attribute nodes in other ways.
2563     protected Attr createAttrNode (QName attrQName) {
2564         Attr attr = null;
2565 
2566         if (fNamespaceAware) {
2567             if (fDocumentImpl != null) {
2568                 // if we are using xerces DOM implementation, call our
2569                 // own constructor to reuse the strings we have here.
2570                 attr = fDocumentImpl.createAttributeNS (attrQName.uri,
2571                 attrQName.rawname,
2572                 attrQName.localpart);
2573             }
2574             else {
2575                 attr = fDocument.createAttributeNS (attrQName.uri,
2576                 attrQName.rawname);
2577             }
2578         }
2579         else {
2580             attr = fDocument.createAttribute (attrQName.rawname);
2581         }
2582 
2583         return attr;
2584     }
2585 
2586     /*
2587      * When the first characters() call is received, the data is stored in
2588      * a new Text node. If right after the first characters() we receive another chunk of data,
2589      * the data from the Text node, following the new characters are appended
2590      * to the fStringBuffer and the text node data is set to empty.
2591      *
2592      * This function is called when the state is changed and the
2593      * data must be appended to the current node.
2594      *
2595      * Note: if DOMFilter is set, you must make sure that if Node is skipped,
2596      * or removed fFistChunk must be set to true, otherwise some data can be lost.
2597      *
2598      */
2599     protected void  setCharacterData (boolean sawChars){
2600 
2601         // handle character data
2602         fFirstChunk = sawChars;
2603 
2604 
2605         // if we have data in the buffer we must have created
2606         // a text node already.
2607 
2608         Node child = fCurrentNode.getLastChild ();
2609         if (child != null) {
2610             if (fStringBuilder.length () > 0) {
2611                 // REVISIT: should this check be performed?
2612                 if (child.getNodeType () == Node.TEXT_NODE) {
2613                     if (fDocumentImpl != null) {
2614                         ((TextImpl)child).replaceData (fStringBuilder.toString ());
2615                     }
2616                     else {
2617                         ((Text)child).setData (fStringBuilder.toString ());
2618                     }
2619                 }
2620                 // reset string buffer
2621                 fStringBuilder.setLength (0);
2622             }
2623 
2624             if (fDOMFilter !=null && !fInEntityRef) {
2625                 if ( (child.getNodeType () == Node.TEXT_NODE ) &&
2626                 ((fDOMFilter.getWhatToShow () & NodeFilter.SHOW_TEXT)!= 0) ) {
2627                     short code = fDOMFilter.acceptNode (child);
2628                     switch (code) {
2629                         case LSParserFilter.FILTER_INTERRUPT:{
2630                             throw Abort.INSTANCE;
2631                         }
2632                         case LSParserFilter.FILTER_REJECT:{
2633                             // fall through to SKIP since Comment has no children.
2634                         }
2635                         case LSParserFilter.FILTER_SKIP: {
2636                             fCurrentNode.removeChild (child);
2637                             return;
2638                         }
2639                         default: {
2640                             // accept node -- do nothing
2641                         }
2642                     }
2643                 }
2644             }   // end-if fDOMFilter !=null
2645 
2646         } // end-if child !=null
2647     }
2648 
2649 
2650     /**
2651      * @see org.w3c.dom.ls.LSParser#abort()
2652      */
2653     public void abort () {
2654         throw Abort.INSTANCE;
2655     }
2656 
2657 
2658 } // class AbstractDOMParser