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