0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.parsers;
0019:
0020: import java.util.Locale;
0021: import java.util.Stack;
0022:
0023: import org.apache.xerces.dom.AttrImpl;
0024: import org.apache.xerces.dom.CoreDocumentImpl;
0025: import org.apache.xerces.dom.DOMErrorImpl;
0026: import org.apache.xerces.dom.DOMMessageFormatter;
0027: import org.apache.xerces.dom.DeferredDocumentImpl;
0028: import org.apache.xerces.dom.DocumentImpl;
0029: import org.apache.xerces.dom.DocumentTypeImpl;
0030: import org.apache.xerces.dom.ElementDefinitionImpl;
0031: import org.apache.xerces.dom.ElementImpl;
0032: import org.apache.xerces.dom.ElementNSImpl;
0033: import org.apache.xerces.dom.EntityImpl;
0034: import org.apache.xerces.dom.EntityReferenceImpl;
0035: import org.apache.xerces.dom.NodeImpl;
0036: import org.apache.xerces.dom.NotationImpl;
0037: import org.apache.xerces.dom.PSVIAttrNSImpl;
0038: import org.apache.xerces.dom.PSVIDocumentImpl;
0039: import org.apache.xerces.dom.PSVIElementNSImpl;
0040: import org.apache.xerces.dom.TextImpl;
0041: import org.apache.xerces.impl.Constants;
0042: import org.apache.xerces.impl.dv.XSSimpleType;
0043: import org.apache.xerces.util.DOMErrorHandlerWrapper;
0044: import org.apache.xerces.xni.Augmentations;
0045: import org.apache.xerces.xni.NamespaceContext;
0046: import org.apache.xerces.xni.QName;
0047: import org.apache.xerces.xni.XMLAttributes;
0048: import org.apache.xerces.xni.XMLLocator;
0049: import org.apache.xerces.xni.XMLResourceIdentifier;
0050: import org.apache.xerces.xni.XMLString;
0051: import org.apache.xerces.xni.XNIException;
0052: import org.apache.xerces.xni.parser.XMLParserConfiguration;
0053: import org.apache.xerces.xs.AttributePSVI;
0054: import org.apache.xerces.xs.ElementPSVI;
0055: import org.apache.xerces.xs.XSTypeDefinition;
0056: import org.w3c.dom.Attr;
0057: import org.w3c.dom.CDATASection;
0058: import org.w3c.dom.Comment;
0059: import org.w3c.dom.Document;
0060: import org.w3c.dom.DocumentType;
0061: import org.w3c.dom.DOMError;
0062: import org.w3c.dom.Element;
0063: import org.w3c.dom.EntityReference;
0064: import org.w3c.dom.NamedNodeMap;
0065: import org.w3c.dom.Node;
0066: import org.w3c.dom.NodeList;
0067: import org.w3c.dom.ProcessingInstruction;
0068: import org.w3c.dom.Text;
0069: import org.w3c.dom.ls.LSParserFilter;
0070: import org.w3c.dom.traversal.NodeFilter;
0071: import org.xml.sax.SAXException;
0072:
0073: /**
0074: * This is the base class of all DOM parsers. It implements the XNI
0075: * callback methods to create the DOM tree. After a successful parse of
0076: * an XML document, the DOM Document object can be queried using the
0077: * <code>getDocument</code> method. The actual pipeline is defined in
0078: * parser configuration.
0079: *
0080: * @author Arnaud Le Hors, IBM
0081: * @author Andy Clark, IBM
0082: * @author Elena Litani, IBM
0083: *
0084: * @version $Id: AbstractDOMParser.java 568412 2007-08-22 04:40:44Z mrglavas $
0085: */
0086: public class AbstractDOMParser extends AbstractXMLDocumentParser {
0087:
0088: //
0089: // Constants
0090: //
0091:
0092: // feature ids
0093:
0094: /** Feature id: namespace. */
0095: protected static final String NAMESPACES = Constants.SAX_FEATURE_PREFIX
0096: + Constants.NAMESPACES_FEATURE;
0097:
0098: /** Feature id: create entity ref nodes. */
0099: protected static final String CREATE_ENTITY_REF_NODES = Constants.XERCES_FEATURE_PREFIX
0100: + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
0101:
0102: /** Feature id: include comments. */
0103: protected static final String INCLUDE_COMMENTS_FEATURE = Constants.XERCES_FEATURE_PREFIX
0104: + Constants.INCLUDE_COMMENTS_FEATURE;
0105:
0106: /** Feature id: create cdata nodes. */
0107: protected static final String CREATE_CDATA_NODES_FEATURE = Constants.XERCES_FEATURE_PREFIX
0108: + Constants.CREATE_CDATA_NODES_FEATURE;
0109:
0110: /** Feature id: include ignorable whitespace. */
0111: protected static final String INCLUDE_IGNORABLE_WHITESPACE = Constants.XERCES_FEATURE_PREFIX
0112: + Constants.INCLUDE_IGNORABLE_WHITESPACE;
0113:
0114: /** Feature id: defer node expansion. */
0115: protected static final String DEFER_NODE_EXPANSION = Constants.XERCES_FEATURE_PREFIX
0116: + Constants.DEFER_NODE_EXPANSION_FEATURE;
0117:
0118: /** Recognized features. */
0119: private static final String[] RECOGNIZED_FEATURES = { NAMESPACES,
0120: CREATE_ENTITY_REF_NODES, INCLUDE_COMMENTS_FEATURE,
0121: CREATE_CDATA_NODES_FEATURE, INCLUDE_IGNORABLE_WHITESPACE,
0122: DEFER_NODE_EXPANSION };
0123:
0124: // property ids
0125:
0126: /** Property id: document class name. */
0127: protected static final String DOCUMENT_CLASS_NAME = Constants.XERCES_PROPERTY_PREFIX
0128: + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
0129:
0130: protected static final String CURRENT_ELEMENT_NODE = Constants.XERCES_PROPERTY_PREFIX
0131: + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
0132:
0133: // protected static final String GRAMMAR_POOL =
0134: // Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
0135:
0136: /** Recognized properties. */
0137: private static final String[] RECOGNIZED_PROPERTIES = {
0138: DOCUMENT_CLASS_NAME, CURRENT_ELEMENT_NODE, };
0139:
0140: // other
0141:
0142: /** Default document class name. */
0143: protected static final String DEFAULT_DOCUMENT_CLASS_NAME = "org.apache.xerces.dom.DocumentImpl";
0144:
0145: protected static final String CORE_DOCUMENT_CLASS_NAME = "org.apache.xerces.dom.CoreDocumentImpl";
0146:
0147: protected static final String PSVI_DOCUMENT_CLASS_NAME = "org.apache.xerces.dom.PSVIDocumentImpl";
0148:
0149: /**
0150: * If the user stops the process, this exception will be thrown.
0151: */
0152: protected static final RuntimeException ABORT = new RuntimeException() {
0153: private static final long serialVersionUID = 1687848994976808490L;
0154:
0155: public Throwable fillInStackTrace() {
0156: return this ;
0157: }
0158: };
0159:
0160: // debugging
0161:
0162: private static final boolean DEBUG_EVENTS = false;
0163: private static final boolean DEBUG_BASEURI = false;
0164:
0165: //
0166: // Data
0167: //
0168:
0169: /** DOM L3 error handler */
0170: protected DOMErrorHandlerWrapper fErrorHandler = null;
0171:
0172: /** True if inside DTD. */
0173: protected boolean fInDTD;
0174:
0175: // features
0176:
0177: /** Create entity reference nodes. */
0178: protected boolean fCreateEntityRefNodes;
0179:
0180: /** Include ignorable whitespace. */
0181: protected boolean fIncludeIgnorableWhitespace;
0182:
0183: /** Include Comments. */
0184: protected boolean fIncludeComments;
0185:
0186: /** Create cdata nodes. */
0187: protected boolean fCreateCDATANodes;
0188:
0189: // dom information
0190:
0191: /** The document. */
0192: protected Document fDocument;
0193:
0194: /** The default Xerces document implementation, if used. */
0195: protected CoreDocumentImpl fDocumentImpl;
0196:
0197: /** Whether to store PSVI information in DOM tree. */
0198: protected boolean fStorePSVI;
0199:
0200: /** The document class name to use. */
0201: protected String fDocumentClassName;
0202:
0203: /** The document type node. */
0204: protected DocumentType fDocumentType;
0205:
0206: /** Current node. */
0207: protected Node fCurrentNode;
0208: protected CDATASection fCurrentCDATASection;
0209: protected EntityImpl fCurrentEntityDecl;
0210: protected int fDeferredEntityDecl;
0211:
0212: /** Character buffer */
0213: protected final StringBuffer fStringBuffer = new StringBuffer(50);
0214:
0215: // internal subset
0216:
0217: /** Internal subset buffer. */
0218: protected StringBuffer fInternalSubset;
0219:
0220: // deferred expansion data
0221:
0222: protected boolean fDeferNodeExpansion;
0223: protected boolean fNamespaceAware;
0224: protected DeferredDocumentImpl fDeferredDocumentImpl;
0225: protected int fDocumentIndex;
0226: protected int fDocumentTypeIndex;
0227: protected int fCurrentNodeIndex;
0228: protected int fCurrentCDATASectionIndex;
0229:
0230: // state
0231:
0232: /** True if inside DTD external subset. */
0233: protected boolean fInDTDExternalSubset;
0234:
0235: /** Root element name */
0236: protected QName fRoot = new QName();
0237:
0238: /** True if inside CDATA section. */
0239: protected boolean fInCDATASection;
0240:
0241: /** True if saw the first chunk of characters*/
0242: protected boolean fFirstChunk = false;
0243:
0244: /** LSParserFilter: specifies that element with given QNAME and all its children
0245: * must be rejected */
0246: protected boolean fFilterReject = false;
0247:
0248: // data
0249:
0250: /** Base uri stack*/
0251: protected Stack fBaseURIStack = new Stack();
0252:
0253: /** LSParserFilter: the QNAME of rejected element*/
0254: protected final QName fRejectedElement = new QName();
0255:
0256: /** LSParserFilter: store qnames of skipped elements*/
0257: protected Stack fSkippedElemStack = null;
0258:
0259: /** LSParserFilter: true if inside entity reference */
0260: protected boolean fInEntityRef = false;
0261:
0262: /** Attribute QName. */
0263: private QName fAttrQName = new QName();
0264:
0265: /** Document locator. */
0266: private XMLLocator fLocator;
0267:
0268: // handlers
0269:
0270: protected LSParserFilter fDOMFilter = null;
0271:
0272: //
0273: // Constructors
0274: //
0275:
0276: /** Default constructor. */
0277: protected AbstractDOMParser(XMLParserConfiguration config) {
0278:
0279: super (config);
0280:
0281: // add recognized features
0282: fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES);
0283:
0284: // set default values
0285: fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, true);
0286: fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
0287: fConfiguration.setFeature(DEFER_NODE_EXPANSION, true);
0288: fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
0289: fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, true);
0290:
0291: // add recognized properties
0292: fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);
0293:
0294: // set default values
0295: fConfiguration.setProperty(DOCUMENT_CLASS_NAME,
0296: DEFAULT_DOCUMENT_CLASS_NAME);
0297:
0298: } // <init>(XMLParserConfiguration)
0299:
0300: /**
0301: * This method retreives the name of current document class.
0302: */
0303: protected String getDocumentClassName() {
0304: return fDocumentClassName;
0305: }
0306:
0307: /**
0308: * This method allows the programmer to decide which document
0309: * factory to use when constructing the DOM tree. However, doing
0310: * so will lose the functionality of the default factory. Also,
0311: * a document class other than the default will lose the ability
0312: * to defer node expansion on the DOM tree produced.
0313: *
0314: * @param documentClassName The fully qualified class name of the
0315: * document factory to use when constructing
0316: * the DOM tree.
0317: *
0318: * @see #getDocumentClassName
0319: * @see #DEFAULT_DOCUMENT_CLASS_NAME
0320: */
0321: protected void setDocumentClassName(String documentClassName) {
0322:
0323: // normalize class name
0324: if (documentClassName == null) {
0325: documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
0326: }
0327:
0328: if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)
0329: && !documentClassName.equals(PSVI_DOCUMENT_CLASS_NAME)) {
0330: // verify that this class exists and is of the right type
0331: try {
0332: Class _class = ObjectFactory.findProviderClass(
0333: documentClassName, ObjectFactory
0334: .findClassLoader(), true);
0335: //if (!_class.isAssignableFrom(Document.class)) {
0336: if (!Document.class.isAssignableFrom(_class)) {
0337: throw new IllegalArgumentException(
0338: DOMMessageFormatter.formatMessage(
0339: DOMMessageFormatter.DOM_DOMAIN,
0340: "InvalidDocumentClassName",
0341: new Object[] { documentClassName }));
0342: }
0343: } catch (ClassNotFoundException e) {
0344: throw new IllegalArgumentException(DOMMessageFormatter
0345: .formatMessage(DOMMessageFormatter.DOM_DOMAIN,
0346: "MissingDocumentClassName",
0347: new Object[] { documentClassName }));
0348: }
0349: }
0350:
0351: // set document class name
0352: fDocumentClassName = documentClassName;
0353: if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
0354: fDeferNodeExpansion = false;
0355: }
0356:
0357: } // setDocumentClassName(String)
0358:
0359: //
0360: // Public methods
0361: //
0362:
0363: /** Returns the DOM document object. */
0364: public Document getDocument() {
0365: return fDocument;
0366: } // getDocument():Document
0367:
0368: /**
0369: * Drops all references to the last DOM which was built by this parser.
0370: */
0371: public final void dropDocumentReferences() {
0372: fDocument = null;
0373: fDocumentImpl = null;
0374: fDeferredDocumentImpl = null;
0375: fDocumentType = null;
0376: fCurrentNode = null;
0377: fCurrentCDATASection = null;
0378: fCurrentEntityDecl = null;
0379: } // dropDocumentReferences()
0380:
0381: //
0382: // XMLDocumentParser methods
0383: //
0384:
0385: /**
0386: * Resets the parser state.
0387: *
0388: * @throws SAXException Thrown on initialization error.
0389: */
0390: public void reset() throws XNIException {
0391: super .reset();
0392:
0393: // get feature state
0394: fCreateEntityRefNodes = fConfiguration
0395: .getFeature(CREATE_ENTITY_REF_NODES);
0396:
0397: fIncludeIgnorableWhitespace = fConfiguration
0398: .getFeature(INCLUDE_IGNORABLE_WHITESPACE);
0399:
0400: fDeferNodeExpansion = fConfiguration
0401: .getFeature(DEFER_NODE_EXPANSION);
0402:
0403: fNamespaceAware = fConfiguration.getFeature(NAMESPACES);
0404:
0405: fIncludeComments = fConfiguration
0406: .getFeature(INCLUDE_COMMENTS_FEATURE);
0407:
0408: fCreateCDATANodes = fConfiguration
0409: .getFeature(CREATE_CDATA_NODES_FEATURE);
0410:
0411: // get property
0412: setDocumentClassName((String) fConfiguration
0413: .getProperty(DOCUMENT_CLASS_NAME));
0414:
0415: // reset dom information
0416: fDocument = null;
0417: fDocumentImpl = null;
0418: fStorePSVI = false;
0419: fDocumentType = null;
0420: fDocumentTypeIndex = -1;
0421: fDeferredDocumentImpl = null;
0422: fCurrentNode = null;
0423:
0424: // reset string buffer
0425: fStringBuffer.setLength(0);
0426:
0427: // reset state information
0428: fRoot.clear();
0429: fInDTD = false;
0430: fInDTDExternalSubset = false;
0431: fInCDATASection = false;
0432: fFirstChunk = false;
0433: fCurrentCDATASection = null;
0434: fCurrentCDATASectionIndex = -1;
0435:
0436: fBaseURIStack.removeAllElements();
0437:
0438: } // reset()
0439:
0440: /**
0441: * Set the locale to use for messages.
0442: *
0443: * @param locale The locale object to use for localization of messages.
0444: *
0445: */
0446: public void setLocale(Locale locale) {
0447: fConfiguration.setLocale(locale);
0448:
0449: } // setLocale(Locale)
0450:
0451: //
0452: // XMLDocumentHandler methods
0453: //
0454:
0455: /**
0456: * This method notifies the start of a general entity.
0457: * <p>
0458: * <strong>Note:</strong> This method is not called for entity references
0459: * appearing as part of attribute values.
0460: *
0461: * @param name The name of the general entity.
0462: * @param identifier The resource identifier.
0463: * @param encoding The auto-detected IANA encoding name of the entity
0464: * stream. This value will be null in those situations
0465: * where the entity encoding is not auto-detected (e.g.
0466: * internal entities or a document entity that is
0467: * parsed from a java.io.Reader).
0468: * @param augs Additional information that may include infoset augmentations
0469: *
0470: * @exception XNIException Thrown by handler to signal an error.
0471: */
0472: public void startGeneralEntity(String name,
0473: XMLResourceIdentifier identifier, String encoding,
0474: Augmentations augs) throws XNIException {
0475: if (DEBUG_EVENTS) {
0476: System.out.println("==>startGeneralEntity (" + name + ")");
0477: if (DEBUG_BASEURI) {
0478: System.out.println(" expandedSystemId( **baseURI): "
0479: + identifier.getExpandedSystemId());
0480: System.out.println(" baseURI:"
0481: + identifier.getBaseSystemId());
0482: }
0483: }
0484:
0485: // Always create entity reference nodes to be able to recreate
0486: // entity as a part of doctype
0487: if (!fDeferNodeExpansion) {
0488: if (fFilterReject) {
0489: return;
0490: }
0491: setCharacterData(true);
0492: EntityReference er = fDocument.createEntityReference(name);
0493: if (fDocumentImpl != null) {
0494: // REVISIT: baseURI/actualEncoding
0495: // remove dependency on our implementation when DOM L3 is REC
0496: //
0497:
0498: EntityReferenceImpl erImpl = (EntityReferenceImpl) er;
0499:
0500: // set base uri
0501: erImpl.setBaseURI(identifier.getExpandedSystemId());
0502: if (fDocumentType != null) {
0503: // set actual encoding
0504: NamedNodeMap entities = fDocumentType.getEntities();
0505: fCurrentEntityDecl = (EntityImpl) entities
0506: .getNamedItem(name);
0507: if (fCurrentEntityDecl != null) {
0508: fCurrentEntityDecl.setInputEncoding(encoding);
0509: }
0510:
0511: }
0512: // we don't need synchronization now, because entity ref will be
0513: // expanded anyway. Synch only needed when user creates entityRef node
0514: erImpl.needsSyncChildren(false);
0515: }
0516: fInEntityRef = true;
0517: fCurrentNode.appendChild(er);
0518: fCurrentNode = er;
0519: } else {
0520:
0521: int er = fDeferredDocumentImpl
0522: .createDeferredEntityReference(name, identifier
0523: .getExpandedSystemId());
0524: if (fDocumentTypeIndex != -1) {
0525: // find corresponding Entity decl
0526: int node = fDeferredDocumentImpl.getLastChild(
0527: fDocumentTypeIndex, false);
0528: while (node != -1) {
0529: short nodeType = fDeferredDocumentImpl.getNodeType(
0530: node, false);
0531: if (nodeType == Node.ENTITY_NODE) {
0532: String nodeName = fDeferredDocumentImpl
0533: .getNodeName(node, false);
0534: if (nodeName.equals(name)) {
0535: fDeferredEntityDecl = node;
0536: fDeferredDocumentImpl.setInputEncoding(
0537: node, encoding);
0538: break;
0539: }
0540: }
0541: node = fDeferredDocumentImpl.getRealPrevSibling(
0542: node, false);
0543: }
0544: }
0545: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, er);
0546: fCurrentNodeIndex = er;
0547: }
0548:
0549: } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
0550:
0551: /**
0552: * Notifies of the presence of a TextDecl line in an entity. If present,
0553: * this method will be called immediately following the startEntity call.
0554: * <p>
0555: * <strong>Note:</strong> This method will never be called for the
0556: * document entity; it is only called for external general entities
0557: * referenced in document content.
0558: * <p>
0559: * <strong>Note:</strong> This method is not called for entity references
0560: * appearing as part of attribute values.
0561: *
0562: * @param version The XML version, or null if not specified.
0563: * @param encoding The IANA encoding name of the entity.
0564: * @param augs Additional information that may include infoset augmentations
0565: *
0566: * @throws XNIException Thrown by handler to signal an error.
0567: */
0568: public void textDecl(String version, String encoding,
0569: Augmentations augs) throws XNIException {
0570: if (fInDTD) {
0571: return;
0572: }
0573: if (!fDeferNodeExpansion) {
0574: if (fCurrentEntityDecl != null && !fFilterReject) {
0575: fCurrentEntityDecl.setXmlEncoding(encoding);
0576: if (version != null)
0577: fCurrentEntityDecl.setXmlVersion(version);
0578: }
0579: } else {
0580: if (fDeferredEntityDecl != -1) {
0581: fDeferredDocumentImpl.setEntityInfo(
0582: fDeferredEntityDecl, version, encoding);
0583: }
0584: }
0585: } // textDecl(String,String)
0586:
0587: /**
0588: * A comment.
0589: *
0590: * @param text The text in the comment.
0591: * @param augs Additional information that may include infoset augmentations
0592: *
0593: * @throws XNIException Thrown by application to signal an error.
0594: */
0595: public void comment(XMLString text, Augmentations augs)
0596: throws XNIException {
0597: if (fInDTD) {
0598: if (fInternalSubset != null && !fInDTDExternalSubset) {
0599: fInternalSubset.append("<!--");
0600: if (text.length > 0) {
0601: fInternalSubset.append(text.ch, text.offset,
0602: text.length);
0603: }
0604: fInternalSubset.append("-->");
0605: }
0606: return;
0607: }
0608: if (!fIncludeComments || fFilterReject) {
0609: return;
0610: }
0611: if (!fDeferNodeExpansion) {
0612: Comment comment = fDocument.createComment(text.toString());
0613:
0614: setCharacterData(false);
0615: fCurrentNode.appendChild(comment);
0616: if (fDOMFilter != null
0617: && !fInEntityRef
0618: && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT) != 0) {
0619: short code = fDOMFilter.acceptNode(comment);
0620: switch (code) {
0621: case LSParserFilter.FILTER_INTERRUPT: {
0622: throw ABORT;
0623: }
0624: case LSParserFilter.FILTER_REJECT: {
0625: // REVISIT: the constant FILTER_REJECT should be changed when new
0626: // DOM LS specs gets published
0627:
0628: // fall through to SKIP since comment has no children.
0629: }
0630: case LSParserFilter.FILTER_SKIP: {
0631: // REVISIT: the constant FILTER_SKIP should be changed when new
0632: // DOM LS specs gets published
0633: fCurrentNode.removeChild(comment);
0634: // make sure we don't loose chars if next event is characters()
0635: fFirstChunk = true;
0636: return;
0637: }
0638:
0639: default: {
0640: // accept node
0641: }
0642: }
0643: }
0644:
0645: } else {
0646: int comment = fDeferredDocumentImpl
0647: .createDeferredComment(text.toString());
0648: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex,
0649: comment);
0650: }
0651:
0652: } // comment(XMLString)
0653:
0654: /**
0655: * A processing instruction. Processing instructions consist of a
0656: * target name and, optionally, text data. The data is only meaningful
0657: * to the application.
0658: * <p>
0659: * Typically, a processing instruction's data will contain a series
0660: * of pseudo-attributes. These pseudo-attributes follow the form of
0661: * element attributes but are <strong>not</strong> parsed or presented
0662: * to the application as anything other than text. The application is
0663: * responsible for parsing the data.
0664: *
0665: * @param target The target.
0666: * @param data The data or null if none specified.
0667: * @param augs Additional information that may include infoset augmentations
0668: *
0669: * @throws XNIException Thrown by handler to signal an error.
0670: */
0671: public void processingInstruction(String target, XMLString data,
0672: Augmentations augs) throws XNIException {
0673:
0674: if (fInDTD) {
0675: if (fInternalSubset != null && !fInDTDExternalSubset) {
0676: fInternalSubset.append("<?");
0677: fInternalSubset.append(target);
0678: if (data.length > 0) {
0679: fInternalSubset.append(' ').append(data.ch,
0680: data.offset, data.length);
0681: }
0682: fInternalSubset.append("?>");
0683: }
0684: return;
0685: }
0686:
0687: if (DEBUG_EVENTS) {
0688: System.out.println("==>processingInstruction (" + target
0689: + ")");
0690: }
0691: if (!fDeferNodeExpansion) {
0692: if (fFilterReject) {
0693: return;
0694: }
0695: ProcessingInstruction pi = fDocument
0696: .createProcessingInstruction(target, data
0697: .toString());
0698:
0699: setCharacterData(false);
0700: fCurrentNode.appendChild(pi);
0701: if (fDOMFilter != null
0702: && !fInEntityRef
0703: && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION) != 0) {
0704: short code = fDOMFilter.acceptNode(pi);
0705: switch (code) {
0706: case LSParserFilter.FILTER_INTERRUPT: {
0707: throw ABORT;
0708: }
0709: case LSParserFilter.FILTER_REJECT: {
0710: // fall through to SKIP since PI has no children.
0711: }
0712: case LSParserFilter.FILTER_SKIP: {
0713: fCurrentNode.removeChild(pi);
0714: // fFirstChunk must be set to true so that data
0715: // won't be lost in the case where the child before PI is
0716: // a text node and the next event is characters.
0717: fFirstChunk = true;
0718: return;
0719: }
0720: default: {
0721: }
0722: }
0723: }
0724: } else {
0725: int pi = fDeferredDocumentImpl
0726: .createDeferredProcessingInstruction(target, data
0727: .toString());
0728: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
0729: }
0730:
0731: } // processingInstruction(String,XMLString)
0732:
0733: /**
0734: * The start of the document.
0735: *
0736: * @param locator The system identifier of the entity if the entity
0737: * is external, null otherwise.
0738: * @param encoding The auto-detected IANA encoding name of the entity
0739: * stream. This value will be null in those situations
0740: * where the entity encoding is not auto-detected (e.g.
0741: * internal entities or a document entity that is
0742: * parsed from a java.io.Reader).
0743: * @param namespaceContext
0744: * The namespace context in effect at the
0745: * start of this document.
0746: * This object represents the current context.
0747: * Implementors of this class are responsible
0748: * for copying the namespace bindings from the
0749: * the current context (and its parent contexts)
0750: * if that information is important.
0751: * @param augs Additional information that may include infoset augmentations
0752: *
0753: * @throws XNIException Thrown by handler to signal an error.
0754: */
0755: public void startDocument(XMLLocator locator, String encoding,
0756: NamespaceContext namespaceContext, Augmentations augs)
0757: throws XNIException {
0758:
0759: fLocator = locator;
0760: if (!fDeferNodeExpansion) {
0761: if (fDocumentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
0762: fDocument = new DocumentImpl();
0763: fDocumentImpl = (CoreDocumentImpl) fDocument;
0764: // REVISIT: when DOM Level 3 is REC rely on Document.support
0765: // instead of specific class
0766: // set DOM error checking off
0767: fDocumentImpl.setStrictErrorChecking(false);
0768: // set actual encoding
0769: fDocumentImpl.setInputEncoding(encoding);
0770: // set documentURI
0771: fDocumentImpl.setDocumentURI(locator
0772: .getExpandedSystemId());
0773: } else if (fDocumentClassName
0774: .equals(PSVI_DOCUMENT_CLASS_NAME)) {
0775: fDocument = new PSVIDocumentImpl();
0776: fDocumentImpl = (CoreDocumentImpl) fDocument;
0777: fStorePSVI = true;
0778: // REVISIT: when DOM Level 3 is REC rely on Document.support
0779: // instead of specific class
0780: // set DOM error checking off
0781: fDocumentImpl.setStrictErrorChecking(false);
0782: // set actual encoding
0783: fDocumentImpl.setInputEncoding(encoding);
0784: // set documentURI
0785: fDocumentImpl.setDocumentURI(locator
0786: .getExpandedSystemId());
0787: } else {
0788: // use specified document class
0789: try {
0790: ClassLoader cl = ObjectFactory.findClassLoader();
0791: Class documentClass = ObjectFactory
0792: .findProviderClass(fDocumentClassName, cl,
0793: true);
0794: fDocument = (Document) documentClass.newInstance();
0795:
0796: // if subclass of our own class that's cool too
0797: Class defaultDocClass = ObjectFactory
0798: .findProviderClass(
0799: CORE_DOCUMENT_CLASS_NAME, cl, true);
0800: if (defaultDocClass.isAssignableFrom(documentClass)) {
0801: fDocumentImpl = (CoreDocumentImpl) fDocument;
0802:
0803: Class psviDocClass = ObjectFactory
0804: .findProviderClass(
0805: PSVI_DOCUMENT_CLASS_NAME, cl,
0806: true);
0807: if (psviDocClass
0808: .isAssignableFrom(documentClass)) {
0809: fStorePSVI = true;
0810: }
0811:
0812: // REVISIT: when DOM Level 3 is REC rely on
0813: // Document.support instead of specific class
0814: // set DOM error checking off
0815: fDocumentImpl.setStrictErrorChecking(false);
0816: // set actual encoding
0817: fDocumentImpl.setInputEncoding(encoding);
0818: // set documentURI
0819: if (locator != null) {
0820: fDocumentImpl.setDocumentURI(locator
0821: .getExpandedSystemId());
0822: }
0823: }
0824: } catch (ClassNotFoundException e) {
0825: // won't happen we already checked that earlier
0826: } catch (Exception e) {
0827: throw new RuntimeException(
0828: DOMMessageFormatter
0829: .formatMessage(
0830: DOMMessageFormatter.DOM_DOMAIN,
0831: "CannotCreateDocumentClass",
0832: new Object[] { fDocumentClassName }));
0833: }
0834: }
0835: fCurrentNode = fDocument;
0836: } else {
0837: fDeferredDocumentImpl = new DeferredDocumentImpl(
0838: fNamespaceAware);
0839: fDocument = fDeferredDocumentImpl;
0840: fDocumentIndex = fDeferredDocumentImpl
0841: .createDeferredDocument();
0842: // REVISIT: strict error checking is not implemented in deferred dom.
0843: // Document.support instead of specific class
0844:
0845: // set actual encoding
0846: fDeferredDocumentImpl.setInputEncoding(encoding);
0847: // set documentURI
0848: fDeferredDocumentImpl.setDocumentURI(locator
0849: .getExpandedSystemId());
0850: fCurrentNodeIndex = fDocumentIndex;
0851:
0852: }
0853:
0854: } // startDocument(String,String)
0855:
0856: /**
0857: * Notifies of the presence of an XMLDecl line in the document. If
0858: * present, this method will be called immediately following the
0859: * startDocument call.
0860: *
0861: * @param version The XML version.
0862: * @param encoding The IANA encoding name of the document, or null if
0863: * not specified.
0864: * @param standalone The standalone value, or null if not specified.
0865: * @param augs Additional information that may include infoset augmentations
0866: *
0867: * @throws XNIException Thrown by handler to signal an error.
0868: */
0869: public void xmlDecl(String version, String encoding,
0870: String standalone, Augmentations augs) throws XNIException {
0871: if (!fDeferNodeExpansion) {
0872: // REVISIT: when DOM Level 3 is REC rely on Document.support
0873: // instead of specific class
0874: if (fDocumentImpl != null) {
0875: if (version != null)
0876: fDocumentImpl.setXmlVersion(version);
0877: fDocumentImpl.setXmlEncoding(encoding);
0878: fDocumentImpl
0879: .setXmlStandalone("yes".equals(standalone));
0880: }
0881: } else {
0882: if (version != null)
0883: fDeferredDocumentImpl.setXmlVersion(version);
0884: fDeferredDocumentImpl.setXmlEncoding(encoding);
0885: fDeferredDocumentImpl.setXmlStandalone("yes"
0886: .equals(standalone));
0887: }
0888: } // xmlDecl(String,String,String)
0889:
0890: /**
0891: * Notifies of the presence of the DOCTYPE line in the document.
0892: *
0893: * @param rootElement The name of the root element.
0894: * @param publicId The public identifier if an external DTD or null
0895: * if the external DTD is specified using SYSTEM.
0896: * @param systemId The system identifier if an external DTD, null
0897: * otherwise.
0898: * @param augs Additional information that may include infoset augmentations
0899: *
0900: * @throws XNIException Thrown by handler to signal an error.
0901: */
0902: public void doctypeDecl(String rootElement, String publicId,
0903: String systemId, Augmentations augs) throws XNIException {
0904:
0905: if (!fDeferNodeExpansion) {
0906: if (fDocumentImpl != null) {
0907: fDocumentType = fDocumentImpl.createDocumentType(
0908: rootElement, publicId, systemId);
0909: fCurrentNode.appendChild(fDocumentType);
0910: }
0911: } else {
0912: fDocumentTypeIndex = fDeferredDocumentImpl
0913: .createDeferredDocumentType(rootElement, publicId,
0914: systemId);
0915: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex,
0916: fDocumentTypeIndex);
0917: }
0918:
0919: } // doctypeDecl(String,String,String)
0920:
0921: /**
0922: * The start of an element. If the document specifies the start element
0923: * by using an empty tag, then the startElement method will immediately
0924: * be followed by the endElement method, with no intervening methods.
0925: *
0926: * @param element The name of the element.
0927: * @param attributes The element attributes.
0928: * @param augs Additional information that may include infoset augmentations
0929: *
0930: * @throws XNIException Thrown by handler to signal an error.
0931: */
0932: public void startElement(QName element, XMLAttributes attributes,
0933: Augmentations augs) throws XNIException {
0934: if (DEBUG_EVENTS) {
0935: System.out.println("==>startElement (" + element.rawname
0936: + ")");
0937: }
0938: if (!fDeferNodeExpansion) {
0939: if (fFilterReject) {
0940: return;
0941: }
0942: Element el = createElementNode(element);
0943: int attrCount = attributes.getLength();
0944: boolean seenSchemaDefault = false;
0945: for (int i = 0; i < attrCount; i++) {
0946: attributes.getName(i, fAttrQName);
0947: Attr attr = createAttrNode(fAttrQName);
0948:
0949: String attrValue = attributes.getValue(i);
0950:
0951: AttributePSVI attrPSVI = (AttributePSVI) attributes
0952: .getAugmentations(i).getItem(
0953: Constants.ATTRIBUTE_PSVI);
0954: if (fStorePSVI && attrPSVI != null) {
0955: ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
0956: }
0957:
0958: attr.setValue(attrValue);
0959: boolean specified = attributes.isSpecified(i);
0960: // Take special care of schema defaulted attributes. Calling the
0961: // non-namespace aware setAttributeNode() method could overwrite
0962: // another attribute with the same local name.
0963: if (!specified
0964: && (seenSchemaDefault || (fAttrQName.uri != null && fAttrQName.prefix == null))) {
0965: el.setAttributeNodeNS(attr);
0966: seenSchemaDefault = true;
0967: } else {
0968: el.setAttributeNode(attr);
0969: }
0970: // NOTE: The specified value MUST be set after you set
0971: // the node value because that turns the "specified"
0972: // flag to "true" which may overwrite a "false"
0973: // value from the attribute list. -Ac
0974: if (fDocumentImpl != null) {
0975: AttrImpl attrImpl = (AttrImpl) attr;
0976: Object type = null;
0977: boolean id = false;
0978:
0979: // REVISIT: currently it is possible that someone turns off
0980: // namespaces and turns on xml schema validation
0981: // To avoid classcast exception in AttrImpl check for namespaces
0982: // however the correct solution should probably disallow setting
0983: // namespaces to false when schema processing is turned on.
0984: if (attrPSVI != null && fNamespaceAware) {
0985: // XML Schema
0986: type = attrPSVI.getMemberTypeDefinition();
0987: if (type == null) {
0988: type = attrPSVI.getTypeDefinition();
0989: if (type != null) {
0990: id = ((XSSimpleType) type).isIDType();
0991: attrImpl.setType(type);
0992: }
0993: } else {
0994: id = ((XSSimpleType) type).isIDType();
0995: attrImpl.setType(type);
0996: }
0997: } else {
0998: // DTD
0999: boolean isDeclared = Boolean.TRUE
1000: .equals(attributes
1001: .getAugmentations(i)
1002: .getItem(
1003: 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,
1016: true);
1017: }
1018:
1019: attrImpl.setSpecified(specified);
1020: // REVISIT: Handle entities in attribute value.
1021: }
1022: }
1023: setCharacterData(false);
1024:
1025: if (augs != null) {
1026: ElementPSVI elementPSVI = (ElementPSVI) augs
1027: .getItem(Constants.ELEMENT_PSVI);
1028: if (elementPSVI != null && fNamespaceAware) {
1029: XSTypeDefinition type = elementPSVI
1030: .getMemberTypeDefinition();
1031: if (type == null) {
1032: type = elementPSVI.getTypeDefinition();
1033: }
1034: ((ElementNSImpl) el).setType(type);
1035: }
1036: }
1037:
1038: // filter nodes
1039: if (fDOMFilter != null && !fInEntityRef) {
1040: if (fRoot.rawname == null) {
1041: // fill value of the root element
1042: fRoot.setValues(element);
1043: } else {
1044: short code = fDOMFilter.startElement(el);
1045: switch (code) {
1046: case LSParserFilter.FILTER_INTERRUPT: {
1047: throw ABORT;
1048: }
1049: case LSParserFilter.FILTER_REJECT: {
1050: fFilterReject = true;
1051: fRejectedElement.setValues(element);
1052: return;
1053: }
1054: case LSParserFilter.FILTER_SKIP: {
1055: fSkippedElemStack.push(element.clone());
1056: return;
1057: }
1058: default: {
1059: }
1060: }
1061: }
1062: }
1063: fCurrentNode.appendChild(el);
1064: fCurrentNode = el;
1065: } else {
1066: int el = fDeferredDocumentImpl.createDeferredElement(
1067: fNamespaceAware ? element.uri : null,
1068: element.rawname);
1069: Object type = null;
1070: int attrCount = attributes.getLength();
1071: // Need to loop in reverse order so that the attributes
1072: // are processed in document order when the DOM is expanded.
1073: for (int i = attrCount - 1; i >= 0; --i) {
1074:
1075: // set type information
1076: AttributePSVI attrPSVI = (AttributePSVI) attributes
1077: .getAugmentations(i).getItem(
1078: Constants.ATTRIBUTE_PSVI);
1079: boolean id = false;
1080:
1081: // REVISIT: currently it is possible that someone turns off
1082: // namespaces and turns on xml schema validation
1083: // To avoid classcast exception in AttrImpl check for namespaces
1084: // however the correct solution should probably disallow setting
1085: // namespaces to false when schema processing is turned on.
1086: if (attrPSVI != null && fNamespaceAware) {
1087: // XML Schema
1088: type = attrPSVI.getMemberTypeDefinition();
1089: if (type == null) {
1090: type = attrPSVI.getTypeDefinition();
1091: if (type != null) {
1092: id = ((XSSimpleType) type).isIDType();
1093: }
1094: } else {
1095: id = ((XSSimpleType) type).isIDType();
1096: }
1097: } else {
1098: // DTD
1099: boolean isDeclared = Boolean.TRUE.equals(attributes
1100: .getAugmentations(i).getItem(
1101: Constants.ATTRIBUTE_DECLARED));
1102: // For DOM Level 3 TypeInfo, the type name must
1103: // be null if this attribute has not been declared
1104: // in the DTD.
1105: if (isDeclared) {
1106: type = attributes.getType(i);
1107: id = "ID".equals(type);
1108: }
1109: }
1110:
1111: // create attribute
1112: fDeferredDocumentImpl.setDeferredAttribute(el,
1113: attributes.getQName(i), attributes.getURI(i),
1114: attributes.getValue(i), attributes
1115: .isSpecified(i), id, type);
1116: }
1117:
1118: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, el);
1119: fCurrentNodeIndex = el;
1120: }
1121: } // startElement(QName,XMLAttributes)
1122:
1123: /**
1124: * An empty element.
1125: *
1126: * @param element The name of the element.
1127: * @param attributes The element attributes.
1128: * @param augs Additional information that may include infoset augmentations
1129: *
1130: * @throws XNIException Thrown by handler to signal an error.
1131: */
1132: public void emptyElement(QName element, XMLAttributes attributes,
1133: Augmentations augs) throws XNIException {
1134:
1135: startElement(element, attributes, augs);
1136: endElement(element, augs);
1137:
1138: } // emptyElement(QName,XMLAttributes)
1139:
1140: /**
1141: * Character content.
1142: *
1143: * @param text The content.
1144: * @param augs Additional information that may include infoset augmentations
1145: *
1146: * @throws XNIException Thrown by handler to signal an error.
1147: */
1148: public void characters(XMLString text, Augmentations augs)
1149: throws XNIException {
1150:
1151: if (DEBUG_EVENTS) {
1152: System.out.println("==>characters(): " + text.toString());
1153: }
1154:
1155: if (!fDeferNodeExpansion) {
1156:
1157: if (fFilterReject) {
1158: return;
1159: }
1160: if (fInCDATASection && fCreateCDATANodes) {
1161: if (fCurrentCDATASection == null) {
1162: fCurrentCDATASection = fDocument
1163: .createCDATASection(text.toString());
1164: fCurrentNode.appendChild(fCurrentCDATASection);
1165: fCurrentNode = fCurrentCDATASection;
1166: } else {
1167: fCurrentCDATASection.appendData(text.toString());
1168: }
1169: } else if (!fInDTD) {
1170: // if type is union (XML Schema) it is possible that we receive
1171: // character call with empty data
1172: if (text.length == 0) {
1173: return;
1174: }
1175:
1176: Node child = fCurrentNode.getLastChild();
1177: if (child != null
1178: && child.getNodeType() == Node.TEXT_NODE) {
1179: // collect all the data into the string buffer.
1180: if (fFirstChunk) {
1181: if (fDocumentImpl != null) {
1182: fStringBuffer.append(((TextImpl) child)
1183: .removeData());
1184: } else {
1185: fStringBuffer.append(((Text) child)
1186: .getData());
1187: ((Text) child).setNodeValue(null);
1188: }
1189: fFirstChunk = false;
1190: }
1191: if (text.length > 0) {
1192: fStringBuffer.append(text.ch, text.offset,
1193: text.length);
1194: }
1195: } else {
1196: fFirstChunk = true;
1197: Text textNode = fDocument.createTextNode(text
1198: .toString());
1199: fCurrentNode.appendChild(textNode);
1200: }
1201:
1202: }
1203: } else {
1204: // The Text and CDATASection normalization is taken care of within
1205: // the DOM in the deferred case.
1206: if (fInCDATASection && fCreateCDATANodes) {
1207: if (fCurrentCDATASectionIndex == -1) {
1208: int cs = fDeferredDocumentImpl
1209: .createDeferredCDATASection(text.toString());
1210:
1211: fDeferredDocumentImpl.appendChild(
1212: fCurrentNodeIndex, cs);
1213: fCurrentCDATASectionIndex = cs;
1214: fCurrentNodeIndex = cs;
1215: } else {
1216: int txt = fDeferredDocumentImpl
1217: .createDeferredTextNode(text.toString(),
1218: false);
1219: fDeferredDocumentImpl.appendChild(
1220: fCurrentNodeIndex, txt);
1221: }
1222: } else if (!fInDTD) {
1223: // if type is union (XML Schema) it is possible that we receive
1224: // character call with empty data
1225: if (text.length == 0) {
1226: return;
1227: }
1228:
1229: String value = text.toString();
1230: int txt = fDeferredDocumentImpl.createDeferredTextNode(
1231: value, false);
1232: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex,
1233: txt);
1234:
1235: }
1236: }
1237: } // characters(XMLString)
1238:
1239: /**
1240: * Ignorable whitespace. For this method to be called, the document
1241: * source must have some way of determining that the text containing
1242: * only whitespace characters should be considered ignorable. For
1243: * example, the validator can determine if a length of whitespace
1244: * characters in the document are ignorable based on the element
1245: * content model.
1246: *
1247: * @param text The ignorable whitespace.
1248: * @param augs Additional information that may include infoset augmentations
1249: *
1250: * @throws XNIException Thrown by handler to signal an error.
1251: */
1252: public void ignorableWhitespace(XMLString text, Augmentations augs)
1253: throws XNIException {
1254:
1255: if (!fIncludeIgnorableWhitespace || fFilterReject) {
1256: return;
1257: }
1258: if (!fDeferNodeExpansion) {
1259: Node child = fCurrentNode.getLastChild();
1260: if (child != null && child.getNodeType() == Node.TEXT_NODE) {
1261: Text textNode = (Text) child;
1262: textNode.appendData(text.toString());
1263: } else {
1264: Text textNode = fDocument.createTextNode(text
1265: .toString());
1266: if (fDocumentImpl != null) {
1267: TextImpl textNodeImpl = (TextImpl) textNode;
1268: textNodeImpl.setIgnorableWhitespace(true);
1269: }
1270: fCurrentNode.appendChild(textNode);
1271: }
1272: } else {
1273: // The Text normalization is taken care of within the DOM in the
1274: // deferred case.
1275: int txt = fDeferredDocumentImpl.createDeferredTextNode(text
1276: .toString(), true);
1277: fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
1278: }
1279:
1280: } // ignorableWhitespace(XMLString)
1281:
1282: /**
1283: * The end of an element.
1284: *
1285: * @param element The name of the element.
1286: * @param augs Additional information that may include infoset augmentations
1287: *
1288: * @throws XNIException Thrown by handler to signal an error.
1289: */
1290: public void endElement(QName element, Augmentations augs)
1291: throws XNIException {
1292: if (DEBUG_EVENTS) {
1293: System.out.println("==>endElement (" + element.rawname
1294: + ")");
1295: }
1296: if (!fDeferNodeExpansion) {
1297:
1298: // REVISIT: Should this happen after we call the filter?
1299: if (augs != null && fDocumentImpl != null
1300: && (fNamespaceAware || fStorePSVI)) {
1301: ElementPSVI elementPSVI = (ElementPSVI) augs
1302: .getItem(Constants.ELEMENT_PSVI);
1303: if (elementPSVI != null) {
1304: // Updating TypeInfo. If the declared type is a union the
1305: // [member type definition] will only be available at the
1306: // end of an element.
1307: if (fNamespaceAware) {
1308: XSTypeDefinition type = elementPSVI
1309: .getMemberTypeDefinition();
1310: if (type == null) {
1311: type = elementPSVI.getTypeDefinition();
1312: }
1313: ((ElementNSImpl) fCurrentNode).setType(type);
1314: }
1315: if (fStorePSVI) {
1316: ((PSVIElementNSImpl) fCurrentNode)
1317: .setPSVI(elementPSVI);
1318: }
1319: }
1320: }
1321:
1322: if (fDOMFilter != null) {
1323: if (fFilterReject) {
1324: if (element.equals(fRejectedElement)) {
1325: fFilterReject = false;
1326: }
1327: return;
1328: }
1329: if (!fSkippedElemStack.isEmpty()) {
1330: if (fSkippedElemStack.peek().equals(element)) {
1331: fSkippedElemStack.pop();
1332: return;
1333: }
1334: }
1335: setCharacterData(false);
1336: if (!fRoot.equals(element)
1337: && !fInEntityRef
1338: && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT) != 0) {
1339: short code = fDOMFilter.acceptNode(fCurrentNode);
1340: switch (code) {
1341: case LSParserFilter.FILTER_INTERRUPT: {
1342: throw ABORT;
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 loose 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: }
1376: fCurrentNode = fCurrentNode.getParentNode();
1377:
1378: } // end-if DOMFilter
1379: else {
1380: setCharacterData(false);
1381: fCurrentNode = fCurrentNode.getParentNode();
1382: }
1383:
1384: } else {
1385: if (augs != null) {
1386: ElementPSVI elementPSVI = (ElementPSVI) augs
1387: .getItem(Constants.ELEMENT_PSVI);
1388: if (elementPSVI != null) {
1389: // Setting TypeInfo. If the declared type is a union the
1390: // [member type definition] will only be available at the
1391: // end of an element.
1392: XSTypeDefinition type = elementPSVI
1393: .getMemberTypeDefinition();
1394: if (type == null) {
1395: type = elementPSVI.getTypeDefinition();
1396: }
1397: fDeferredDocumentImpl.setTypeInfo(
1398: fCurrentNodeIndex, type);
1399: }
1400: }
1401: fCurrentNodeIndex = fDeferredDocumentImpl.getParentNode(
1402: fCurrentNodeIndex, false);
1403: }
1404:
1405: } // endElement(QName)
1406:
1407: /**
1408: * The start of a CDATA section.
1409: * @param augs Additional information that may include infoset augmentations
1410: *
1411: * @throws XNIException Thrown by handler to signal an error.
1412: */
1413: public void startCDATA(Augmentations augs) throws XNIException {
1414:
1415: fInCDATASection = true;
1416: if (!fDeferNodeExpansion) {
1417: if (fFilterReject) {
1418: return;
1419: }
1420: if (fCreateCDATANodes) {
1421: setCharacterData(false);
1422: }
1423: }
1424: } // startCDATA()
1425:
1426: /**
1427: * The end of a CDATA section.
1428: * @param augs Additional information that may include infoset augmentations
1429: *
1430: * @throws XNIException Thrown by handler to signal an error.
1431: */
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
1444: && !fInEntityRef
1445: && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_CDATA_SECTION) != 0) {
1446: short code = fDOMFilter
1447: .acceptNode(fCurrentCDATASection);
1448: switch (code) {
1449: case LSParserFilter.FILTER_INTERRUPT: {
1450: throw ABORT;
1451: }
1452: case LSParserFilter.FILTER_REJECT: {
1453: // fall through to SKIP since CDATA section has no children.
1454: }
1455: case LSParserFilter.FILTER_SKIP: {
1456: Node parent = fCurrentNode.getParentNode();
1457: parent.removeChild(fCurrentCDATASection);
1458: fCurrentNode = parent;
1459: return;
1460: }
1461:
1462: default: {
1463: // accept node
1464: }
1465: }
1466: }
1467:
1468: fCurrentNode = fCurrentNode.getParentNode();
1469: fCurrentCDATASection = null;
1470: }
1471: } else {
1472: if (fCurrentCDATASectionIndex != -1) {
1473: fCurrentNodeIndex = fDeferredDocumentImpl
1474: .getParentNode(fCurrentNodeIndex, false);
1475: fCurrentCDATASectionIndex = -1;
1476: }
1477: }
1478:
1479: } // endCDATA()
1480:
1481: /**
1482: * The end of the document.
1483: * @param augs Additional information that may include infoset augmentations
1484: *
1485: * @throws XNIException Thrown by handler to signal an error.
1486: */
1487: public void endDocument(Augmentations augs) throws XNIException {
1488:
1489: if (!fDeferNodeExpansion) {
1490: // REVISIT: when DOM Level 3 is REC rely on Document.support
1491: // instead of specific class
1492: // set the actual encoding and set DOM error checking back on
1493: if (fDocumentImpl != null) {
1494: if (fLocator != null) {
1495: fDocumentImpl.setInputEncoding(fLocator
1496: .getEncoding());
1497: }
1498: fDocumentImpl.setStrictErrorChecking(true);
1499: }
1500: fCurrentNode = null;
1501: } else {
1502: // set the actual encoding
1503: if (fLocator != null) {
1504: fDeferredDocumentImpl.setInputEncoding(fLocator
1505: .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)
1525: throws XNIException {
1526: if (DEBUG_EVENTS) {
1527: System.out.println("==>endGeneralEntity: (" + name + ")");
1528: }
1529: if (!fDeferNodeExpansion) {
1530:
1531: if (fFilterReject) {
1532: return;
1533: }
1534: setCharacterData(true);
1535:
1536: if (fDocumentType != null) {
1537: // get current entity declaration
1538: NamedNodeMap entities = fDocumentType.getEntities();
1539: fCurrentEntityDecl = (EntityImpl) entities
1540: .getNamedItem(name);
1541: if (fCurrentEntityDecl != null) {
1542: if (fCurrentEntityDecl != null
1543: && fCurrentEntityDecl.getFirstChild() == null) {
1544: fCurrentEntityDecl.setReadOnly(false, true);
1545: Node child = fCurrentNode.getFirstChild();
1546: while (child != null) {
1547: Node copy = child.cloneNode(true);
1548: fCurrentEntityDecl.appendChild(copy);
1549: child = child.getNextSibling();
1550: }
1551: fCurrentEntityDecl.setReadOnly(true, true);
1552:
1553: //entities.setNamedItem(fCurrentEntityDecl);
1554: }
1555: fCurrentEntityDecl = null;
1556: }
1557:
1558: }
1559: fInEntityRef = false;
1560: boolean removeEntityRef = false;
1561: if (fCreateEntityRefNodes) {
1562: if (fDocumentImpl != null) {
1563: // Make entity ref node read only
1564: ((NodeImpl) fCurrentNode).setReadOnly(true, true);
1565: }
1566:
1567: if (fDOMFilter != null
1568: && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE) != 0) {
1569: short code = fDOMFilter.acceptNode(fCurrentNode);
1570: switch (code) {
1571: case LSParserFilter.FILTER_INTERRUPT: {
1572: throw ABORT;
1573: }
1574: case LSParserFilter.FILTER_REJECT: {
1575: Node parent = fCurrentNode.getParentNode();
1576: parent.removeChild(fCurrentNode);
1577: fCurrentNode = parent;
1578: return;
1579:
1580: }
1581: case LSParserFilter.FILTER_SKIP: {
1582: // make sure we don't loose chars if next event is characters()
1583: fFirstChunk = true;
1584: removeEntityRef = true;
1585: break;
1586: }
1587:
1588: default: {
1589: fCurrentNode = fCurrentNode.getParentNode();
1590: }
1591: }
1592: } else {
1593: fCurrentNode = fCurrentNode.getParentNode();
1594: }
1595: }
1596:
1597: if (!fCreateEntityRefNodes || removeEntityRef) {
1598: // move entity reference children to the list of
1599: // siblings of its parent and remove entity reference
1600: NodeList children = fCurrentNode.getChildNodes();
1601: Node parent = fCurrentNode.getParentNode();
1602: int length = children.getLength();
1603: if (length > 0) {
1604:
1605: // get previous sibling of the entity reference
1606: Node node = fCurrentNode.getPreviousSibling();
1607: // normalize text nodes
1608: Node child = children.item(0);
1609: if (node != null
1610: && node.getNodeType() == Node.TEXT_NODE
1611: && child.getNodeType() == Node.TEXT_NODE) {
1612: ((Text) node).appendData(child.getNodeValue());
1613: fCurrentNode.removeChild(child);
1614:
1615: } else {
1616: node = parent.insertBefore(child, fCurrentNode);
1617: handleBaseURI(node);
1618: }
1619:
1620: for (int i = 1; i < length; i++) {
1621: node = parent.insertBefore(children.item(0),
1622: fCurrentNode);
1623: handleBaseURI(node);
1624: }
1625: } // length > 0
1626: parent.removeChild(fCurrentNode);
1627: fCurrentNode = parent;
1628: }
1629: } else {
1630:
1631: if (fDocumentTypeIndex != -1) {
1632: // find corresponding Entity decl
1633: int node = fDeferredDocumentImpl.getLastChild(
1634: fDocumentTypeIndex, false);
1635: while (node != -1) {
1636: short nodeType = fDeferredDocumentImpl.getNodeType(
1637: node, false);
1638: if (nodeType == Node.ENTITY_NODE) {
1639: String nodeName = fDeferredDocumentImpl
1640: .getNodeName(node, false);
1641: if (nodeName.equals(name)) {
1642: fDeferredEntityDecl = node;
1643: break;
1644: }
1645: }
1646: node = fDeferredDocumentImpl.getRealPrevSibling(
1647: node, false);
1648: }
1649: }
1650:
1651: if (fDeferredEntityDecl != -1
1652: && fDeferredDocumentImpl.getLastChild(
1653: fDeferredEntityDecl, false) == -1) {
1654: // entity definition exists and it does not have any children
1655: int prevIndex = -1;
1656: int childIndex = fDeferredDocumentImpl.getLastChild(
1657: fCurrentNodeIndex, false);
1658: while (childIndex != -1) {
1659: int cloneIndex = fDeferredDocumentImpl.cloneNode(
1660: childIndex, true);
1661: fDeferredDocumentImpl.insertBefore(
1662: fDeferredEntityDecl, cloneIndex, prevIndex);
1663: prevIndex = cloneIndex;
1664: childIndex = fDeferredDocumentImpl
1665: .getRealPrevSibling(childIndex, false);
1666: }
1667: }
1668: if (fCreateEntityRefNodes) {
1669: fCurrentNodeIndex = fDeferredDocumentImpl
1670: .getParentNode(fCurrentNodeIndex, false);
1671: } else { //!fCreateEntityRefNodes
1672: // move children of entity ref before the entity ref.
1673: // remove entity ref.
1674:
1675: // holds a child of entity ref
1676: int childIndex = fDeferredDocumentImpl.getLastChild(
1677: fCurrentNodeIndex, false);
1678: int parentIndex = fDeferredDocumentImpl.getParentNode(
1679: fCurrentNodeIndex, false);
1680:
1681: int prevIndex = fCurrentNodeIndex;
1682: int lastChild = childIndex;
1683: int sibling = -1;
1684: while (childIndex != -1) {
1685: handleBaseURI(childIndex);
1686: sibling = fDeferredDocumentImpl.getRealPrevSibling(
1687: childIndex, false);
1688: fDeferredDocumentImpl.insertBefore(parentIndex,
1689: childIndex, prevIndex);
1690: prevIndex = childIndex;
1691: childIndex = sibling;
1692: }
1693: if (lastChild != -1)
1694: fDeferredDocumentImpl.setAsLastChild(parentIndex,
1695: lastChild);
1696: else {
1697: sibling = fDeferredDocumentImpl.getRealPrevSibling(
1698: prevIndex, false);
1699: fDeferredDocumentImpl.setAsLastChild(parentIndex,
1700: sibling);
1701: }
1702: fCurrentNodeIndex = parentIndex;
1703: }
1704: fDeferredEntityDecl = -1;
1705: }
1706:
1707: } // endGeneralEntity(String, Augmentations)
1708:
1709: /**
1710: * Record baseURI information for the Element (by adding xml:base attribute)
1711: * or for the ProcessingInstruction (by setting a baseURI field)
1712: * Non deferred DOM.
1713: *
1714: * @param node
1715: */
1716: protected final void handleBaseURI(Node node) {
1717: if (fDocumentImpl != null) {
1718: // REVISIT: remove dependency on our implementation when
1719: // DOM L3 becomes REC
1720:
1721: String baseURI = null;
1722: short nodeType = node.getNodeType();
1723:
1724: if (nodeType == Node.ELEMENT_NODE) {
1725: // if an element already has xml:base attribute
1726: // do nothing
1727: if (fNamespaceAware) {
1728: if (((Element) node).getAttributeNodeNS(
1729: "http://www.w3.org/XML/1998/namespace",
1730: "base") != null) {
1731: return;
1732: }
1733: } else if (((Element) node)
1734: .getAttributeNode("xml:base") != null) {
1735: return;
1736: }
1737: // retrive the baseURI from the entity reference
1738: baseURI = ((EntityReferenceImpl) fCurrentNode)
1739: .getBaseURI();
1740: if (baseURI != null
1741: && !baseURI.equals(fDocumentImpl
1742: .getDocumentURI())) {
1743: if (fNamespaceAware) {
1744: ((Element) node).setAttributeNS(
1745: "http://www.w3.org/XML/1998/namespace",
1746: "base", baseURI);
1747: } else {
1748: ((Element) node).setAttribute("xml:base",
1749: baseURI);
1750: }
1751: }
1752: } else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1753:
1754: baseURI = ((EntityReferenceImpl) fCurrentNode)
1755: .getBaseURI();
1756: if (baseURI != null && fErrorHandler != null) {
1757: DOMErrorImpl error = new DOMErrorImpl();
1758: error.fType = "pi-base-uri-not-preserved";
1759: error.fRelatedData = baseURI;
1760: error.fSeverity = DOMError.SEVERITY_WARNING;
1761: fErrorHandler.getErrorHandler().handleError(error);
1762: }
1763: }
1764: }
1765: }
1766:
1767: /**
1768: *
1769: * Record baseURI information for the Element (by adding xml:base attribute)
1770: * or for the ProcessingInstruction (by setting a baseURI field)
1771: * Deferred DOM.
1772: *
1773: * @param node
1774: */
1775: protected final void handleBaseURI(int node) {
1776: short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
1777:
1778: if (nodeType == Node.ELEMENT_NODE) {
1779: String baseURI = fDeferredDocumentImpl.getNodeValueString(
1780: fCurrentNodeIndex, false);
1781: if (baseURI == null) {
1782: baseURI = fDeferredDocumentImpl
1783: .getDeferredEntityBaseURI(fDeferredEntityDecl);
1784: }
1785: if (baseURI != null
1786: && !baseURI.equals(fDeferredDocumentImpl
1787: .getDocumentURI())) {
1788: fDeferredDocumentImpl.setDeferredAttribute(node,
1789: "xml:base",
1790: "http://www.w3.org/XML/1998/namespace",
1791: baseURI, true);
1792: }
1793: } else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1794:
1795: // retrieve baseURI from the entity reference
1796: String baseURI = fDeferredDocumentImpl.getNodeValueString(
1797: fCurrentNodeIndex, false);
1798:
1799: if (baseURI == null) {
1800: // try baseURI of the entity declaration
1801: baseURI = fDeferredDocumentImpl
1802: .getDeferredEntityBaseURI(fDeferredEntityDecl);
1803: }
1804:
1805: if (baseURI != null && fErrorHandler != null) {
1806: DOMErrorImpl error = new DOMErrorImpl();
1807: error.fType = "pi-base-uri-not-preserved";
1808: error.fRelatedData = baseURI;
1809: error.fSeverity = DOMError.SEVERITY_WARNING;
1810: fErrorHandler.getErrorHandler().handleError(error);
1811: }
1812: }
1813: }
1814:
1815: //
1816: // XMLDTDHandler methods
1817: //
1818:
1819: /**
1820: * The start of the DTD.
1821: *
1822: * @param locator The document locator, or null if the document
1823: * location cannot be reported during the parsing of
1824: * the document DTD. However, it is <em>strongly</em>
1825: * recommended that a locator be supplied that can
1826: * at least report the base system identifier of the
1827: * DTD.
1828: * @param augs Additional information that may include infoset
1829: * augmentations.
1830: *
1831: * @throws XNIException Thrown by handler to signal an error.
1832: */
1833: public void startDTD(XMLLocator locator, Augmentations augs)
1834: throws XNIException {
1835: if (DEBUG_EVENTS) {
1836: System.out.println("==>startDTD");
1837: if (DEBUG_BASEURI) {
1838: System.out.println(" expandedSystemId: "
1839: + locator.getExpandedSystemId());
1840: System.out.println(" baseURI:"
1841: + locator.getBaseSystemId());
1842: }
1843: }
1844:
1845: fInDTD = true;
1846: if (locator != null) {
1847: fBaseURIStack.push(locator.getBaseSystemId());
1848: }
1849: if (fDeferNodeExpansion || fDocumentImpl != null) {
1850: fInternalSubset = new StringBuffer(1024);
1851: }
1852: } // startDTD(XMLLocator)
1853:
1854: /**
1855: * The end of the DTD.
1856: *
1857: * @param augs Additional information that may include infoset
1858: * augmentations.
1859: *
1860: * @throws XNIException Thrown by handler to signal an error.
1861: */
1862: public void endDTD(Augmentations augs) throws XNIException {
1863: if (DEBUG_EVENTS) {
1864: System.out.println("==>endDTD()");
1865: }
1866: fInDTD = false;
1867: if (!fBaseURIStack.isEmpty()) {
1868: fBaseURIStack.pop();
1869: }
1870: String internalSubset = fInternalSubset != null
1871: && fInternalSubset.length() > 0 ? fInternalSubset
1872: .toString() : null;
1873: if (fDeferNodeExpansion) {
1874: if (internalSubset != null) {
1875: fDeferredDocumentImpl.setInternalSubset(
1876: fDocumentTypeIndex, internalSubset);
1877: }
1878: } else if (fDocumentImpl != null) {
1879: if (internalSubset != null) {
1880: ((DocumentTypeImpl) fDocumentType)
1881: .setInternalSubset(internalSubset);
1882: }
1883: }
1884: } // endDTD()
1885:
1886: /**
1887: * The start of a conditional section.
1888: *
1889: * @param type The type of the conditional section. This value will
1890: * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1891: * @param augs Additional information that may include infoset
1892: * augmentations.
1893: *
1894: * @throws XNIException Thrown by handler to signal an error.
1895: *
1896: * @see #CONDITIONAL_INCLUDE
1897: * @see #CONDITIONAL_IGNORE
1898: */
1899: public void startConditional(short type, Augmentations augs)
1900: throws XNIException {
1901: } // startConditional(short)
1902:
1903: /**
1904: * The end of a conditional section.
1905: *
1906: * @param augs Additional information that may include infoset
1907: * augmentations.
1908: *
1909: * @throws XNIException Thrown by handler to signal an error.
1910: */
1911: public void endConditional(Augmentations augs) throws XNIException {
1912: } // endConditional()
1913:
1914: /**
1915: * The start of the DTD external subset.
1916: *
1917: * @param augs Additional information that may include infoset
1918: * augmentations.
1919: *
1920: * @throws XNIException Thrown by handler to signal an error.
1921: */
1922: public void startExternalSubset(XMLResourceIdentifier identifier,
1923: Augmentations augs) throws XNIException {
1924: if (DEBUG_EVENTS) {
1925: System.out.println("==>startExternalSubset");
1926: if (DEBUG_BASEURI) {
1927: System.out.println(" expandedSystemId: "
1928: + identifier.getExpandedSystemId());
1929: System.out.println(" baseURI:"
1930: + identifier.getBaseSystemId());
1931: }
1932: }
1933: fBaseURIStack.push(identifier.getBaseSystemId());
1934: fInDTDExternalSubset = true;
1935: } // startExternalSubset(Augmentations)
1936:
1937: /**
1938: * The end of the DTD external subset.
1939: *
1940: * @param augs Additional information that may include infoset
1941: * augmentations.
1942: *
1943: * @throws XNIException Thrown by handler to signal an error.
1944: */
1945: public void endExternalSubset(Augmentations augs)
1946: throws XNIException {
1947: fInDTDExternalSubset = false;
1948: fBaseURIStack.pop();
1949: } // endExternalSubset(Augmentations)
1950:
1951: /**
1952: * An internal entity declaration.
1953: *
1954: * @param name The name of the entity. Parameter entity names start with
1955: * '%', whereas the name of a general entity is just the
1956: * entity name.
1957: * @param text The value of the entity.
1958: * @param nonNormalizedText The non-normalized value of the entity. This
1959: * value contains the same sequence of characters that was in
1960: * the internal entity declaration, without any entity
1961: * references expanded.
1962: * @param augs Additional information that may include infoset
1963: * augmentations.
1964: *
1965: * @throws XNIException Thrown by handler to signal an error.
1966: */
1967: public void internalEntityDecl(String name, XMLString text,
1968: XMLString nonNormalizedText, Augmentations augs)
1969: throws XNIException {
1970:
1971: if (DEBUG_EVENTS) {
1972: System.out.println("==>internalEntityDecl: " + name);
1973: if (DEBUG_BASEURI) {
1974: System.out.println(" baseURI:"
1975: + (String) fBaseURIStack.peek());
1976: }
1977: }
1978: // internal subset string
1979: if (fInternalSubset != null && !fInDTDExternalSubset) {
1980: fInternalSubset.append("<!ENTITY ");
1981: if (name.startsWith("%")) {
1982: fInternalSubset.append("% ");
1983: fInternalSubset.append(name.substring(1));
1984: } else {
1985: fInternalSubset.append(name);
1986: }
1987: fInternalSubset.append(' ');
1988: String value = nonNormalizedText.toString();
1989: boolean singleQuote = value.indexOf('\'') == -1;
1990: fInternalSubset.append(singleQuote ? '\'' : '"');
1991: fInternalSubset.append(value);
1992: fInternalSubset.append(singleQuote ? '\'' : '"');
1993: fInternalSubset.append(">\n");
1994: }
1995:
1996: // NOTE: We only know how to create these nodes for the Xerces
1997: // DOM implementation because DOM Level 2 does not specify
1998: // that functionality. -Ac
1999:
2000: // create full node
2001: // don't add parameter entities!
2002: if (name.startsWith("%"))
2003: return;
2004: if (fDocumentType != null) {
2005: NamedNodeMap entities = fDocumentType.getEntities();
2006: EntityImpl entity = (EntityImpl) entities
2007: .getNamedItem(name);
2008: if (entity == null) {
2009: entity = (EntityImpl) fDocumentImpl.createEntity(name);
2010: entity.setBaseURI((String) fBaseURIStack.peek());
2011: entities.setNamedItem(entity);
2012: }
2013: }
2014:
2015: // create deferred node
2016: if (fDocumentTypeIndex != -1) {
2017: boolean found = false;
2018: int node = fDeferredDocumentImpl.getLastChild(
2019: fDocumentTypeIndex, false);
2020: while (node != -1) {
2021: short nodeType = fDeferredDocumentImpl.getNodeType(
2022: node, false);
2023: if (nodeType == Node.ENTITY_NODE) {
2024: String nodeName = fDeferredDocumentImpl
2025: .getNodeName(node, false);
2026: if (nodeName.equals(name)) {
2027: found = true;
2028: break;
2029: }
2030: }
2031: node = fDeferredDocumentImpl.getRealPrevSibling(node,
2032: false);
2033: }
2034: if (!found) {
2035: int entityIndex = fDeferredDocumentImpl
2036: .createDeferredEntity(name, null, null, null,
2037: (String) fBaseURIStack.peek());
2038: fDeferredDocumentImpl.appendChild(fDocumentTypeIndex,
2039: entityIndex);
2040: }
2041: }
2042:
2043: } // internalEntityDecl(String,XMLString,XMLString)
2044:
2045: /**
2046: * An external entity declaration.
2047: *
2048: * @param name The name of the entity. Parameter entity names start
2049: * with '%', whereas the name of a general entity is just
2050: * the entity name.
2051: * @param identifier An object containing all location information
2052: * pertinent to this notation.
2053: * @param augs Additional information that may include infoset
2054: * augmentations.
2055: *
2056: * @throws XNIException Thrown by handler to signal an error.
2057: */
2058: public void externalEntityDecl(String name,
2059: XMLResourceIdentifier identifier, Augmentations augs)
2060: throws XNIException {
2061:
2062: if (DEBUG_EVENTS) {
2063: System.out.println("==>externalEntityDecl: " + name);
2064: if (DEBUG_BASEURI) {
2065: System.out.println(" expandedSystemId:"
2066: + identifier.getExpandedSystemId());
2067: System.out.println(" baseURI:"
2068: + identifier.getBaseSystemId());
2069: }
2070: }
2071: // internal subset string
2072: String publicId = identifier.getPublicId();
2073: String literalSystemId = identifier.getLiteralSystemId();
2074: if (fInternalSubset != null && !fInDTDExternalSubset) {
2075: fInternalSubset.append("<!ENTITY ");
2076: if (name.startsWith("%")) {
2077: fInternalSubset.append("% ");
2078: fInternalSubset.append(name.substring(1));
2079: } else {
2080: fInternalSubset.append(name);
2081: }
2082: fInternalSubset.append(' ');
2083: if (publicId != null) {
2084: fInternalSubset.append("PUBLIC '");
2085: fInternalSubset.append(publicId);
2086: fInternalSubset.append("' '");
2087: } else {
2088: fInternalSubset.append("SYSTEM '");
2089: }
2090: fInternalSubset.append(literalSystemId);
2091: fInternalSubset.append("'>\n");
2092: }
2093:
2094: // NOTE: We only know how to create these nodes for the Xerces
2095: // DOM implementation because DOM Level 2 does not specify
2096: // that functionality. -Ac
2097:
2098: // create full node
2099: // don't add parameter entities!
2100: if (name.startsWith("%"))
2101: return;
2102: if (fDocumentType != null) {
2103: NamedNodeMap entities = fDocumentType.getEntities();
2104: EntityImpl entity = (EntityImpl) entities
2105: .getNamedItem(name);
2106: if (entity == null) {
2107: entity = (EntityImpl) fDocumentImpl.createEntity(name);
2108: entity.setPublicId(publicId);
2109: entity.setSystemId(literalSystemId);
2110: entity.setBaseURI(identifier.getBaseSystemId());
2111: entities.setNamedItem(entity);
2112: }
2113: }
2114:
2115: // create deferred node
2116: if (fDocumentTypeIndex != -1) {
2117: boolean found = false;
2118: int nodeIndex = fDeferredDocumentImpl.getLastChild(
2119: fDocumentTypeIndex, false);
2120: while (nodeIndex != -1) {
2121: short nodeType = fDeferredDocumentImpl.getNodeType(
2122: nodeIndex, false);
2123: if (nodeType == Node.ENTITY_NODE) {
2124: String nodeName = fDeferredDocumentImpl
2125: .getNodeName(nodeIndex, false);
2126: if (nodeName.equals(name)) {
2127: found = true;
2128: break;
2129: }
2130: }
2131: nodeIndex = fDeferredDocumentImpl.getRealPrevSibling(
2132: nodeIndex, false);
2133: }
2134: if (!found) {
2135: int entityIndex = fDeferredDocumentImpl
2136: .createDeferredEntity(name, publicId,
2137: literalSystemId, null, identifier
2138: .getBaseSystemId());
2139: fDeferredDocumentImpl.appendChild(fDocumentTypeIndex,
2140: entityIndex);
2141: }
2142: }
2143:
2144: } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
2145:
2146: /**
2147: * This method notifies of the start of a parameter entity. The parameter
2148: * entity name start with a '%' character.
2149: *
2150: * @param name The name of the parameter entity.
2151: * @param identifier The resource identifier.
2152: * @param encoding The auto-detected IANA encoding name of the entity
2153: * stream. This value will be null in those situations
2154: * where the entity encoding is not auto-detected (e.g.
2155: * internal parameter entities).
2156: * @param augs Additional information that may include infoset
2157: * augmentations.
2158: *
2159: * @throws XNIException Thrown by handler to signal an error.
2160: */
2161: public void startParameterEntity(String name,
2162: XMLResourceIdentifier identifier, String encoding,
2163: Augmentations augs) throws XNIException {
2164: if (DEBUG_EVENTS) {
2165: System.out.println("==>startParameterEntity: " + name);
2166: if (DEBUG_BASEURI) {
2167: System.out.println(" expandedSystemId: "
2168: + identifier.getExpandedSystemId());
2169: System.out.println(" baseURI:"
2170: + identifier.getBaseSystemId());
2171: }
2172: }
2173: if (augs != null
2174: && fInternalSubset != null
2175: && !fInDTDExternalSubset
2176: && Boolean.TRUE.equals(augs
2177: .getItem(Constants.ENTITY_SKIPPED))) {
2178: fInternalSubset.append(name).append(";\n");
2179: }
2180: fBaseURIStack.push(identifier.getExpandedSystemId());
2181: }
2182:
2183: /**
2184: * This method notifies the end of a parameter entity. Parameter entity
2185: * names begin with a '%' character.
2186: *
2187: * @param name The name of the parameter entity.
2188: * @param augs Additional information that may include infoset
2189: * augmentations.
2190: *
2191: * @throws XNIException Thrown by handler to signal an error.
2192: */
2193: public void endParameterEntity(String name, Augmentations augs)
2194: throws XNIException {
2195:
2196: if (DEBUG_EVENTS) {
2197: System.out.println("==>endParameterEntity: " + name);
2198: }
2199: fBaseURIStack.pop();
2200: }
2201:
2202: /**
2203: * An unparsed entity declaration.
2204: *
2205: * @param name The name of the entity.
2206: * @param identifier An object containing all location information
2207: * pertinent to this entity.
2208: * @param notation The name of the notation.
2209: * @param augs Additional information that may include infoset
2210: * augmentations.
2211: *
2212: * @throws XNIException Thrown by handler to signal an error.
2213: */
2214: public void unparsedEntityDecl(String name,
2215: XMLResourceIdentifier identifier, String notation,
2216: Augmentations augs) throws XNIException {
2217:
2218: if (DEBUG_EVENTS) {
2219: System.out.println("==>unparsedEntityDecl: " + name);
2220: if (DEBUG_BASEURI) {
2221: System.out.println(" expandedSystemId:"
2222: + identifier.getExpandedSystemId());
2223: System.out.println(" baseURI:"
2224: + identifier.getBaseSystemId());
2225: }
2226: }
2227: // internal subset string
2228: String publicId = identifier.getPublicId();
2229: String literalSystemId = identifier.getLiteralSystemId();
2230: if (fInternalSubset != null && !fInDTDExternalSubset) {
2231: fInternalSubset.append("<!ENTITY ");
2232: fInternalSubset.append(name);
2233: fInternalSubset.append(' ');
2234: if (publicId != null) {
2235: fInternalSubset.append("PUBLIC '");
2236: fInternalSubset.append(publicId);
2237: if (literalSystemId != null) {
2238: fInternalSubset.append("' '");
2239: fInternalSubset.append(literalSystemId);
2240: }
2241: } else {
2242: fInternalSubset.append("SYSTEM '");
2243: fInternalSubset.append(literalSystemId);
2244: }
2245: fInternalSubset.append("' NDATA ");
2246: fInternalSubset.append(notation);
2247: fInternalSubset.append(">\n");
2248: }
2249:
2250: // NOTE: We only know how to create these nodes for the Xerces
2251: // DOM implementation because DOM Level 2 does not specify
2252: // that functionality. -Ac
2253:
2254: // create full node
2255: if (fDocumentType != null) {
2256: NamedNodeMap entities = fDocumentType.getEntities();
2257: EntityImpl entity = (EntityImpl) entities
2258: .getNamedItem(name);
2259: if (entity == null) {
2260: entity = (EntityImpl) fDocumentImpl.createEntity(name);
2261: entity.setPublicId(publicId);
2262: entity.setSystemId(literalSystemId);
2263: entity.setNotationName(notation);
2264: entity.setBaseURI(identifier.getBaseSystemId());
2265: entities.setNamedItem(entity);
2266: }
2267: }
2268:
2269: // create deferred node
2270: if (fDocumentTypeIndex != -1) {
2271: boolean found = false;
2272: int nodeIndex = fDeferredDocumentImpl.getLastChild(
2273: fDocumentTypeIndex, false);
2274: while (nodeIndex != -1) {
2275: short nodeType = fDeferredDocumentImpl.getNodeType(
2276: nodeIndex, false);
2277: if (nodeType == Node.ENTITY_NODE) {
2278: String nodeName = fDeferredDocumentImpl
2279: .getNodeName(nodeIndex, false);
2280: if (nodeName.equals(name)) {
2281: found = true;
2282: break;
2283: }
2284: }
2285: nodeIndex = fDeferredDocumentImpl.getRealPrevSibling(
2286: nodeIndex, false);
2287: }
2288: if (!found) {
2289: int entityIndex = fDeferredDocumentImpl
2290: .createDeferredEntity(name, publicId,
2291: literalSystemId, notation, identifier
2292: .getBaseSystemId());
2293: fDeferredDocumentImpl.appendChild(fDocumentTypeIndex,
2294: entityIndex);
2295: }
2296: }
2297:
2298: } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
2299:
2300: /**
2301: * A notation declaration
2302: *
2303: * @param name The name of the notation.
2304: * @param identifier An object containing all location information
2305: * pertinent to this notation.
2306: * @param augs Additional information that may include infoset
2307: * augmentations.
2308: *
2309: * @throws XNIException Thrown by handler to signal an error.
2310: */
2311: public void notationDecl(String name,
2312: XMLResourceIdentifier identifier, Augmentations augs)
2313: throws XNIException {
2314:
2315: // internal subset string
2316: String publicId = identifier.getPublicId();
2317: String literalSystemId = identifier.getLiteralSystemId();
2318: if (fInternalSubset != null && !fInDTDExternalSubset) {
2319: fInternalSubset.append("<!NOTATION ");
2320: fInternalSubset.append(name);
2321: if (publicId != null) {
2322: fInternalSubset.append(" PUBLIC '");
2323: fInternalSubset.append(publicId);
2324: if (literalSystemId != null) {
2325: fInternalSubset.append("' '");
2326: fInternalSubset.append(literalSystemId);
2327: }
2328: } else {
2329: fInternalSubset.append(" SYSTEM '");
2330: fInternalSubset.append(literalSystemId);
2331: }
2332: fInternalSubset.append("'>\n");
2333: }
2334:
2335: // NOTE: We only know how to create these nodes for the Xerces
2336: // DOM implementation because DOM Level 2 does not specify
2337: // that functionality. -Ac
2338:
2339: // create full node
2340: if (fDocumentImpl != null && fDocumentType != null) {
2341: NamedNodeMap notations = fDocumentType.getNotations();
2342: if (notations.getNamedItem(name) == null) {
2343: NotationImpl notation = (NotationImpl) fDocumentImpl
2344: .createNotation(name);
2345: notation.setPublicId(publicId);
2346: notation.setSystemId(literalSystemId);
2347: notation.setBaseURI(identifier.getBaseSystemId());
2348: notations.setNamedItem(notation);
2349: }
2350: }
2351:
2352: // create deferred node
2353: if (fDocumentTypeIndex != -1) {
2354: boolean found = false;
2355: int nodeIndex = fDeferredDocumentImpl.getLastChild(
2356: fDocumentTypeIndex, false);
2357: while (nodeIndex != -1) {
2358: short nodeType = fDeferredDocumentImpl.getNodeType(
2359: nodeIndex, false);
2360: if (nodeType == Node.NOTATION_NODE) {
2361: String nodeName = fDeferredDocumentImpl
2362: .getNodeName(nodeIndex, false);
2363: if (nodeName.equals(name)) {
2364: found = true;
2365: break;
2366: }
2367: }
2368: nodeIndex = fDeferredDocumentImpl.getPrevSibling(
2369: nodeIndex, false);
2370: }
2371: if (!found) {
2372: int notationIndex = fDeferredDocumentImpl
2373: .createDeferredNotation(name, publicId,
2374: literalSystemId, identifier
2375: .getBaseSystemId());
2376: fDeferredDocumentImpl.appendChild(fDocumentTypeIndex,
2377: notationIndex);
2378: }
2379: }
2380:
2381: } // notationDecl(String,XMLResourceIdentifier, Augmentations)
2382:
2383: /**
2384: * Characters within an IGNORE conditional section.
2385: *
2386: * @param text The ignored text.
2387: * @param augs Additional information that may include infoset
2388: * augmentations.
2389: *
2390: * @throws XNIException Thrown by handler to signal an error.
2391: */
2392: public void ignoredCharacters(XMLString text, Augmentations augs)
2393: throws XNIException {
2394: } // ignoredCharacters(XMLString, Augmentations)
2395:
2396: /**
2397: * An element declaration.
2398: *
2399: * @param name The name of the element.
2400: * @param contentModel The element content model.
2401: * @param augs Additional information that may include infoset
2402: * augmentations.
2403: *
2404: * @throws XNIException Thrown by handler to signal an error.
2405: */
2406: public void elementDecl(String name, String contentModel,
2407: Augmentations augs) throws XNIException {
2408:
2409: // internal subset string
2410: if (fInternalSubset != null && !fInDTDExternalSubset) {
2411: fInternalSubset.append("<!ELEMENT ");
2412: fInternalSubset.append(name);
2413: fInternalSubset.append(' ');
2414: fInternalSubset.append(contentModel);
2415: fInternalSubset.append(">\n");
2416: }
2417:
2418: } // elementDecl(String,String)
2419:
2420: /**
2421: * An attribute declaration.
2422: *
2423: * @param elementName The name of the element that this attribute
2424: * is associated with.
2425: * @param attributeName The name of the attribute.
2426: * @param type The attribute type. This value will be one of
2427: * the following: "CDATA", "ENTITY", "ENTITIES",
2428: * "ENUMERATION", "ID", "IDREF", "IDREFS",
2429: * "NMTOKEN", "NMTOKENS", or "NOTATION".
2430: * @param enumeration If the type has the value "ENUMERATION" or
2431: * "NOTATION", this array holds the allowed attribute
2432: * values; otherwise, this array is null.
2433: * @param defaultType The attribute default type. This value will be
2434: * one of the following: "#FIXED", "#IMPLIED",
2435: * "#REQUIRED", or null.
2436: * @param defaultValue The attribute default value, or null if no
2437: * default value is specified.
2438: * @param nonNormalizedDefaultValue The attribute default value with no normalization
2439: * performed, or null if no default value is specified.
2440: * @param augs Additional information that may include infoset
2441: * augmentations.
2442: *
2443: * @throws XNIException Thrown by handler to signal an error.
2444: */
2445: public void attributeDecl(String elementName, String attributeName,
2446: String type, String[] enumeration, String defaultType,
2447: XMLString defaultValue,
2448: XMLString nonNormalizedDefaultValue, Augmentations augs)
2449: throws XNIException {
2450:
2451: // internal subset string
2452: if (fInternalSubset != null && !fInDTDExternalSubset) {
2453: fInternalSubset.append("<!ATTLIST ");
2454: fInternalSubset.append(elementName);
2455: fInternalSubset.append(' ');
2456: fInternalSubset.append(attributeName);
2457: fInternalSubset.append(' ');
2458: if (type.equals("ENUMERATION")) {
2459: fInternalSubset.append('(');
2460: for (int i = 0; i < enumeration.length; i++) {
2461: if (i > 0) {
2462: fInternalSubset.append('|');
2463: }
2464: fInternalSubset.append(enumeration[i]);
2465: }
2466: fInternalSubset.append(')');
2467: } else {
2468: fInternalSubset.append(type);
2469: }
2470: if (defaultType != null) {
2471: fInternalSubset.append(' ');
2472: fInternalSubset.append(defaultType);
2473: }
2474: if (defaultValue != null) {
2475: fInternalSubset.append(" '");
2476: for (int i = 0; i < defaultValue.length; i++) {
2477: char c = defaultValue.ch[defaultValue.offset + i];
2478: if (c == '\'') {
2479: fInternalSubset.append("'");
2480: } else {
2481: fInternalSubset.append(c);
2482: }
2483: }
2484: fInternalSubset.append('\'');
2485: }
2486: fInternalSubset.append(">\n");
2487: }
2488: // REVISIT: This code applies to the support of domx/grammar-access
2489: // feature in Xerces 1
2490:
2491: // deferred expansion
2492: if (fDeferredDocumentImpl != null) {
2493:
2494: // get the default value
2495: if (defaultValue != null) {
2496:
2497: // get element definition
2498: int elementDefIndex = fDeferredDocumentImpl
2499: .lookupElementDefinition(elementName);
2500:
2501: // create element definition if not already there
2502: if (elementDefIndex == -1) {
2503: elementDefIndex = fDeferredDocumentImpl
2504: .createDeferredElementDefinition(elementName);
2505: fDeferredDocumentImpl.appendChild(
2506: fDocumentTypeIndex, elementDefIndex);
2507: }
2508: // add default attribute
2509: int attrIndex = fDeferredDocumentImpl
2510: .createDeferredAttribute(attributeName,
2511: defaultValue.toString(), false);
2512: if ("ID".equals(type)) {
2513: fDeferredDocumentImpl.setIdAttribute(attrIndex);
2514: }
2515: // REVISIT: set ID type correctly
2516: fDeferredDocumentImpl.appendChild(elementDefIndex,
2517: attrIndex);
2518: }
2519:
2520: } // if deferred
2521:
2522: // full expansion
2523: else if (fDocumentImpl != null) {
2524:
2525: // get the default value
2526: if (defaultValue != null) {
2527:
2528: // get element definition node
2529: NamedNodeMap elements = ((DocumentTypeImpl) fDocumentType)
2530: .getElements();
2531: ElementDefinitionImpl elementDef = (ElementDefinitionImpl) elements
2532: .getNamedItem(elementName);
2533: if (elementDef == null) {
2534: elementDef = fDocumentImpl
2535: .createElementDefinition(elementName);
2536: ((DocumentTypeImpl) fDocumentType).getElements()
2537: .setNamedItem(elementDef);
2538: }
2539:
2540: // REVISIT: Check for uniqueness of element name? -Ac
2541:
2542: // create attribute and set properties
2543: boolean nsEnabled = fNamespaceAware;
2544: AttrImpl attr;
2545: if (nsEnabled) {
2546: String namespaceURI = null;
2547: // DOM Level 2 wants all namespace declaration attributes
2548: // to be bound to "http://www.w3.org/2000/xmlns/"
2549: // So as long as the XML parser doesn't do it, it needs to
2550: // done here.
2551: if (attributeName.startsWith("xmlns:")
2552: || attributeName.equals("xmlns")) {
2553: namespaceURI = NamespaceContext.XMLNS_URI;
2554: }
2555: attr = (AttrImpl) fDocumentImpl.createAttributeNS(
2556: namespaceURI, attributeName);
2557: } else {
2558: attr = (AttrImpl) fDocumentImpl
2559: .createAttribute(attributeName);
2560: }
2561: attr.setValue(defaultValue.toString());
2562: attr.setSpecified(false);
2563: attr.setIdAttribute("ID".equals(type));
2564:
2565: // add default attribute to element definition
2566: if (nsEnabled) {
2567: elementDef.getAttributes().setNamedItemNS(attr);
2568: } else {
2569: elementDef.getAttributes().setNamedItem(attr);
2570: }
2571: }
2572:
2573: } // if NOT defer-node-expansion
2574:
2575: } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
2576:
2577: /**
2578: * The start of an attribute list.
2579: *
2580: * @param elementName The name of the element that this attribute
2581: * list is associated with.
2582: * @param augs Additional information that may include infoset
2583: * augmentations.
2584: *
2585: * @throws XNIException Thrown by handler to signal an error.
2586: */
2587: public void startAttlist(String elementName, Augmentations augs)
2588: throws XNIException {
2589: } // startAttlist(String)
2590:
2591: /**
2592: * The end of an attribute list.
2593: *
2594: * @param augs Additional information that may include infoset
2595: * augmentations.
2596: *
2597: * @throws XNIException Thrown by handler to signal an error.
2598: */
2599: public void endAttlist(Augmentations augs) throws XNIException {
2600: } // endAttlist()
2601:
2602: // method to create an element node.
2603: // subclasses can override this method to create element nodes in other ways.
2604: protected Element createElementNode(QName element) {
2605: Element el = null;
2606:
2607: if (fNamespaceAware) {
2608: // if we are using xerces DOM implementation, call our
2609: // own constructor to reuse the strings we have here.
2610: if (fDocumentImpl != null) {
2611: el = fDocumentImpl.createElementNS(element.uri,
2612: element.rawname, element.localpart);
2613: } else {
2614: el = fDocument.createElementNS(element.uri,
2615: element.rawname);
2616: }
2617: } else {
2618: el = fDocument.createElement(element.rawname);
2619: }
2620:
2621: return el;
2622: }
2623:
2624: // method to create an attribute node.
2625: // subclasses can override this method to create attribute nodes in other ways.
2626: protected Attr createAttrNode(QName attrQName) {
2627: Attr attr = null;
2628:
2629: if (fNamespaceAware) {
2630: if (fDocumentImpl != null) {
2631: // if we are using xerces DOM implementation, call our
2632: // own constructor to reuse the strings we have here.
2633: attr = fDocumentImpl.createAttributeNS(attrQName.uri,
2634: attrQName.rawname, attrQName.localpart);
2635: } else {
2636: attr = fDocument.createAttributeNS(attrQName.uri,
2637: attrQName.rawname);
2638: }
2639: } else {
2640: attr = fDocument.createAttribute(attrQName.rawname);
2641: }
2642:
2643: return attr;
2644: }
2645:
2646: /*
2647: * When the first characters() call is received, the data is stored in
2648: * a new Text node. If right after the first characters() we receive another chunk of data,
2649: * the data from the Text node, following the new characters are appended
2650: * to the fStringBuffer and the text node data is set to empty.
2651: *
2652: * This function is called when the state is changed and the
2653: * data must be appended to the current node.
2654: *
2655: * Note: if DOMFilter is set, you must make sure that if Node is skipped,
2656: * or removed fFistChunk must be set to true, otherwise some data can be lost.
2657: *
2658: */
2659: protected void setCharacterData(boolean sawChars) {
2660:
2661: // handle character data
2662: fFirstChunk = sawChars;
2663:
2664: // if we have data in the buffer we must have created
2665: // a text node already.
2666:
2667: Node child = fCurrentNode.getLastChild();
2668: if (child != null) {
2669: if (fStringBuffer.length() > 0) {
2670: // REVISIT: should this check be performed?
2671: if (child.getNodeType() == Node.TEXT_NODE) {
2672: if (fDocumentImpl != null) {
2673: ((TextImpl) child).replaceData(fStringBuffer
2674: .toString());
2675: } else {
2676: ((Text) child)
2677: .setData(fStringBuffer.toString());
2678: }
2679: }
2680: // reset string buffer
2681: fStringBuffer.setLength(0);
2682: }
2683:
2684: if (fDOMFilter != null && !fInEntityRef) {
2685: if ((child.getNodeType() == Node.TEXT_NODE)
2686: && ((fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT) != 0)) {
2687: short code = fDOMFilter.acceptNode(child);
2688: switch (code) {
2689: case LSParserFilter.FILTER_INTERRUPT: {
2690: throw ABORT;
2691: }
2692: case LSParserFilter.FILTER_REJECT: {
2693: // fall through to SKIP since Comment has no children.
2694: }
2695: case LSParserFilter.FILTER_SKIP: {
2696: fCurrentNode.removeChild(child);
2697: return;
2698: }
2699: default: {
2700: // accept node -- do nothing
2701: }
2702: }
2703: }
2704: } // end-if fDOMFilter !=null
2705:
2706: } // end-if child !=null
2707: }
2708:
2709: /**
2710: * @see org.w3c.dom.ls.LSParser#abort()
2711: */
2712: public void abort() {
2713: throw ABORT;
2714: }
2715:
2716: } // class AbstractDOMParser
|