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 ("'"); 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