1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 2001-2004 The Apache Software Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.parsers;
  58. import java.util.Locale;
  59. import java.util.Stack;
  60. import com.sun.org.apache.xerces.internal.dom.AttrImpl;
  61. import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
  62. import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
  63. import com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl;
  64. import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
  65. import com.sun.org.apache.xerces.internal.dom.DocumentTypeImpl;
  66. import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  67. import com.sun.org.apache.xerces.internal.dom.ElementDefinitionImpl;
  68. import com.sun.org.apache.xerces.internal.dom.ElementImpl;
  69. import com.sun.org.apache.xerces.internal.dom.EntityImpl;
  70. import com.sun.org.apache.xerces.internal.dom.EntityReferenceImpl;
  71. import com.sun.org.apache.xerces.internal.dom.NodeImpl;
  72. import com.sun.org.apache.xerces.internal.dom.NotationImpl;
  73. import com.sun.org.apache.xerces.internal.dom.PSVIAttrNSImpl;
  74. import com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl;
  75. import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl;
  76. import com.sun.org.apache.xerces.internal.dom.TextImpl;
  77. import com.sun.org.apache.xerces.internal.impl.Constants;
  78. import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  79. import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
  80. import com.sun.org.apache.xerces.internal.util.TypeInfoImpl;
  81. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  82. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  83. import com.sun.org.apache.xerces.internal.xni.QName;
  84. import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  85. import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  86. import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  87. import com.sun.org.apache.xerces.internal.xni.XMLString;
  88. import com.sun.org.apache.xerces.internal.xni.XNIException;
  89. import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  90. import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  91. import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  92. import org.w3c.dom.Attr;
  93. import org.w3c.dom.CDATASection;
  94. import org.w3c.dom.Comment;
  95. import org.w3c.dom.DOMError;
  96. import org.w3c.dom.Document;
  97. import org.w3c.dom.DocumentType;
  98. import org.w3c.dom.Element;
  99. import org.w3c.dom.EntityReference;
  100. import org.w3c.dom.NamedNodeMap;
  101. import org.w3c.dom.Node;
  102. import org.w3c.dom.NodeList;
  103. import org.w3c.dom.ProcessingInstruction;
  104. import org.w3c.dom.Text;
  105. import org.w3c.dom.TypeInfo;
  106. import org.w3c.dom.ls.LSParserFilter;
  107. import org.w3c.dom.traversal.NodeFilter;
  108. /**
  109. * This is the base class of all DOM parsers. It implements the XNI
  110. * callback methods to create the DOM tree. After a successful parse of
  111. * an XML document, the DOM Document object can be queried using the
  112. * <code>getDocument</code> method. The actual pipeline is defined in
  113. * parser configuration.
  114. *
  115. * @author Arnaud Le Hors, IBM
  116. * @author Andy Clark, IBM
  117. * @author Elena Litani, IBM
  118. *
  119. * @version $Id: AbstractDOMParser.java,v 1.108 2004/02/17 07:14:48 neeraj Exp $
  120. */
  121. public class AbstractDOMParser extends AbstractXMLDocumentParser {
  122. //
  123. // Constants
  124. //
  125. // feature ids
  126. /** Feature id: namespace. */
  127. protected static final String NAMESPACES =
  128. Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
  129. /** Feature id: create entity ref nodes. */
  130. protected static final String CREATE_ENTITY_REF_NODES =
  131. Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
  132. /** Feature id: include comments. */
  133. protected static final String INCLUDE_COMMENTS_FEATURE =
  134. Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
  135. /** Feature id: create cdata nodes. */
  136. protected static final String CREATE_CDATA_NODES_FEATURE =
  137. Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
  138. /** Feature id: include ignorable whitespace. */
  139. protected static final String INCLUDE_IGNORABLE_WHITESPACE =
  140. Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
  141. /** Feature id: defer node expansion. */
  142. protected static final String DEFER_NODE_EXPANSION =
  143. Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
  144. /** Recognized features. */
  145. private static final String[] RECOGNIZED_FEATURES = {
  146. NAMESPACES,
  147. CREATE_ENTITY_REF_NODES,
  148. INCLUDE_COMMENTS_FEATURE,
  149. CREATE_CDATA_NODES_FEATURE,
  150. INCLUDE_IGNORABLE_WHITESPACE,
  151. DEFER_NODE_EXPANSION
  152. };
  153. // property ids
  154. /** Property id: document class name. */
  155. protected static final String DOCUMENT_CLASS_NAME =
  156. Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
  157. protected static final String CURRENT_ELEMENT_NODE=
  158. Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
  159. // protected static final String GRAMMAR_POOL =
  160. // Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  161. /** Recognized properties. */
  162. private static final String[] RECOGNIZED_PROPERTIES = {
  163. DOCUMENT_CLASS_NAME,
  164. CURRENT_ELEMENT_NODE,
  165. };
  166. // other
  167. /** Default document class name. */
  168. protected static final String DEFAULT_DOCUMENT_CLASS_NAME =
  169. "com.sun.org.apache.xerces.internal.dom.DocumentImpl";
  170. protected static final String CORE_DOCUMENT_CLASS_NAME =
  171. "com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl";
  172. protected static final String PSVI_DOCUMENT_CLASS_NAME =
  173. "com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl";
  174. /**
  175. * If the user stops the process, this exception will be thrown.
  176. */
  177. public static final RuntimeException abort = new RuntimeException();
  178. // debugging
  179. private static final boolean DEBUG_EVENTS = false;
  180. private static final boolean DEBUG_BASEURI = false;
  181. //
  182. // Data
  183. //
  184. /** DOM L3 error handler */
  185. protected DOMErrorHandlerWrapper fErrorHandler = null;
  186. /** True if inside DTD. */
  187. protected boolean fInDTD;
  188. // features
  189. /** Create entity reference nodes. */
  190. protected boolean fCreateEntityRefNodes;
  191. /** Include ignorable whitespace. */
  192. protected boolean fIncludeIgnorableWhitespace;
  193. /** Include Comments. */
  194. protected boolean fIncludeComments;
  195. /** Create cdata nodes. */
  196. protected boolean fCreateCDATANodes;
  197. // dom information
  198. /** The document. */
  199. protected Document fDocument;
  200. /** The default Xerces document implementation, if used. */
  201. protected CoreDocumentImpl fDocumentImpl;
  202. /** Whether to store PSVI information in DOM tree. */
  203. protected boolean fStorePSVI;
  204. /** The document class name to use. */
  205. protected String fDocumentClassName;
  206. /** The document type node. */
  207. protected DocumentType fDocumentType;
  208. /** Current node. */
  209. protected Node fCurrentNode;
  210. protected CDATASection fCurrentCDATASection;
  211. protected EntityImpl fCurrentEntityDecl;
  212. protected int fDeferredEntityDecl;
  213. /** Character buffer */
  214. protected final StringBuffer fStringBuffer = new StringBuffer (50);
  215. // internal subset
  216. /** Internal subset buffer. */
  217. protected StringBuffer fInternalSubset;
  218. // deferred expansion data
  219. protected boolean fDeferNodeExpansion;
  220. protected boolean fNamespaceAware;
  221. protected DeferredDocumentImpl fDeferredDocumentImpl;
  222. protected int fDocumentIndex;
  223. protected int fDocumentTypeIndex;
  224. protected int fCurrentNodeIndex;
  225. protected int fCurrentCDATASectionIndex;
  226. // state
  227. /** True if inside DTD external subset. */
  228. protected boolean fInDTDExternalSubset;
  229. /** Root element name */
  230. protected QName fRoot = new QName();
  231. /** True if inside CDATA section. */
  232. protected boolean fInCDATASection;
  233. /** True if saw the first chunk of characters*/
  234. protected boolean fFirstChunk = false;
  235. /** LSParserFilter: specifies that element with given QNAME and all its children
  236. must be rejected */
  237. protected boolean fFilterReject = false;
  238. // data
  239. /** Base uri stack*/
  240. protected Stack fBaseURIStack = new Stack ();
  241. /** LSParserFilter: the QNAME of rejected element*/
  242. protected final QName fRejectedElement = new QName ();
  243. /** LSParserFilter: store qnames of skipped elements*/
  244. protected Stack fSkippedElemStack = null;
  245. /** LSParserFilter: true if inside entity reference */
  246. protected boolean fInEntityRef = false;
  247. /** Attribute QName. */
  248. private QName fAttrQName = new QName ();
  249. // handlers
  250. protected LSParserFilter fDOMFilter = null;
  251. //
  252. // Constructors
  253. //
  254. /** Default constructor. */
  255. protected AbstractDOMParser (XMLParserConfiguration config) {
  256. super (config);
  257. // add recognized features
  258. fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);
  259. // set default values
  260. fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, true);
  261. fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, true);
  262. fConfiguration.setFeature (DEFER_NODE_EXPANSION, true);
  263. fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, true);
  264. fConfiguration.setFeature (CREATE_CDATA_NODES_FEATURE, true);
  265. // add recognized properties
  266. fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);
  267. // set default values
  268. fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
  269. DEFAULT_DOCUMENT_CLASS_NAME);
  270. } // <init>(XMLParserConfiguration)
  271. /**
  272. * This method retreives the name of current document class.
  273. */
  274. protected String getDocumentClassName() {
  275. return fDocumentClassName;
  276. }
  277. /**
  278. * This method allows the programmer to decide which document
  279. * factory to use when constructing the DOM tree. However, doing
  280. * so will lose the functionality of the default factory. Also,
  281. * a document class other than the default will lose the ability
  282. * to defer node expansion on the DOM tree produced.
  283. *
  284. * @param documentClassName The fully qualified class name of the
  285. * document factory to use when constructing
  286. * the DOM tree.
  287. *
  288. * @see #getDocumentClassName
  289. * @see #DEFAULT_DOCUMENT_CLASS_NAME
  290. */
  291. protected void setDocumentClassName (String documentClassName) {
  292. // normalize class name
  293. if (documentClassName == null) {
  294. documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
  295. }
  296. if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME) &&
  297. !documentClassName.equals(PSVI_DOCUMENT_CLASS_NAME)) {
  298. // verify that this class exists and is of the right type
  299. try {
  300. Class _class = ObjectFactory.findProviderClass (documentClassName,
  301. ObjectFactory.findClassLoader (), true);
  302. //if (!_class.isAssignableFrom(Document.class)) {
  303. if (!Document.class.isAssignableFrom (_class)) {
  304. throw new IllegalArgumentException (
  305. DOMMessageFormatter.formatMessage(
  306. DOMMessageFormatter.DOM_DOMAIN,
  307. "InvalidDocumentClassName", new Object [] {documentClassName}));
  308. }
  309. }
  310. catch (ClassNotFoundException e) {
  311. throw new IllegalArgumentException (
  312. DOMMessageFormatter.formatMessage(
  313. DOMMessageFormatter.DOM_DOMAIN,
  314. "MissingDocumentClassName", new Object [] {documentClassName}));
  315. }
  316. }
  317. // set document class name
  318. fDocumentClassName = documentClassName;
  319. if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
  320. fDeferNodeExpansion = false;
  321. }
  322. } // setDocumentClassName(String)
  323. //
  324. // Public methods
  325. //
  326. /** Returns the DOM document object. */
  327. public Document getDocument() {
  328. return fDocument;
  329. } // getDocument():Document
  330. //
  331. // XMLDocumentParser methods
  332. //
  333. /**
  334. * Resets the parser state.
  335. *
  336. * @throws SAXException Thrown on initialization error.
  337. */
  338. public void reset () throws XNIException {
  339. super.reset ();
  340. // get feature state
  341. fCreateEntityRefNodes =
  342. fConfiguration.getFeature (CREATE_ENTITY_REF_NODES);
  343. fIncludeIgnorableWhitespace =
  344. fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE);
  345. fDeferNodeExpansion =
  346. fConfiguration.getFeature (DEFER_NODE_EXPANSION);
  347. fNamespaceAware = fConfiguration.getFeature (NAMESPACES);
  348. fIncludeComments = fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE);
  349. fCreateCDATANodes = fConfiguration.getFeature (CREATE_CDATA_NODES_FEATURE);
  350. // get property
  351. setDocumentClassName ((String)
  352. fConfiguration.getProperty (DOCUMENT_CLASS_NAME));
  353. // reset dom information
  354. fDocument = null;
  355. fDocumentImpl = null;
  356. fStorePSVI = false;
  357. fDocumentType = null;
  358. fDocumentTypeIndex = -1;
  359. fDeferredDocumentImpl = null;
  360. fCurrentNode = null;
  361. // reset string buffer
  362. fStringBuffer.setLength (0);
  363. // reset state information
  364. fRoot.clear();
  365. fInDTD = false;
  366. fInDTDExternalSubset = false;
  367. fInCDATASection = false;
  368. fFirstChunk = false;
  369. fCurrentCDATASection = null;
  370. fCurrentCDATASectionIndex = -1;
  371. fBaseURIStack.removeAllElements ();
  372. } // reset()
  373. /**
  374. * Set the locale to use for messages.
  375. *
  376. * @param locale The locale object to use for localization of messages.
  377. *
  378. */
  379. public void setLocale (Locale locale) {
  380. fConfiguration.setLocale (locale);
  381. } // setLocale(Locale)
  382. //
  383. // XMLDocumentHandler methods
  384. //
  385. /**
  386. * This method notifies the start of a general entity.
  387. * <p>
  388. * <strong>Note:</strong> This method is not called for entity references
  389. * appearing as part of attribute values.
  390. *
  391. * @param name The name of the general entity.
  392. * @param identifier The resource identifier.
  393. * @param encoding The auto-detected IANA encoding name of the entity
  394. * stream. This value will be null in those situations
  395. * where the entity encoding is not auto-detected (e.g.
  396. * internal entities or a document entity that is
  397. * parsed from a java.io.Reader).
  398. * @param augs Additional information that may include infoset augmentations
  399. *
  400. * @exception XNIException Thrown by handler to signal an error.
  401. */
  402. public void startGeneralEntity(String name,
  403. XMLResourceIdentifier identifier,
  404. String encoding, Augmentations augs)
  405. throws XNIException {
  406. if (DEBUG_EVENTS) {
  407. System.out.println("==>startGeneralEntity ("+name+")");
  408. if (DEBUG_BASEURI) {
  409. System.out.println(" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId());
  410. System.out.println(" baseURI:"+ identifier.getBaseSystemId());
  411. }
  412. }
  413. // Always create entity reference nodes to be able to recreate
  414. // entity as a part of doctype
  415. if (!fDeferNodeExpansion) {
  416. if (fFilterReject) {
  417. return;
  418. }
  419. setCharacterData(true);
  420. EntityReference er = fDocument.createEntityReference(name);
  421. if (fDocumentImpl != null) {
  422. // REVISIT: baseURI/actualEncoding
  423. // remove dependency on our implementation when DOM L3 is REC
  424. //
  425. EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
  426. // set base uri
  427. erImpl.setBaseURI(identifier.getExpandedSystemId());
  428. if (fDocumentType != null) {
  429. // set actual encoding
  430. NamedNodeMap entities = fDocumentType.getEntities();
  431. fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name);
  432. if (fCurrentEntityDecl != null) {
  433. fCurrentEntityDecl.setInputEncoding(encoding);
  434. }
  435. }
  436. // we don't need synchronization now, because entity ref will be
  437. // expanded anyway. Synch only needed when user creates entityRef node
  438. erImpl.needsSyncChildren(false);
  439. }
  440. fInEntityRef = true;
  441. fCurrentNode.appendChild (er);
  442. fCurrentNode = er;
  443. }
  444. else {
  445. int er =
  446. fDeferredDocumentImpl.createDeferredEntityReference(name, identifier.getExpandedSystemId());
  447. if (fDocumentTypeIndex != -1) {
  448. // find corresponding Entity decl
  449. int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
  450. while (node != -1) {
  451. short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
  452. if (nodeType == Node.ENTITY_NODE) {
  453. String nodeName =
  454. fDeferredDocumentImpl.getNodeName(node, false);
  455. if (nodeName.equals(name)) {
  456. fDeferredEntityDecl = node;
  457. fDeferredDocumentImpl.setInputEncoding(node, encoding);
  458. break;
  459. }
  460. }
  461. node = fDeferredDocumentImpl.getRealPrevSibling(node, false);
  462. }
  463. }
  464. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, er);
  465. fCurrentNodeIndex = er;
  466. }
  467. } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
  468. /**
  469. * Notifies of the presence of a TextDecl line in an entity. If present,
  470. * this method will be called immediately following the startEntity call.
  471. * <p>
  472. * <strong>Note:</strong> This method will never be called for the
  473. * document entity; it is only called for external general entities
  474. * referenced in document content.
  475. * <p>
  476. * <strong>Note:</strong> This method is not called for entity references
  477. * appearing as part of attribute values.
  478. *
  479. * @param version The XML version, or null if not specified.
  480. * @param encoding The IANA encoding name of the entity.
  481. * @param augs Additional information that may include infoset augmentations
  482. *
  483. * @throws XNIException Thrown by handler to signal an error.
  484. */
  485. public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
  486. if (fInDTD){
  487. return;
  488. }
  489. if (!fDeferNodeExpansion) {
  490. if (fCurrentEntityDecl != null && !fFilterReject) {
  491. fCurrentEntityDecl.setXmlEncoding(encoding);
  492. if(version != null)
  493. fCurrentEntityDecl.setXmlVersion(version);
  494. }
  495. }
  496. else {
  497. if (fDeferredEntityDecl !=-1) {
  498. fDeferredDocumentImpl.setEntityInfo(fDeferredEntityDecl, version, encoding);
  499. }
  500. }
  501. } // textDecl(String,String)
  502. /**
  503. * A comment.
  504. *
  505. * @param text The text in the comment.
  506. * @param augs Additional information that may include infoset augmentations
  507. *
  508. * @throws XNIException Thrown by application to signal an error.
  509. */
  510. public void comment(XMLString text, Augmentations augs) throws XNIException {
  511. if (fInDTD) {
  512. if (fInternalSubset != null && !fInDTDExternalSubset) {
  513. fInternalSubset.append("<!-- ");
  514. fInternalSubset.append(text.toString());
  515. fInternalSubset.append(" -->");
  516. }
  517. return;
  518. }
  519. if (!fIncludeComments || fFilterReject) {
  520. return;
  521. }
  522. if (!fDeferNodeExpansion) {
  523. Comment comment = fDocument.createComment (text.toString ());
  524. setCharacterData (false);
  525. fCurrentNode.appendChild (comment);
  526. if (fDOMFilter !=null && !fInEntityRef &&
  527. (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_COMMENT)!= 0) {
  528. short code = fDOMFilter.acceptNode (comment);
  529. switch (code) {
  530. case LSParserFilter.FILTER_INTERRUPT:{
  531. throw abort;
  532. }
  533. case LSParserFilter.FILTER_REJECT:{
  534. // REVISIT: the constant FILTER_REJECT should be changed when new
  535. // DOM LS specs gets published
  536. // fall through to SKIP since comment has no children.
  537. }
  538. case LSParserFilter.FILTER_SKIP: {
  539. // REVISIT: the constant FILTER_SKIP should be changed when new
  540. // DOM LS specs gets published
  541. fCurrentNode.removeChild(comment);
  542. // make sure we don't loose chars if next event is characters()
  543. fFirstChunk = true;
  544. return;
  545. }
  546. default: {
  547. // accept node
  548. }
  549. }
  550. }
  551. }
  552. else {
  553. int comment =
  554. fDeferredDocumentImpl.createDeferredComment(text.toString());
  555. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, comment);
  556. }
  557. } // comment(XMLString)
  558. /**
  559. * A processing instruction. Processing instructions consist of a
  560. * target name and, optionally, text data. The data is only meaningful
  561. * to the application.
  562. * <p>
  563. * Typically, a processing instruction's data will contain a series
  564. * of pseudo-attributes. These pseudo-attributes follow the form of
  565. * element attributes but are <strong>not</strong> parsed or presented
  566. * to the application as anything other than text. The application is
  567. * responsible for parsing the data.
  568. *
  569. * @param target The target.
  570. * @param data The data or null if none specified.
  571. * @param augs Additional information that may include infoset augmentations
  572. *
  573. * @throws XNIException Thrown by handler to signal an error.
  574. */
  575. public void processingInstruction (String target, XMLString data, Augmentations augs)
  576. throws XNIException {
  577. if (fInDTD) {
  578. if (fInternalSubset != null && !fInDTDExternalSubset) {
  579. fInternalSubset.append ("<?");
  580. fInternalSubset.append (target.toString ());
  581. fInternalSubset.append (' ');
  582. fInternalSubset.append (data.toString ());
  583. fInternalSubset.append ("?>");
  584. }
  585. return;
  586. }
  587. if (DEBUG_EVENTS) {
  588. System.out.println ("==>processingInstruction ("+target+")");
  589. }
  590. if (!fDeferNodeExpansion) {
  591. if (fFilterReject) {
  592. return;
  593. }
  594. ProcessingInstruction pi =
  595. fDocument.createProcessingInstruction (target, data.toString ());
  596. setCharacterData (false);
  597. fCurrentNode.appendChild (pi);
  598. if (fDOMFilter !=null && !fInEntityRef &&
  599. (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
  600. short code = fDOMFilter.acceptNode (pi);
  601. switch (code) {
  602. case LSParserFilter.FILTER_INTERRUPT:{
  603. throw abort;
  604. }
  605. case LSParserFilter.FILTER_REJECT:{
  606. // fall through to SKIP since PI has no children.
  607. }
  608. case LSParserFilter.FILTER_SKIP: {
  609. fCurrentNode.removeChild(pi);
  610. // fFirstChunk must be set to true so that data
  611. // won't be lost in the case where the child before PI is
  612. // a text node and the next event is characters.
  613. fFirstChunk = true;
  614. return;
  615. }
  616. default: {
  617. }
  618. }
  619. }
  620. }
  621. else {
  622. int pi = fDeferredDocumentImpl.
  623. createDeferredProcessingInstruction(target, data.toString());
  624. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
  625. }
  626. } // processingInstruction(String,XMLString)
  627. /**
  628. * The start of the document.
  629. *
  630. * @param locator The system identifier of the entity if the entity
  631. * is external, null otherwise.
  632. * @param encoding The auto-detected IANA encoding name of the entity
  633. * stream. This value will be null in those situations
  634. * where the entity encoding is not auto-detected (e.g.
  635. * internal entities or a document entity that is
  636. * parsed from a java.io.Reader).
  637. * @param namespaceContext
  638. * The namespace context in effect at the
  639. * start of this document.
  640. * This object represents the current context.
  641. * Implementors of this class are responsible
  642. * for copying the namespace bindings from the
  643. * the current context (and its parent contexts)
  644. * if that information is important.
  645. * @param augs Additional information that may include infoset augmentations
  646. *
  647. * @throws XNIException Thrown by handler to signal an error.
  648. */
  649. public void startDocument (XMLLocator locator, String encoding,
  650. NamespaceContext namespaceContext, Augmentations augs)
  651. throws XNIException {
  652. if (!fDeferNodeExpansion) {
  653. if (fDocumentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
  654. fDocument = new DocumentImpl ();
  655. fDocumentImpl = (CoreDocumentImpl)fDocument;
  656. // REVISIT: when DOM Level 3 is REC rely on Document.support
  657. // instead of specific class
  658. // set DOM error checking off
  659. fDocumentImpl.setStrictErrorChecking (false);
  660. // set actual encoding
  661. fDocumentImpl.setInputEncoding (encoding);
  662. // set documentURI
  663. fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
  664. }
  665. else if (fDocumentClassName.equals (PSVI_DOCUMENT_CLASS_NAME)) {
  666. fDocument = new PSVIDocumentImpl();
  667. fDocumentImpl = (CoreDocumentImpl)fDocument;
  668. fStorePSVI = true;
  669. // REVISIT: when DOM Level 3 is REC rely on Document.support
  670. // instead of specific class
  671. // set DOM error checking off
  672. fDocumentImpl.setStrictErrorChecking (false);
  673. // set actual encoding
  674. fDocumentImpl.setInputEncoding (encoding);
  675. // set documentURI
  676. fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
  677. }
  678. else {
  679. // use specified document class
  680. try {
  681. ClassLoader cl = ObjectFactory.findClassLoader();
  682. Class documentClass = ObjectFactory.findProviderClass (fDocumentClassName,
  683. cl, true);
  684. fDocument = (Document)documentClass.newInstance ();
  685. // if subclass of our own class that's cool too
  686. Class defaultDocClass =
  687. ObjectFactory.findProviderClass (CORE_DOCUMENT_CLASS_NAME,
  688. cl, true);
  689. if (defaultDocClass.isAssignableFrom (documentClass)) {
  690. fDocumentImpl = (CoreDocumentImpl)fDocument;
  691. Class psviDocClass = ObjectFactory.findProviderClass (PSVI_DOCUMENT_CLASS_NAME,
  692. cl, true);
  693. if (psviDocClass.isAssignableFrom (documentClass)) {
  694. fStorePSVI = true;
  695. }
  696. // REVISIT: when DOM Level 3 is REC rely on
  697. // Document.support instead of specific class
  698. // set DOM error checking off
  699. fDocumentImpl.setStrictErrorChecking(false);
  700. // set actual encoding
  701. fDocumentImpl.setInputEncoding(encoding);
  702. // set documentURI
  703. if (locator != null) {
  704. fDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
  705. }
  706. }
  707. }
  708. catch (ClassNotFoundException e) {
  709. // won't happen we already checked that earlier
  710. }
  711. catch (Exception e) {
  712. throw new RuntimeException (
  713. DOMMessageFormatter.formatMessage(
  714. DOMMessageFormatter.DOM_DOMAIN,
  715. "CannotCreateDocumentClass",
  716. new Object [] {fDocumentClassName}));
  717. }
  718. }
  719. fCurrentNode = fDocument;
  720. }
  721. else {
  722. fDeferredDocumentImpl = new DeferredDocumentImpl(fNamespaceAware);
  723. fDocument = fDeferredDocumentImpl;
  724. fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument();
  725. // REVISIT: strict error checking is not implemented in deferred dom.
  726. // Document.support instead of specific class
  727. // set actual encoding
  728. fDeferredDocumentImpl.setInputEncoding(encoding);
  729. // set documentURI
  730. fDeferredDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
  731. fCurrentNodeIndex = fDocumentIndex;
  732. }
  733. } // startDocument(String,String)
  734. /**
  735. * Notifies of the presence of an XMLDecl line in the document. If
  736. * present, this method will be called immediately following the
  737. * startDocument call.
  738. *
  739. * @param version The XML version.
  740. * @param encoding The IANA encoding name of the document, or null if
  741. * not specified.
  742. * @param standalone The standalone value, or null if not specified.
  743. * @param augs Additional information that may include infoset augmentations
  744. *
  745. * @throws XNIException Thrown by handler to signal an error.
  746. */
  747. public void xmlDecl(String version, String encoding, String standalone,
  748. Augmentations augs)
  749. throws XNIException {
  750. if (!fDeferNodeExpansion) {
  751. // REVISIT: when DOM Level 3 is REC rely on Document.support
  752. // instead of specific class
  753. if (fDocumentImpl != null) {
  754. if(version != null)
  755. fDocumentImpl.setXmlVersion(version);
  756. fDocumentImpl.setXmlEncoding(encoding);
  757. fDocumentImpl.setXmlStandalone("yes".equals(standalone));
  758. }
  759. }
  760. else {
  761. if(version != null)
  762. fDeferredDocumentImpl.setXmlVersion(version);
  763. fDeferredDocumentImpl.setXmlEncoding(encoding);
  764. fDeferredDocumentImpl.setXmlStandalone("yes".equals(standalone));
  765. }
  766. } // xmlDecl(String,String,String)
  767. /**
  768. * Notifies of the presence of the DOCTYPE line in the document.
  769. *
  770. * @param rootElement The name of the root element.
  771. * @param publicId The public identifier if an external DTD or null
  772. * if the external DTD is specified using SYSTEM.
  773. * @param systemId The system identifier if an external DTD, null
  774. * otherwise.
  775. * @param augs Additional information that may include infoset augmentations
  776. *
  777. * @throws XNIException Thrown by handler to signal an error.
  778. */
  779. public void doctypeDecl (String rootElement,
  780. String publicId, String systemId, Augmentations augs)
  781. throws XNIException {
  782. if (!fDeferNodeExpansion) {
  783. if (fDocumentImpl != null) {
  784. fDocumentType = fDocumentImpl.createDocumentType(
  785. rootElement, publicId, systemId);
  786. fCurrentNode.appendChild(fDocumentType);
  787. }
  788. }
  789. else {
  790. fDocumentTypeIndex = fDeferredDocumentImpl.
  791. createDeferredDocumentType(rootElement, publicId, systemId);
  792. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, fDocumentTypeIndex);
  793. }
  794. } // doctypeDecl(String,String,String)
  795. /**
  796. * The start of an element. If the document specifies the start element
  797. * by using an empty tag, then the startElement method will immediately
  798. * be followed by the endElement method, with no intervening methods.
  799. *
  800. * @param element The name of the element.
  801. * @param attributes The element attributes.
  802. * @param augs Additional information that may include infoset augmentations
  803. *
  804. * @throws XNIException Thrown by handler to signal an error.
  805. */
  806. public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
  807. throws XNIException {
  808. if (DEBUG_EVENTS) {
  809. System.out.println("==>startElement ("+element.rawname+")");
  810. }
  811. if (!fDeferNodeExpansion) {
  812. if (fFilterReject) {
  813. return;
  814. }
  815. Element el = createElementNode(element);
  816. int attrCount = attributes.getLength();
  817. for (int i = 0; i < attrCount; i++) {
  818. attributes.getName (i, fAttrQName);
  819. Attr attr = createAttrNode (fAttrQName);
  820. String attrValue = attributes.getValue (i);
  821. Augmentations aaugs = attributes.getAugmentations(i);
  822. AttributePSVI attrPSVI =(AttributePSVI) aaugs.getItem(Constants.ATTRIBUTE_PSVI);
  823. if (fStorePSVI && attrPSVI != null){
  824. ((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
  825. }
  826. attr.setValue(attrValue);
  827. el.setAttributeNode(attr);
  828. // NOTE: The specified value MUST be set after you set
  829. // the node value because that turns the "specified"
  830. // flag to "true" which may overwrite a "false"
  831. // value from the attribute list. -Ac
  832. if (fDocumentImpl != null) {
  833. AttrImpl attrImpl = (AttrImpl)attr;
  834. attrImpl.setType(getAttributeType(attributes,aaugs,i));
  835. if (isIdAttribute(attributes,aaugs,i)) {
  836. ((ElementImpl)el).setIdAttributeNode(attr, true);
  837. }
  838. attrImpl.setSpecified(attributes.isSpecified(i));
  839. // REVISIT: Handle entities in attribute value.
  840. }
  841. }
  842. setCharacterData (false);
  843. ((ElementImpl)el).setType(getElementTypeInfoFromAugs(augs));
  844. // filter nodes
  845. if (fDOMFilter != null && !fInEntityRef) {
  846. if (fRoot.rawname == null) {
  847. // fill value of the root element
  848. fRoot.setValues(element);
  849. } else {
  850. short code = fDOMFilter.startElement(el);
  851. switch (code) {
  852. case LSParserFilter.FILTER_INTERRUPT :
  853. {
  854. throw abort;
  855. }
  856. case LSParserFilter.FILTER_REJECT :
  857. {
  858. fFilterReject = true;
  859. fRejectedElement.setValues(element);
  860. return;
  861. }
  862. case LSParserFilter.FILTER_SKIP :
  863. {
  864. fSkippedElemStack.push(new QName(element));
  865. return;
  866. }
  867. default : {}
  868. }
  869. }
  870. }
  871. fCurrentNode.appendChild (el);
  872. fCurrentNode = el;
  873. }
  874. else {
  875. int el =
  876. fDeferredDocumentImpl.createDeferredElement(fNamespaceAware ?
  877. element.uri : null,
  878. element.rawname,
  879. getElementTypeInfoFromAugs(augs));
  880. int attrCount = attributes.getLength();
  881. for (int i = 0; i < attrCount; i++) {
  882. // set type information
  883. Augmentations aaugs = attributes.getAugmentations(i);
  884. // create attribute
  885. fDeferredDocumentImpl.setDeferredAttribute(
  886. el,
  887. attributes.getQName(i),
  888. attributes.getURI(i),
  889. attributes.getValue(i),
  890. attributes.isSpecified(i),
  891. isIdAttribute(attributes,aaugs,i),
  892. getAttributeType(attributes,aaugs,i));
  893. }
  894. fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
  895. fCurrentNodeIndex = el;
  896. }
  897. } // startElement(QName,XMLAttributes)
  898. /**
  899. * Returns true if the given attribute is marked as ID.
  900. */
  901. private boolean isIdAttribute(XMLAttributes attributes,Augmentations augs, int index) {
  902. // look for augmentation first.
  903. Object o = augs.getItem(Constants.ID_ATTRIBUTE);
  904. if( o instanceof Boolean )
  905. return ((Boolean)o).booleanValue();
  906. // otherwise fall back to the DTD mode.
  907. return "ID".equals(attributes.getType(index));
  908. }
  909. /**
  910. * Returns {@link TypeInfo} for the given attribute.
  911. */
  912. private TypeInfo getAttributeType(XMLAttributes attributes,Augmentations augs, int index) {
  913. // look for augmentation
  914. TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
  915. if(type!=null) return type;
  916. boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (index).getItem (Constants.ATTRIBUTE_DECLARED));
  917. // otherwise fall back to the DTD mode.
  918. if (isDeclared )
  919. return TypeInfoImpl.getDTDTypeInfo(attributes.getType(index));
  920. else
  921. return new TypeInfoImpl();
  922. }
  923. /**
  924. * Looks for {@link TypeInfo} object for the element in the augmentation.
  925. *
  926. * @return null if not found.
  927. */
  928. private TypeInfo getElementTypeInfoFromAugs( Augmentations augs ) {
  929. //simple fix to handle dtd case.
  930. if (augs == null) return new TypeInfoImpl();
  931. // if an external validator is used via JAXP, this would be set.
  932. TypeInfo ti = (TypeInfo)augs.getItem(Constants.TYPEINFO);
  933. if(ti!=null) return ti;
  934. // Xerces native validator would set this.
  935. ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
  936. if (elementPSVI == null) return null;
  937. XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
  938. if( type!=null ) return type;
  939. return elementPSVI.getTypeDefinition();
  940. }
  941. // /**
  942. // * Looks for {@link TypeInfo} object for the attribute in the augmentation.
  943. // */
  944. // private TypeInfo getAttribtueTypeInfoFromAugs( XMLAttributes atts, int idx ) {
  945. // Augmentations augs = atts.getAugmentations(idx);
  946. //
  947. // // if an external validator is used via JAXP, this would be set.
  948. // TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
  949. // if(type!=null) return type;
  950. //
  951. // // look for PSVI
  952. // AttributePSVI attrPSVI =(AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
  953. // if (attrPSVI != null) {
  954. // type = attrPSVI.getMemberTypeDefinition();
  955. // if (type == null)
  956. // type = attrPSVI.getTypeDefinition();
  957. //
  958. // return type;
  959. // }
  960. //
  961. // // if everything else fails, fall back to the DTD type.
  962. // String typeName = atts.getType(idx);
  963. // return new TypeInfoImpl(null, typeName);
  964. // }
  965. /**
  966. * An empty element.
  967. *
  968. * @param element The name of the element.
  969. * @param attributes The element attributes.
  970. * @param augs Additional information that may include infoset augmentations
  971. *
  972. * @throws XNIException Thrown by handler to signal an error.
  973. */
  974. public void emptyElement (QName element, XMLAttributes attributes, Augmentations augs)
  975. throws XNIException {
  976. startElement (element, attributes, augs);
  977. endElement (element, augs);
  978. } // emptyElement(QName,XMLAttributes)
  979. /**
  980. * Character content.
  981. *
  982. * @param text The content.
  983. * @param augs Additional information that may include infoset augmentations
  984. *
  985. * @throws XNIException Thrown by handler to signal an error.
  986. */
  987. public void characters (XMLString text, Augmentations augs) throws XNIException {
  988. if (DEBUG_EVENTS) {
  989. System.out.println("==>characters(): "+text.toString());
  990. }
  991. if (!fDeferNodeExpansion) {
  992. if (fFilterReject) {
  993. return;
  994. }
  995. if (fInCDATASection && fCreateCDATANodes) {
  996. if (fCurrentCDATASection == null) {
  997. fCurrentCDATASection =
  998. fDocument.createCDATASection(text.toString());
  999. fCurrentNode.appendChild(fCurrentCDATASection);
  1000. fCurrentNode = fCurrentCDATASection;
  1001. }
  1002. else {
  1003. fCurrentCDATASection.appendData(text.toString());
  1004. }
  1005. }
  1006. else if (!fInDTD) {
  1007. // if type is union (XML Schema) it is possible that we receive
  1008. // character call with empty data
  1009. if (text.length == 0) {
  1010. return;
  1011. }
  1012. String value = text.toString ();
  1013. Node child = fCurrentNode.getLastChild ();
  1014. if (child != null && child.getNodeType () == Node.TEXT_NODE) {
  1015. // collect all the data into the string buffer.
  1016. if (fFirstChunk) {
  1017. if (fDocumentImpl != null) {
  1018. fStringBuffer.append(((TextImpl)child).removeData());
  1019. } else {
  1020. fStringBuffer.append(((Text)child).getData());
  1021. ((Text)child).setNodeValue(null);
  1022. }
  1023. fFirstChunk = false;
  1024. }
  1025. fStringBuffer.append(value);
  1026. }
  1027. else {
  1028. fFirstChunk = true;
  1029. Text textNode = fDocument.createTextNode(value);
  1030. fCurrentNode.appendChild(textNode);
  1031. }
  1032. }
  1033. }
  1034. else {
  1035. // The Text and CDATASection normalization is taken care of within
  1036. // the DOM in the deferred case.
  1037. if (fInCDATASection && fCreateCDATANodes) {
  1038. if (fCurrentCDATASectionIndex == -1) {
  1039. int cs = fDeferredDocumentImpl.
  1040. createDeferredCDATASection (text.toString ());
  1041. fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, cs);
  1042. fCurrentCDATASectionIndex = cs;
  1043. fCurrentNodeIndex = cs;
  1044. }
  1045. else {
  1046. int txt = fDeferredDocumentImpl.
  1047. createDeferredTextNode(text.toString(), false);
  1048. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
  1049. }
  1050. } else if (!fInDTD) {
  1051. // if type is union (XML Schema) it is possible that we receive
  1052. // character call with empty data
  1053. if (text.length == 0) {
  1054. return;
  1055. }
  1056. String value = text.toString ();
  1057. int txt = fDeferredDocumentImpl.
  1058. createDeferredTextNode (value, false);
  1059. fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
  1060. }
  1061. }
  1062. } // characters(XMLString)
  1063. /**
  1064. * Ignorable whitespace. For this method to be called, the document
  1065. * source must have some way of determining that the text containing
  1066. * only whitespace characters should be considered ignorable. For
  1067. * example, the validator can determine if a length of whitespace
  1068. * characters in the document are ignorable based on the element
  1069. * content model.
  1070. *
  1071. * @param text The ignorable whitespace.
  1072. * @param augs Additional information that may include infoset augmentations
  1073. *
  1074. * @throws XNIException Thrown by handler to signal an error.
  1075. */
  1076. public void ignorableWhitespace (XMLString text, Augmentations augs) throws XNIException {
  1077. if (!fIncludeIgnorableWhitespace || fFilterReject) {
  1078. return;
  1079. }
  1080. if (!fDeferNodeExpansion) {
  1081. Node child = fCurrentNode.getLastChild();
  1082. if (child != null && child.getNodeType() == Node.TEXT_NODE) {
  1083. Text textNode = (Text)child;
  1084. textNode.appendData(text.toString());
  1085. }
  1086. else {
  1087. Text textNode = fDocument.createTextNode(text.toString());
  1088. if (fDocumentImpl != null) {
  1089. TextImpl textNodeImpl = (TextImpl)textNode;
  1090. textNodeImpl.setIgnorableWhitespace(true);
  1091. }
  1092. fCurrentNode.appendChild(textNode);
  1093. }
  1094. }
  1095. else {
  1096. // The Text normalization is taken care of within the DOM in the
  1097. // deferred case.
  1098. int txt = fDeferredDocumentImpl.
  1099. createDeferredTextNode(text.toString(), true);
  1100. fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
  1101. }
  1102. } // ignorableWhitespace(XMLString)
  1103. /**
  1104. * The end of an element.
  1105. *
  1106. * @param element The name of the element.
  1107. * @param augs Additional information that may include infoset augmentations
  1108. *
  1109. * @throws XNIException Thrown by handler to signal an error.
  1110. */
  1111. public void endElement(QName element, Augmentations augs) throws XNIException {
  1112. if (DEBUG_EVENTS) {
  1113. System.out.println("==>endElement ("+element.rawname+")");
  1114. }
  1115. if (!fDeferNodeExpansion) {
  1116. // REVISIT: Should this happen after we call the filter?
  1117. if (fStorePSVI && augs != null) {
  1118. ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
  1119. if (elementPSVI != null) {
  1120. ((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI);
  1121. }
  1122. }
  1123. if (fDOMFilter != null) {
  1124. if (fFilterReject) {
  1125. if (element.equals(fRejectedElement)) {
  1126. fFilterReject = false;
  1127. }
  1128. return;
  1129. }
  1130. if (!fSkippedElemStack.isEmpty()) {
  1131. if (fSkippedElemStack.peek().equals(element)) {
  1132. fSkippedElemStack.pop();
  1133. return;
  1134. }
  1135. }
  1136. setCharacterData (false);
  1137. if (!fRoot.equals(element) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
  1138. short code = fDOMFilter.acceptNode (fCurrentNode);
  1139. switch (code) {
  1140. case LSParserFilter.FILTER_INTERRUPT:{
  1141. throw abort;
  1142. }
  1143. case LSParserFilter.FILTER_REJECT:{
  1144. Node parent = fCurrentNode.getParentNode();
  1145. parent.removeChild(fCurrentNode);
  1146. fCurrentNode = parent;
  1147. return;
  1148. }
  1149. case LSParserFilter.FILTER_SKIP: {
  1150. // make sure that if any char data is available
  1151. // the fFirstChunk is true, so that if the next event
  1152. // is characters(), and the last node is text, we will copy
  1153. // the value already in the text node to fStringBuffer
  1154. // (not to loose it).
  1155. fFirstChunk = true;
  1156. // replace children
  1157. Node parent = fCurrentNode.getParentNode ();
  1158. NodeList ls = fCurrentNode.getChildNodes ();
  1159. int