/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001, 2002 The Apache Software Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.parsers;
import java.util.Locale;
import java.util.Stack;
import org.apache.xerces.dom.AttrImpl;
import org.apache.xerces.dom.CoreDocumentImpl;
import org.apache.xerces.dom.DOMErrorImpl;
import org.apache.xerces.dom.DeferredDocumentImpl;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xerces.dom.DocumentTypeImpl;
import org.apache.xerces.dom.ElementDefinitionImpl;
import org.apache.xerces.dom.ElementImpl;
import org.apache.xerces.dom.ElementNSImpl;
import org.apache.xerces.dom.EntityImpl;
import org.apache.xerces.dom.EntityReferenceImpl;
import org.apache.xerces.dom.NodeImpl;
import org.apache.xerces.dom.NotationImpl;
import org.apache.xerces.dom.PSVIAttrNSImpl;
import org.apache.xerces.dom.PSVIElementNSImpl;
import org.apache.xerces.dom.ProcessingInstructionImpl;
import org.apache.xerces.dom.TextImpl;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.xs.psvi.XSTypeDefinition;
import org.apache.xerces.util.DOMErrorHandlerWrapper;
import org.apache.xerces.util.ObjectFactory;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLParserConfiguration;
import org.apache.xerces.xni.psvi.AttributePSVI;
import org.apache.xerces.xni.psvi.ElementPSVI;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.ls.DOMBuilderFilter;
import org.w3c.dom.traversal.NodeFilter;
/**
* This is the base class of all DOM parsers. It implements the XNI
* callback methods to create the DOM tree. After a successful parse of
* an XML document, the DOM Document object can be queried using the
* <code>getDocument</code> method. The actual pipeline is defined in
* parser configuration.
*
* @author Arnaud Le Hors, IBM
* @author Andy Clark, IBM
* @author Elena Litani, IBM
*
* @version $Id: AbstractDOMParser.java,v 1.84 2003/03/24 14:28:44 elena Exp $
*/
public class AbstractDOMParser extends AbstractXMLDocumentParser {
//
// Constants
//
// feature ids
/** Feature id: namespace. */
protected static final String NAMESPACES =
Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
/** Feature id: create entity ref nodes. */
protected static final String CREATE_ENTITY_REF_NODES =
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
/** Feature id: include comments. */
protected static final String INCLUDE_COMMENTS_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
/** Feature id: create cdata nodes. */
protected static final String CREATE_CDATA_NODES_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
/** Feature id: include ignorable whitespace. */
protected static final String INCLUDE_IGNORABLE_WHITESPACE =
Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
/** Feature id: defer node expansion. */
protected static final String DEFER_NODE_EXPANSION =
Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
/** Recognized features. */
private static final String[] RECOGNIZED_FEATURES = {
NAMESPACES,
CREATE_ENTITY_REF_NODES,
INCLUDE_COMMENTS_FEATURE,
CREATE_CDATA_NODES_FEATURE,
INCLUDE_IGNORABLE_WHITESPACE,
DEFER_NODE_EXPANSION
};
// property ids
/** Property id: document class name. */
protected static final String DOCUMENT_CLASS_NAME =
Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
protected static final String CURRENT_ELEMENT_NODE=
Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
// protected static final String GRAMMAR_POOL =
// Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
/** Recognized properties. */
private static final String[] RECOGNIZED_PROPERTIES = {
DOCUMENT_CLASS_NAME,
CURRENT_ELEMENT_NODE,
};
// other
/** Default document class name. */
protected static final String DEFAULT_DOCUMENT_CLASS_NAME =
"org.apache.xerces.dom.DocumentImpl";
protected static final String CORE_DOCUMENT_CLASS_NAME =
"org.apache.xerces.dom.CoreDocumentImpl";
protected static final String PSVI_DOCUMENT_CLASS_NAME =
"org.apache.xerces.dom.PSVIDocumentImpl";
// debugging
private static final boolean DEBUG_EVENTS = false;
private static final boolean DEBUG_BASEURI = false;
//
// Data
//
/** DOM L3 error handler */
protected DOMErrorHandlerWrapper fErrorHandler = null;
/** True if inside DTD. */
protected boolean fInDTD;
// features
/** Create entity reference nodes. */
protected boolean fCreateEntityRefNodes;
/** Include ignorable whitespace. */
protected boolean fIncludeIgnorableWhitespace;
/** Include Comments. */
protected boolean fIncludeComments;
/** Create cdata nodes. */
protected boolean fCreateCDATANodes;
// dom information
/** The document. */
protected Document fDocument;
/** The default Xerces document implementation, if used. */
protected CoreDocumentImpl fDocumentImpl;
/** Whether to store PSVI information in DOM tree. */
protected boolean fStorePSVI;
/** The document class name to use. */
protected String fDocumentClassName;
/** The document type node. */
protected DocumentType fDocumentType;
/** Current node. */
protected Node fCurrentNode;
protected CDATASection fCurrentCDATASection;
protected EntityImpl fCurrentEntityDecl;
protected int fDeferredEntityDecl;
/** Character buffer */
protected final StringBuffer fStringBuffer = new StringBuffer(50);
// internal subset
/** Internal subset buffer. */
protected StringBuffer fInternalSubset;
// deferred expansion data
protected boolean fDeferNodeExpansion;
protected boolean fNamespaceAware;
protected DeferredDocumentImpl fDeferredDocumentImpl;
protected int fDocumentIndex;
protected int fDocumentTypeIndex;
protected int fCurrentNodeIndex;
protected int fCurrentCDATASectionIndex;
// state
/** True if inside DTD external subset. */
protected boolean fInDTDExternalSubset;
/** True if inside document. */
protected boolean fInDocument;
/** True if inside CDATA section. */
protected boolean fInCDATASection;
/** True if saw the first chunk of characters*/
protected boolean fFirstChunk = false;
/** DOMBuilderFilter: specifies that element with given QNAME and all its children
must be rejected */
protected boolean fFilterReject = false;
// data
/** Base uri stack*/
protected Stack fBaseURIStack = new Stack();
/** DOMBuilderFilter: the QNAME of rejected element*/
protected final QName fRejectedElement = new QName();
/** DOMBuilderFilter: store qnames of skipped elements*/
protected Stack fSkippedElemStack = null;
/** Attribute QName. */
private QName fAttrQName = new QName();
// handlers
protected DOMBuilderFilter fDOMFilter = null;
//
// Constructors
//
/** Default constructor. */
protected AbstractDOMParser(XMLParserConfiguration config) {
super(config);
// add recognized features
fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES);
// set default values
fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, true);
fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
fConfiguration.setFeature(DEFER_NODE_EXPANSION, true);
fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, true);
// add recognized properties
fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);
// set default values
fConfiguration.setProperty(DOCUMENT_CLASS_NAME,
DEFAULT_DOCUMENT_CLASS_NAME);
} // <init>(XMLParserConfiguration)
/**
* This method retreives the name of current document class.
*/
protected String getDocumentClassName() {
return fDocumentClassName;
}
/**
* This method allows the programmer to decide which document
* factory to use when constructing the DOM tree. However, doing
* so will lose the functionality of the default factory. Also,
* a document class other than the default will lose the ability
* to defer node expansion on the DOM tree produced.
*
* @param documentClassName The fully qualified class name of the
* document factory to use when constructing
* the DOM tree.
*
* @see #getDocumentClassName
* @see #DEFAULT_DOCUMENT_CLASS_NAME
*/
protected void setDocumentClassName(String documentClassName) {
// normalize class name
if (documentClassName == null) {
documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
}
// verify that this class exists and is of the right type
try {
Class _class = ObjectFactory.findProviderClass(documentClassName,
ObjectFactory.findClassLoader(), true);
//if (!_class.isAssignableFrom(Document.class)) {
if (!Document.class.isAssignableFrom(_class)) {
// REVISIT: message
throw new IllegalArgumentException("PAR002 Class, \"" +
documentClassName +
"\", is not of type org.w3c.dom.Document.\n" +
documentClassName);
}
}
catch (ClassNotFoundException e) {
// REVISIT: message
throw new IllegalArgumentException("PAR003 Class, \"" +
documentClassName +
"\", not found.\n" +
documentClassName);
}
// set document class name
fDocumentClassName = documentClassName;
if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
fDeferNodeExpansion = false;
}
} // setDocumentClassName(String)
//
// Public methods
//
/** Returns the DOM document object. */
public Document getDocument() {
return fDocument;
} // getDocument():Document
//
// XMLDocumentParser methods
//
/**
* Resets the parser state.
*
* @throws SAXException Thrown on initialization error.
*/
public void reset() throws XNIException {
super.reset();
// get feature state
fCreateEntityRefNodes =
fConfiguration.getFeature(CREATE_ENTITY_REF_NODES);
fIncludeIgnorableWhitespace =
fConfiguration.getFeature(INCLUDE_IGNORABLE_WHITESPACE);
fDeferNodeExpansion =
fConfiguration.getFeature(DEFER_NODE_EXPANSION);
fNamespaceAware = fConfiguration.getFeature(NAMESPACES);
fIncludeComments = fConfiguration.getFeature(INCLUDE_COMMENTS_FEATURE);
fCreateCDATANodes = fConfiguration.getFeature(CREATE_CDATA_NODES_FEATURE);
// get property
setDocumentClassName((String)
fConfiguration.getProperty(DOCUMENT_CLASS_NAME));
// reset dom information
fDocument = null;
fDocumentImpl = null;
fStorePSVI = false;
fDocumentType = null;
fDocumentTypeIndex = -1;
fDeferredDocumentImpl = null;
fCurrentNode = null;
// reset string buffer
fStringBuffer.setLength(0);
// reset state information
fInDocument = false;
fInDTD = false;
fInDTDExternalSubset = false;
fInCDATASection = false;
fFirstChunk = false;
fCurrentCDATASection = null;
fCurrentCDATASectionIndex = -1;
fBaseURIStack.removeAllElements();
} // reset()
/**
* Set the locale to use for messages.
*
* @param locale The locale object to use for localization of messages.
*
*/
public void setLocale(Locale locale) {
fConfiguration.setLocale(locale);
} // setLocale(Locale)
//
// XMLDocumentHandler methods
//
/**
* This method notifies the start of a general entity.
* <p>
* <strong>Note:</strong> This method is not called for entity references
* appearing as part of attribute values.
*
* @param name The name of the general entity.
* @param identifier The resource identifier.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal entities or a document entity that is
* parsed from a java.io.Reader).
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException Thrown by handler to signal an error.
*/
public void startGeneralEntity(String name,
XMLResourceIdentifier identifier,
String encoding, Augmentations augs)
throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startGeneralEntity ("+name+")");
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId());
System.out.println(" baseURI:"+ identifier.getBaseSystemId());
}
}
// Always create entity reference nodes to be able to recreate
// entity as a part of doctype
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
setCharacterData(true);
EntityReference er = fDocument.createEntityReference(name);
if (fDocumentImpl != null) {
// REVISIT: baseURI/actualEncoding
// remove dependency on our implementation when DOM L3 is REC
//
EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
// set base uri
erImpl.setBaseURI(identifier.getExpandedSystemId());
if (fDocumentType != null) {
// set actual encoding
NamedNodeMap entities = fDocumentType.getEntities();
fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name);
if (fCurrentEntityDecl != null) {
fCurrentEntityDecl.setActualEncoding(encoding);
}
}
// we don't need synchronization now, because entity ref will be
// expanded anyway. Synch only needed when user creates entityRef node
erImpl.needsSyncChildren(false);
}
fCurrentNode.appendChild(er);
fCurrentNode = er;
}
else {
int er =
fDeferredDocumentImpl.createDeferredEntityReference(name, identifier.getExpandedSystemId());
if (fDocumentTypeIndex != -1) {
// find corresponding Entity decl
int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (node != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
if (nodeType == Node.ENTITY_NODE) {
String nodeName =
fDeferredDocumentImpl.getNodeName(node, false);
if (nodeName.equals(name)) {
fDeferredEntityDecl = node;
fDeferredDocumentImpl.setActualEncoding(node, encoding);
break;
}
}
node = fDeferredDocumentImpl.getRealPrevSibling(node, false);
}
}
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, er);
fCurrentNodeIndex = er;
}
} // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
/**
* Notifies of the presence of a TextDecl line in an entity. If present,
* this method will be called immediately following the startEntity call.
* <p>
* <strong>Note:</strong> This method will never be called for the
* document entity; it is only called for external general entities
* referenced in document content.
* <p>
* <strong>Note:</strong> This method is not called for entity references
* appearing as part of attribute values.
*
* @param version The XML version, or null if not specified.
* @param encoding The IANA encoding name of the entity.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
if (fInDTD){
return;
}
if (!fDeferNodeExpansion) {
if (fCurrentEntityDecl != null && !fFilterReject) {
fCurrentEntityDecl.setEncoding(encoding);
fCurrentEntityDecl.setVersion(version);
}
}
else {
if (fDeferredEntityDecl !=-1) {
fDeferredDocumentImpl.setEntityInfo(fDeferredEntityDecl, version, encoding);
}
}
} // textDecl(String,String)
/**
* A comment.
*
* @param text The text in the comment.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by application to signal an error.
*/
public void comment(XMLString text, Augmentations augs) throws XNIException {
if (fInDTD) {
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!-- ");
fInternalSubset.append(text.toString());
fInternalSubset.append(" -->");
}
return;
}
if (!fIncludeComments || fFilterReject) {
return;
}
if (!fDeferNodeExpansion) {
Comment comment = fDocument.createComment(text.toString());
setCharacterData(false);
fCurrentNode.appendChild(comment);
if (fDOMFilter !=null &&
(fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT)!= 0) {
short code = fDOMFilter.acceptNode(comment);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
// REVISIT: the constant FILTER_REJECT should be changed when new
// DOM LS specs gets published
// fall through to SKIP since comment has no children.
}
case DOMBuilderFilter.FILTER_SKIP: {
// REVISIT: the constant FILTER_SKIP should be changed when new
// DOM LS specs gets published
fCurrentNode.removeChild(comment);
// make sure we don't loose chars if next event is characters()
fFirstChunk = true;
return;
}
default: {
// accept node
}
}
}
}
else {
int comment =
fDeferredDocumentImpl.createDeferredComment(text.toString());
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, comment);
}
} // comment(XMLString)
/**
* A processing instruction. Processing instructions consist of a
* target name and, optionally, text data. The data is only meaningful
* to the application.
* <p>
* Typically, a processing instruction's data will contain a series
* of pseudo-attributes. These pseudo-attributes follow the form of
* element attributes but are <strong>not</strong> parsed or presented
* to the application as anything other than text. The application is
* responsible for parsing the data.
*
* @param target The target.
* @param data The data or null if none specified.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void processingInstruction(String target, XMLString data, Augmentations augs)
throws XNIException {
if (fInDTD) {
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<?");
fInternalSubset.append(target.toString());
fInternalSubset.append(' ');
fInternalSubset.append(data.toString());
fInternalSubset.append("?>");
}
return;
}
if (DEBUG_EVENTS) {
System.out.println("==>processingInstruction ("+target+")");
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
ProcessingInstruction pi =
fDocument.createProcessingInstruction(target, data.toString());
setCharacterData(false);
fCurrentNode.appendChild(pi);
if (fDOMFilter !=null &&
(fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
short code = fDOMFilter.acceptNode(pi);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
// fall through to SKIP since PI has no children.
}
case DOMBuilderFilter.FILTER_SKIP: {
fCurrentNode.removeChild(pi);
// fFirstChunk must be set to true so that data
// won't be lost in the case where the child before PI is
// a text node and the next event is characters.
fFirstChunk = true;
return;
}
default: {
}
}
}
}
else {
int pi = fDeferredDocumentImpl.
createDeferredProcessingInstruction(target, data.toString());
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
}
} // processingInstruction(String,XMLString)
/**
* The start of the document.
*
* @param locator The system identifier of the entity if the entity
* is external, null otherwise.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal entities or a document entity that is
* parsed from a java.io.Reader).
* @param namespaceContext
* The namespace context in effect at the
* start of this document.
* This object represents the current context.
* Implementors of this class are responsible
* for copying the namespace bindings from the
* the current context (and its parent contexts)
* if that information is important.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {
fInDocument = true;
if (!fDeferNodeExpansion) {
if (fDocumentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME)) {
fDocument = new DocumentImpl();
fDocumentImpl = (CoreDocumentImpl)fDocument;
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
// set DOM error checking off
fDocumentImpl.setStrictErrorChecking(false);
// set actual encoding
fDocumentImpl.setActualEncoding(encoding);
// set documentURI
fDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
}
else {
// use specified document class
try {
Class documentClass = ObjectFactory.findProviderClass(fDocumentClassName,
ObjectFactory.findClassLoader(), true);
fDocument = (Document)documentClass.newInstance();
// if subclass of our own class that's cool too
Class defaultDocClass =
ObjectFactory.findProviderClass(CORE_DOCUMENT_CLASS_NAME,
ObjectFactory.findClassLoader(), true);
if (defaultDocClass.isAssignableFrom(documentClass)) {
fDocumentImpl = (CoreDocumentImpl)fDocument;
Class psviDocClass = ObjectFactory.findProviderClass(PSVI_DOCUMENT_CLASS_NAME,
ObjectFactory.findClassLoader(), true);
if (psviDocClass.isAssignableFrom(documentClass)) {
fStorePSVI = true;
}
// REVISIT: when DOM Level 3 is REC rely on
// Document.support instead of specific class
// set DOM error checking off
fDocumentImpl.setStrictErrorChecking(false);
// set actual encoding
fDocumentImpl.setActualEncoding(encoding);
// set documentURI
if (locator != null) {
fDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
}
}
}
catch (ClassNotFoundException e) {
// won't happen we already checked that earlier
}
catch (Exception e) {
// REVISIT: Localize this message.
throw new RuntimeException(
"Failed to create document object of class: "
+ fDocumentClassName);
}
}
fCurrentNode = fDocument;
}
else {
fDeferredDocumentImpl = new DeferredDocumentImpl(fNamespaceAware);
fDocument = fDeferredDocumentImpl;
fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument();
// REVISIT: strict error checking is not implemented in deferred dom.
// Document.support instead of specific class
// set actual encoding
fDeferredDocumentImpl.setActualEncoding(encoding);
// set documentURI
fDeferredDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
fCurrentNodeIndex = fDocumentIndex;
}
} // startDocument(String,String)
/**
* Notifies of the presence of an XMLDecl line in the document. If
* present, this method will be called immediately following the
* startDocument call.
*
* @param version The XML version.
* @param encoding The IANA encoding name of the document, or null if
* not specified.
* @param standalone The standalone value, or null if not specified.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void xmlDecl(String version, String encoding, String standalone,
Augmentations augs)
throws XNIException {
if (!fDeferNodeExpansion) {
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
if (fDocumentImpl != null) {
fDocumentImpl.setVersion(version);
fDocumentImpl.setEncoding(encoding);
fDocumentImpl.setStandalone("true".equals(standalone));
}
}
else {
fDeferredDocumentImpl.setVersion(version);
fDeferredDocumentImpl.setEncoding(encoding);
fDeferredDocumentImpl.setStandalone("true".equals(standalone));
}
} // xmlDecl(String,String,String)
/**
* Notifies of the presence of the DOCTYPE line in the document.
*
* @param rootElement The name of the root element.
* @param publicId The public identifier if an external DTD or null
* if the external DTD is specified using SYSTEM.
* @param systemId The system identifier if an external DTD, null
* otherwise.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void doctypeDecl(String rootElement,
String publicId, String systemId, Augmentations augs)
throws XNIException {
if (!fDeferNodeExpansion) {
if (fDocumentImpl != null) {
fDocumentType = fDocumentImpl.createDocumentType(
rootElement, publicId, systemId);
fCurrentNode.appendChild(fDocumentType);
}
}
else {
fDocumentTypeIndex = fDeferredDocumentImpl.
createDeferredDocumentType(rootElement, publicId, systemId);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, fDocumentTypeIndex);
}
} // doctypeDecl(String,String,String)
/**
* The start of an element. If the document specifies the start element
* by using an empty tag, then the startElement method will immediately
* be followed by the endElement method, with no intervening methods.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startElement ("+element.rawname+")");
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
Element el = createElementNode(element);
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount; i++) {
attributes.getName(i, fAttrQName);
Attr attr = createAttrNode(fAttrQName);
String attrValue = attributes.getValue(i);
AttributePSVI attrPSVI =(AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
if (fStorePSVI && attrPSVI != null){
((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
}
attr.setValue(attrValue);
el.setAttributeNode(attr);
// NOTE: The specified value MUST be set after you set
// the node value because that turns the "specified"
// flag to "true" which may overwrite a "false"
// value from the attribute list. -Ac
if (fDocumentImpl != null) {
AttrImpl attrImpl = (AttrImpl) attr;
Object type = null;
boolean id = false;
// REVISIT: currently it is possible that someone turns off
// namespaces and turns on xml schema validation
// To avoid classcast exception in AttrImpl check for namespaces
// however the correct solution should probably disallow setting
// namespaces to false when schema processing is turned on.
if (attrPSVI != null && fNamespaceAware) {
// XML Schema
type = attrPSVI.getMemberTypeDefinition();
if (type == null) {
type = attrPSVI.getTypeDefinition();
if (type != null) {
id = ((XSSimpleType) type).isIDType();
attrImpl.setType(type);
}
}
else {
id = ((XSSimpleType) type).isIDType();
attrImpl.setType(type);
}
}
else {
// DTD
type = attributes.getType(i);
attrImpl.setType(type);
id = (type.equals("ID")) ? true : false;
}
if (id) {
((ElementImpl) el).setIdAttributeNode(attr, true);
}
attrImpl.setSpecified(attributes.isSpecified(i));
// REVISIT: Handle entities in attribute value.
}
}
setCharacterData(false);
if (augs != null) {
ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null && fNamespaceAware) {
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
((ElementNSImpl)el).setType(type);
}
}
// filter nodes
if (fDOMFilter != null) {
short code = fDOMFilter.startElement(el);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
fFilterReject = true;
fRejectedElement.setValues(element);
return;
}
case DOMBuilderFilter.FILTER_SKIP: {
fSkippedElemStack.push(element);
return;
}
default: {
}
}
}
fCurrentNode.appendChild(el);
fCurrentNode = el;
}
else {
Object type = null;
if (augs != null) {
ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
}
}
int el =
fDeferredDocumentImpl.createDeferredElement(fNamespaceAware ?
element.uri : null,
element.rawname,
type);
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount; i++) {
// set type information
AttributePSVI attrPSVI = (AttributePSVI)attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
boolean id = false;
// REVISIT: currently it is possible that someone turns off
// namespaces and turns on xml schema validation
// To avoid classcast exception in AttrImpl check for namespaces
// however the correct solution should probably disallow setting
// namespaces to false when schema processing is turned on.
if (attrPSVI != null && fNamespaceAware) {
// XML Schema
type = attrPSVI.getMemberTypeDefinition();
if (type == null) {
type = attrPSVI.getTypeDefinition();
if (type != null){
id = ((XSSimpleType) type).isIDType();
}
}
else {
id = ((XSSimpleType) type).isIDType();
}
}
else {
// DTD
type = attributes.getType(i);
id = (type.equals("ID")) ? true : false;
}
// create attribute
fDeferredDocumentImpl.setDeferredAttribute(
el,
attributes.getQName(i),
attributes.getURI(i),
attributes.getValue(i),
attributes.isSpecified(i),
id,
type);
}
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, el);
fCurrentNodeIndex = el;
}
} // startElement(QName,XMLAttributes)
/**
* An empty element.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
startElement(element, attributes, augs);
endElement(element, augs);
} // emptyElement(QName,XMLAttributes)
/**
* Character content.
*
* @param text The content.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void characters(XMLString text, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>characters(): "+text.toString());
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
if (fInCDATASection && fCreateCDATANodes) {
if (fCurrentCDATASection == null) {
fCurrentCDATASection =
fDocument.createCDATASection(text.toString());
fCurrentNode.appendChild(fCurrentCDATASection);
fCurrentNode = fCurrentCDATASection;
}
else {
fCurrentCDATASection.appendData(text.toString());
}
}
else if (!fInDTD) {
// if type is union (XML Schema) it is possible that we receive
// character call with empty data
if (text.length == 0) {
return;
}
String value = text.toString();
Node child = fCurrentNode.getLastChild();
if (child != null && child.getNodeType() == Node.TEXT_NODE) {
// collect all the data into the string buffer.
if (fFirstChunk) {
if (fDocumentImpl != null) {
fStringBuffer.append(((TextImpl)child).removeData());
} else {
fStringBuffer.append(((Text)child).getData());
((Text)child).setNodeValue(null);
}
fFirstChunk = false;
}
fStringBuffer.append(value);
}
else {
fFirstChunk = true;
Text textNode = fDocument.createTextNode(value);
fCurrentNode.appendChild(textNode);
}
}
}
else {
// The Text and CDATASection normalization is taken care of within
// the DOM in the deferred case.
if (fInCDATASection && fCreateCDATANodes) {
if (fCurrentCDATASectionIndex == -1) {
int cs = fDeferredDocumentImpl.
createDeferredCDATASection(text.toString());
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, cs);
fCurrentCDATASectionIndex = cs;
fCurrentNodeIndex = cs;
}
else {
int txt = fDeferredDocumentImpl.
createDeferredTextNode(text.toString(), false);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
}
} else if (!fInDTD) {
// if type is union (XML Schema) it is possible that we receive
// character call with empty data
if (text.length == 0) {
return;
}
String value = text.toString();
int txt = fDeferredDocumentImpl.
createDeferredTextNode(value, false);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
}
}
} // characters(XMLString)
/**
* Ignorable whitespace. For this method to be called, the document
* source must have some way of determining that the text containing
* only whitespace characters should be considered ignorable. For
* example, the validator can determine if a length of whitespace
* characters in the document are ignorable based on the element
* content model.
*
* @param text The ignorable whitespace.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
if (!fIncludeIgnorableWhitespace || fFilterReject) {
return;
}
if (!fDeferNodeExpansion) {
Node child = fCurrentNode.getLastChild();
if (child != null && child.getNodeType() == Node.TEXT_NODE) {
Text textNode = (Text)child;
textNode.appendData(text.toString());
}
else {
Text textNode = fDocument.createTextNode(text.toString());
if (fDocumentImpl != null) {
TextImpl textNodeImpl = (TextImpl)textNode;
textNodeImpl.setIgnorableWhitespace(true);
}
fCurrentNode.appendChild(textNode);
}
}
else {
// The Text normalization is taken care of within the DOM in the
// deferred case.
int txt = fDeferredDocumentImpl.
createDeferredTextNode(text.toString(), true);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
}
} // ignorableWhitespace(XMLString)
/**
* The end of an element.
*
* @param element The name of the element.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endElement(QName element, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endElement ("+element.rawname+")");
}
if (!fDeferNodeExpansion) {
// REVISIT: Should this happen after we call the filter?
if (fStorePSVI && augs != null) {
ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI);
}
}
if (fDOMFilter != null) {
if (fFilterReject) {
if (element.equals(fRejectedElement)) {
fFilterReject = false;
}
return;
}
if (!fSkippedElemStack.isEmpty()) {
if (fSkippedElemStack.peek().equals(element)) {
fSkippedElemStack.pop();
return;
}
}
setCharacterData(false);
if ((fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT)!=0) {
short code = fDOMFilter.acceptNode(fCurrentNode);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
Node parent = fCurrentNode.getParentNode();
parent.removeChild(fCurrentNode);
fCurrentNode = parent;
return;
}
case DOMBuilderFilter.FILTER_SKIP: {
// make sure that if any char data is available
// the fFirstChunk is true, so that if the next event
// is characters(), and the last node is text, we will copy
// the value already in the text node to fStringBuffer
// (not to loose it).
fFirstChunk = true;
// replace children
Node parent = fCurrentNode.getParentNode();
NodeList ls = fCurrentNode.getChildNodes();
int length = ls.getLength();
for (int i=0;i<length;i++) {
parent.appendChild(ls.item(0));
}
parent.removeChild(fCurrentNode);
fCurrentNode = parent;
return;
}
default: { }
}
}
fCurrentNode = fCurrentNode.getParentNode();
} // end-if DOMFilter
else {
setCharacterData(false);
fCurrentNode = fCurrentNode.getParentNode();
}
}
else {
fCurrentNodeIndex =
fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex, false);
}
} // endElement(QName)
/**
* The start of a CDATA section.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startCDATA(Augmentations augs) throws XNIException {
fInCDATASection = true;
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
setCharacterData(false);
}
} // startCDATA()
/**
* The end of a CDATA section.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endCDATA(Augmentations augs) throws XNIException {
fInCDATASection = false;
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
if (fCurrentCDATASection !=null) {
if (fDOMFilter !=null &&
(fDOMFilter.getWhatToShow() & NodeFilter.SHOW_CDATA_SECTION)!= 0) {
short code = fDOMFilter.acceptNode(fCurrentCDATASection);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
// fall through to SKIP since CDATA section has no children.
}
case DOMBuilderFilter.FILTER_SKIP: {
Node parent = fCurrentNode.getParentNode();
parent.removeChild(fCurrentCDATASection);
fCurrentNode = parent;
return;
}
default: {
// accept node
}
}
}
fCurrentNode = fCurrentNode.getParentNode();
fCurrentCDATASection = null;
}
}
else {
if (fCurrentCDATASectionIndex !=-1) {
fCurrentNodeIndex =
fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex, false);
fCurrentCDATASectionIndex = -1;
}
}
} // endCDATA()
/**
* The end of the document.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endDocument(Augmentations augs) throws XNIException {
fInDocument = false;
if (!fDeferNodeExpansion) {
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
// set DOM error checking back on
if (fDocumentImpl != null) {
fDocumentImpl.setStrictErrorChecking(true);
}
fCurrentNode = null;
}
else {
fCurrentNodeIndex = -1;
}
} // endDocument()
/**
* This method notifies the end of a general entity.
* <p>
* <strong>Note:</strong> This method is not called for entity references
* appearing as part of attribute values.
*
* @param name The name of the entity.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endGeneralEntity: ("+name+")");
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
setCharacterData(true);
if (fDocumentType != null) {
// get current entity declaration
NamedNodeMap entities = fDocumentType.getEntities();
fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name);
if (fCurrentEntityDecl != null) {
if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild() == null) {
fCurrentEntityDecl.setReadOnly(false, true);
Node child = fCurrentNode.getFirstChild();
while (child != null) {
Node copy = child.cloneNode(true);
fCurrentEntityDecl.appendChild(copy);
child = child.getNextSibling();
}
fCurrentEntityDecl.setReadOnly(true, true);
//entities.setNamedItem(fCurrentEntityDecl);
}
fCurrentEntityDecl = null;
}
}
boolean removeEntityRef = false;
if (fCreateEntityRefNodes) {
if (fDocumentImpl != null) {
// Make entity ref node read only
((NodeImpl)fCurrentNode).setReadOnly(true, true);
}
if (fDOMFilter !=null &&
(fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) {
short code = fDOMFilter.acceptNode(fCurrentNode);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
Node parent = fCurrentNode.getParentNode();
parent.removeChild(fCurrentNode);
fCurrentNode = parent;
return;
}
case DOMBuilderFilter.FILTER_SKIP: {
// make sure we don't loose chars if next event is characters()
fFirstChunk = true;
removeEntityRef = true;
break;
}
default: {
fCurrentNode = fCurrentNode.getParentNode();
}
}
} else {
fCurrentNode = fCurrentNode.getParentNode();
}
}
if (!fCreateEntityRefNodes || removeEntityRef) {
// move entity reference children to the list of
// siblings of its parent and remove entity reference
NodeList children = fCurrentNode.getChildNodes();
Node parent = fCurrentNode.getParentNode();
int length = children.getLength();
if (length > 0) {
// get previous sibling of the entity reference
Node node = fCurrentNode.getPreviousSibling();
// normalize text nodes
Node child = children.item(0);
if (node != null && node.getNodeType() == Node.TEXT_NODE &&
child.getNodeType() == Node.TEXT_NODE) {
((Text)node).appendData(child.getNodeValue());
fCurrentNode.removeChild(child);
} else {
node = parent.insertBefore(child, fCurrentNode);
handleBaseURI(node);
}
for (int i=1;i <length;i++) {
node = parent.insertBefore(children.item(0), fCurrentNode);
handleBaseURI(node);
}
} // length > 0
parent.removeChild(fCurrentNode);
fCurrentNode = parent;
}
}
else {
if (fDocumentTypeIndex != -1) {
// find corresponding Entity decl
int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (node != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
if (nodeType == Node.ENTITY_NODE) {
String nodeName =
fDeferredDocumentImpl.getNodeName(node, false);
if (nodeName.equals(name)) {
fDeferredEntityDecl = node;
break;
}
}
node = fDeferredDocumentImpl.getRealPrevSibling(node, false);
}
}
if (fDeferredEntityDecl != -1 &&
fDeferredDocumentImpl.getLastChild(fDeferredEntityDecl, false) == -1) {
// entity definition exists and it does not have any children
int prevIndex = -1;
int childIndex = fDeferredDocumentImpl.getLastChild(fCurrentNodeIndex, false);
while (childIndex != -1) {
int cloneIndex = fDeferredDocumentImpl.cloneNode(childIndex, true);
fDeferredDocumentImpl.insertBefore(fDeferredEntityDecl, cloneIndex, prevIndex);
prevIndex = cloneIndex;
childIndex = fDeferredDocumentImpl.getRealPrevSibling(childIndex, false);
}
}
if (fCreateEntityRefNodes) {
fCurrentNodeIndex =
fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex,
false);
} else { //!fCreateEntityRefNodes
// move children of entity ref before the entity ref.
// remove entity ref.
// holds a child of entity ref
int childIndex = fDeferredDocumentImpl.getLastChild(fCurrentNodeIndex, false);
int parentIndex =
fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex,
false);
int prevIndex = fCurrentNodeIndex;
int lastChild = childIndex;
int sibling = -1;
while (childIndex != -1) {
handleBaseURI(childIndex);
sibling = fDeferredDocumentImpl.getRealPrevSibling(childIndex, false);
fDeferredDocumentImpl.insertBefore(parentIndex, childIndex, prevIndex);
prevIndex = childIndex;
childIndex = sibling;
}
fDeferredDocumentImpl.setAsLastChild(parentIndex, lastChild);
fCurrentNodeIndex = parentIndex;
}
fDeferredEntityDecl = -1;
}
} // endGeneralEntity(String, Augmentations)
/**
* Record baseURI information for the Element (by adding xml:base attribute)
* or for the ProcessingInstruction (by setting a baseURI field)
* Non deferred DOM.
*
* @param node
*/
protected final void handleBaseURI (Node node){
if (fDocumentImpl != null) {
// REVISIT: remove dependency on our implementation when
// DOM L3 becomes REC
String baseURI = null;
short nodeType = node.getNodeType();
if (nodeType == Node.ELEMENT_NODE) {
// if an element already has xml:base attribute
// do nothing
if (fNamespaceAware) {
if (((Element)node).getAttributeNodeNS("http://www.w3.org/XML/1998/namespace","base")!=null) {
return;
}
} else if (((Element)node).getAttributeNode("xml:base") != null) {
return;
}
// retrive the baseURI from the entity reference
baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI();
if (baseURI !=null && !baseURI.equals(fDocumentImpl.getDocumentURI())) {
if (fNamespaceAware) {
((Element)node).setAttributeNS("http://www.w3.org/XML/1998/namespace","base", baseURI);
} else {
((Element)node).setAttribute("xml:base", baseURI);
}
}
}
else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI();
if (baseURI !=null && fErrorHandler != null) {
DOMErrorImpl error = new DOMErrorImpl();
error.fType = "infoset-baseURI";
error.fRelatedData = baseURI;
error.fSeverity = error.SEVERITY_WARNING;
fErrorHandler.getErrorHandler().handleError(error);
}
}
}
}
/**
*
* Record baseURI information for the Element (by adding xml:base attribute)
* or for the ProcessingInstruction (by setting a baseURI field)
* Deferred DOM.
*
* @param node
*/
protected final void handleBaseURI (int node){
short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
if (nodeType == Node.ELEMENT_NODE) {
String baseURI = fDeferredDocumentImpl.getNodeValueString(fCurrentNodeIndex, false);
if (baseURI == null) {
baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI(fDeferredEntityDecl);
}
if (baseURI !=null && !baseURI.equals(fDeferredDocumentImpl.getDocumentURI())) {
fDeferredDocumentImpl.setDeferredAttribute(node,
"xml:base",
"http://www.w3.org/XML/1998/namespace",
baseURI,
true);
}
}
else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
// retrieve baseURI from the entity reference
String baseURI = fDeferredDocumentImpl.getNodeValueString(fCurrentNodeIndex, false);
if (baseURI == null) {
// try baseURI of the entity declaration
baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI(fDeferredEntityDecl);
}
if (baseURI != null && fErrorHandler != null) {
DOMErrorImpl error = new DOMErrorImpl();
error.fType = "infoset-baseURI";
error.fRelatedData = baseURI;
error.fSeverity = error.SEVERITY_WARNING;
fErrorHandler.getErrorHandler().handleError(error);
}
}
}
//
// XMLDTDHandler methods
//
/**
* The start of the DTD.
*
* @param locator The document locator, or null if the document
* location cannot be reported during the parsing of
* the document DTD. However, it is <em>strongly</em>
* recommended that a locator be supplied that can
* at least report the base system identifier of the
* DTD.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startDTD");
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId: "+locator.getExpandedSystemId());
System.out.println(" baseURI:"+ locator.getBaseSystemId());
}
}
fInDTD = true;
if (locator != null) {
fBaseURIStack.push(locator.getBaseSystemId());
}
if (fDeferNodeExpansion || fDocumentImpl != null) {
fInternalSubset = new StringBuffer(1024);
}
} // startDTD(XMLLocator)
/**
* The end of the DTD.
*
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endDTD(Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endDTD()");
}
fInDTD = false;
if (!fBaseURIStack.isEmpty()) {
fBaseURIStack.pop();
}
String internalSubset = fInternalSubset != null && fInternalSubset.length() > 0
? fInternalSubset.toString() : null;
if (fDeferNodeExpansion) {
if (internalSubset != null) {
fDeferredDocumentImpl.setInternalSubset(fDocumentTypeIndex, internalSubset);
}
}
else if (fDocumentImpl != null) {
if (internalSubset != null) {
((DocumentTypeImpl)fDocumentType).setInternalSubset(internalSubset);
}
}
} // endDTD()
/**
* The start of a conditional section.
*
* @param type The type of the conditional section. This value will
* either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*
* @see #CONDITIONAL_INCLUDE
* @see #CONDITIONAL_IGNORE
*/
public void startConditional(short type, Augmentations augs) throws XNIException {
} // startConditional(short)
/**
* The end of a conditional section.
*
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endConditional(Augmentations augs) throws XNIException {
} // endConditional()
/**
* The start of the DTD external subset.
*
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startExternalSubset(XMLResourceIdentifier identifier,
Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startExternalSubset");
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId: "+identifier.getExpandedSystemId());
System.out.println(" baseURI:"+ identifier.getBaseSystemId());
}
}
fBaseURIStack.push(identifier.getBaseSystemId());
fInDTDExternalSubset = true;
} // startExternalSubset(Augmentations)
/**
* The end of the DTD external subset.
*
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endExternalSubset(Augmentations augs) throws XNIException {
fInDTDExternalSubset = false;
fBaseURIStack.pop();
} // endExternalSubset(Augmentations)
/**
* An internal entity declaration.
*
* @param name The name of the entity. Parameter entity names start with
* '%', whereas the name of a general entity is just the
* entity name.
* @param text The value of the entity.
* @param nonNormalizedText The non-normalized value of the entity. This
* value contains the same sequence of characters that was in
* the internal entity declaration, without any entity
* references expanded.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void internalEntityDecl(String name, XMLString text,
XMLString nonNormalizedText,
Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>internalEntityDecl: "+name);
if (DEBUG_BASEURI) {
System.out.println(" baseURI:"+ (String)fBaseURIStack.peek());
}
}
// internal subset string
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!ENTITY ");
if (name.startsWith("%")) {
fInternalSubset.append("% ");
fInternalSubset.append(name.substring(1));
}
else {
fInternalSubset.append(name);
}
fInternalSubset.append(' ');
String value = nonNormalizedText.toString();
boolean singleQuote = value.indexOf('\'') == -1;
fInternalSubset.append(singleQuote ? '\'' : '"');
fInternalSubset.append(value);
fInternalSubset.append(singleQuote ? '\'' : '"');
fInternalSubset.append(">\n");
}
// NOTE: We only know how to create these nodes for the Xerces
// DOM implementation because DOM Level 2 does not specify
// that functionality. -Ac
// create full node
// don't add parameter entities!
if(name.startsWith("%"))
return;
if (fDocumentType != null) {
NamedNodeMap entities = fDocumentType.getEntities();
EntityImpl entity = (EntityImpl)entities.getNamedItem(name);
if (entity == null) {
entity = (EntityImpl)fDocumentImpl.createEntity(name);
entity.setBaseURI((String)fBaseURIStack.peek());
entities.setNamedItem(entity);
}
}
// create deferred node
if (fDocumentTypeIndex != -1) {
boolean found = false;
int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (node != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(node, false);
if (nodeType == Node.ENTITY_NODE) {
String nodeName = fDeferredDocumentImpl.getNodeName(node, false);
if (nodeName.equals(name)) {
found = true;
break;
}
}
node = fDeferredDocumentImpl.getRealPrevSibling(node, false);
}
if (!found) {
int entityIndex =
fDeferredDocumentImpl.createDeferredEntity(name, null, null, null, (String)fBaseURIStack.peek());
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, entityIndex);
}
}
} // internalEntityDecl(String,XMLString,XMLString)
/**
* An external entity declaration.
*
* @param name The name of the entity. Parameter entity names start
* with '%', whereas the name of a general entity is just
* the entity name.
* @param identifier An object containing all location information
* pertinent to this notation.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void externalEntityDecl(String name, XMLResourceIdentifier identifier,
Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>externalEntityDecl: "+name);
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId:"+ identifier.getExpandedSystemId());
System.out.println(" baseURI:"+ identifier.getBaseSystemId());
}
}
// internal subset string
String publicId = identifier.getPublicId();
String literalSystemId = identifier.getLiteralSystemId();
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!ENTITY ");
if (name.startsWith("%")) {
fInternalSubset.append("% ");
fInternalSubset.append(name.substring(1));
}
else {
fInternalSubset.append(name);
}
fInternalSubset.append(' ');
if (publicId != null) {
fInternalSubset.append("PUBLIC '");
fInternalSubset.append(publicId);
fInternalSubset.append("' '");
}
else {
fInternalSubset.append("SYSTEM '");
}
fInternalSubset.append(literalSystemId);
fInternalSubset.append("'>\n");
}
// NOTE: We only know how to create these nodes for the Xerces
// DOM implementation because DOM Level 2 does not specify
// that functionality. -Ac
// create full node
// don't add parameter entities!
if(name.startsWith("%"))
return;
if (fDocumentType != null) {
NamedNodeMap entities = fDocumentType.getEntities();
EntityImpl entity = (EntityImpl)entities.getNamedItem(name);
if (entity == null) {
entity = (EntityImpl)fDocumentImpl.createEntity(name);
entity.setPublicId(publicId);
entity.setSystemId(literalSystemId);
entity.setBaseURI(identifier.getBaseSystemId());
entities.setNamedItem(entity);
}
}
// create deferred node
if (fDocumentTypeIndex != -1) {
boolean found = false;
int nodeIndex = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (nodeIndex != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(nodeIndex, false);
if (nodeType == Node.ENTITY_NODE) {
String nodeName = fDeferredDocumentImpl.getNodeName(nodeIndex, false);
if (nodeName.equals(name)) {
found = true;
break;
}
}
nodeIndex = fDeferredDocumentImpl.getRealPrevSibling(nodeIndex, false);
}
if (!found) {
int entityIndex = fDeferredDocumentImpl.createDeferredEntity(
name, publicId, literalSystemId, null, identifier.getBaseSystemId());
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, entityIndex);
}
}
} // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
/**
* This method notifies of the start of a parameter entity. The parameter
* entity name start with a '%' character.
*
* @param name The name of the parameter entity.
* @param identifier The resource identifier.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal parameter entities).
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startParameterEntity(String name,
XMLResourceIdentifier identifier,
String encoding,
Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startParameterEntity: "+name);
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId: "+identifier.getExpandedSystemId());
System.out.println(" baseURI:"+ identifier.getBaseSystemId());
}
}
fBaseURIStack.push(identifier.getExpandedSystemId());
}
/**
* This method notifies the end of a parameter entity. Parameter entity
* names begin with a '%' character.
*
* @param name The name of the parameter entity.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endParameterEntity(String name, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endParameterEntity: "+name);
}
fBaseURIStack.pop();
}
/**
* An unparsed entity declaration.
*
* @param name The name of the entity.
* @param identifier An object containing all location information
* pertinent to this entity.
* @param notation The name of the notation.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
String notation, Augmentations augs)
throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>unparsedEntityDecl: "+name);
if (DEBUG_BASEURI) {
System.out.println(" expandedSystemId:"+ identifier.getExpandedSystemId());
System.out.println(" baseURI:"+ identifier.getBaseSystemId());
}
}
// internal subset string
String publicId = identifier.getPublicId();
String literalSystemId = identifier.getLiteralSystemId();
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!ENTITY ");
fInternalSubset.append(name);
fInternalSubset.append(' ');
if (publicId != null) {
fInternalSubset.append("PUBLIC '");
fInternalSubset.append(publicId);
if (literalSystemId != null) {
fInternalSubset.append("' '");
fInternalSubset.append(literalSystemId);
}
}
else {
fInternalSubset.append("SYSTEM '");
fInternalSubset.append(literalSystemId);
}
fInternalSubset.append("' NDATA ");
fInternalSubset.append(notation);
fInternalSubset.append(">\n");
}
// NOTE: We only know how to create these nodes for the Xerces
// DOM implementation because DOM Level 2 does not specify
// that functionality. -Ac
// create full node
if (fDocumentType != null) {
NamedNodeMap entities = fDocumentType.getEntities();
EntityImpl entity = (EntityImpl)entities.getNamedItem(name);
if (entity == null) {
entity = (EntityImpl)fDocumentImpl.createEntity(name);
entity.setPublicId(publicId);
entity.setSystemId(literalSystemId);
entity.setNotationName(notation);
entity.setBaseURI(identifier.getBaseSystemId());
entities.setNamedItem(entity);
}
}
// create deferred node
if (fDocumentTypeIndex != -1) {
boolean found = false;
int nodeIndex = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (nodeIndex != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(nodeIndex, false);
if (nodeType == Node.ENTITY_NODE) {
String nodeName = fDeferredDocumentImpl.getNodeName(nodeIndex, false);
if (nodeName.equals(name)) {
found = true;
break;
}
}
nodeIndex = fDeferredDocumentImpl.getRealPrevSibling(nodeIndex, false);
}
if (!found) {
int entityIndex = fDeferredDocumentImpl.createDeferredEntity(
name, publicId, literalSystemId, notation, identifier.getBaseSystemId());
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, entityIndex);
}
}
} // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
/**
* A notation declaration
*
* @param name The name of the notation.
* @param identifier An object containing all location information
* pertinent to this notation.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void notationDecl(String name, XMLResourceIdentifier identifier,
Augmentations augs) throws XNIException {
// internal subset string
String publicId = identifier.getPublicId();
String literalSystemId = identifier.getLiteralSystemId();
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!NOTATION ");
fInternalSubset.append(name);
if (publicId != null) {
fInternalSubset.append(" PUBLIC '");
fInternalSubset.append(publicId);
if (literalSystemId != null) {
fInternalSubset.append("' '");
fInternalSubset.append(literalSystemId);
}
}
else {
fInternalSubset.append(" SYSTEM '");
fInternalSubset.append(literalSystemId);
}
fInternalSubset.append("'>\n");
}
// NOTE: We only know how to create these nodes for the Xerces
// DOM implementation because DOM Level 2 does not specify
// that functionality. -Ac
// create full node
if (fDocumentImpl !=null && fDocumentType != null) {
NamedNodeMap notations = fDocumentType.getNotations();
if (notations.getNamedItem(name) == null) {
NotationImpl notation = (NotationImpl)fDocumentImpl.createNotation(name);
notation.setPublicId(publicId);
notation.setSystemId(literalSystemId);
notation.setBaseURI(identifier.getBaseSystemId());
notations.setNamedItem(notation);
}
}
// create deferred node
if (fDocumentTypeIndex != -1) {
boolean found = false;
int nodeIndex = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false);
while (nodeIndex != -1) {
short nodeType = fDeferredDocumentImpl.getNodeType(nodeIndex, false);
if (nodeType == Node.NOTATION_NODE) {
String nodeName = fDeferredDocumentImpl.getNodeName(nodeIndex, false);
if (nodeName.equals(name)) {
found = true;
break;
}
}
nodeIndex = fDeferredDocumentImpl.getPrevSibling(nodeIndex, false);
}
if (!found) {
int notationIndex = fDeferredDocumentImpl.createDeferredNotation(
name, publicId, literalSystemId, identifier.getBaseSystemId());
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, notationIndex);
}
}
} // notationDecl(String,XMLResourceIdentifier, Augmentations)
/**
* Characters within an IGNORE conditional section.
*
* @param text The ignored text.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException {
} // ignoredCharacters(XMLString, Augmentations)
/**
* An element declaration.
*
* @param name The name of the element.
* @param contentModel The element content model.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void elementDecl(String name, String contentModel, Augmentations augs)
throws XNIException {
// internal subset string
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!ELEMENT ");
fInternalSubset.append(name);
fInternalSubset.append(' ');
fInternalSubset.append(contentModel);
fInternalSubset.append(">\n");
}
} // elementDecl(String,String)
/**
* An attribute declaration.
*
* @param elementName The name of the element that this attribute
* is associated with.
* @param attributeName The name of the attribute.
* @param type The attribute type. This value will be one of
* the following: "CDATA", "ENTITY", "ENTITIES",
* "ENUMERATION", "ID", "IDREF", "IDREFS",
* "NMTOKEN", "NMTOKENS", or "NOTATION".
* @param enumeration If the type has the value "ENUMERATION" or
* "NOTATION", this array holds the allowed attribute
* values; otherwise, this array is null.
* @param defaultType The attribute default type. This value will be
* one of the following: "#FIXED", "#IMPLIED",
* "#REQUIRED", or null.
* @param defaultValue The attribute default value, or null if no
* default value is specified.
* @param nonNormalizedDefaultValue The attribute default value with no normalization
* performed, or null if no default value is specified.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void attributeDecl(String elementName, String attributeName,
String type, String[] enumeration,
String defaultType, XMLString defaultValue,
XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
// internal subset string
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append("<!ATTLIST ");
fInternalSubset.append(elementName);
fInternalSubset.append(' ');
fInternalSubset.append(attributeName);
fInternalSubset.append(' ');
if (type.equals("ENUMERATION")) {
fInternalSubset.append('(');
for (int i = 0; i < enumeration.length; i++) {
if (i > 0) {
fInternalSubset.append('|');
}
fInternalSubset.append(enumeration[i]);
}
fInternalSubset.append(')');
}
else {
fInternalSubset.append(type);
}
if (defaultType != null) {
fInternalSubset.append(' ');
fInternalSubset.append(defaultType);
}
if (defaultValue != null) {
fInternalSubset.append(" '");
for (int i = 0; i < defaultValue.length; i++) {
char c = defaultValue.ch[defaultValue.offset + i];
if (c == '\'') {
fInternalSubset.append("'");
}
else {
fInternalSubset.append(c);
}
}
fInternalSubset.append('\'');
}
fInternalSubset.append(">\n");
}
// REVISIT: This code applies to the support of domx/grammar-access
// feature in Xerces 1
// deferred expansion
if (fDeferredDocumentImpl != null) {
// get the default value
if (defaultValue != null) {
// get element definition
int elementDefIndex = fDeferredDocumentImpl.lookupElementDefinition(elementName);
// create element definition if not already there
if (elementDefIndex == -1) {
elementDefIndex = fDeferredDocumentImpl.createDeferredElementDefinition(elementName);
fDeferredDocumentImpl.appendChild(fDocumentTypeIndex, elementDefIndex);
}
// add default attribute
int attrIndex = fDeferredDocumentImpl.createDeferredAttribute(
attributeName, defaultValue.toString(), false);
if (type.equals("ID")) {
fDeferredDocumentImpl.setIdAttribute(attrIndex);
}
// REVISIT: set ID type correctly
fDeferredDocumentImpl.appendChild(elementDefIndex, attrIndex);
}
} // if deferred
// full expansion
else if (fDocumentImpl != null) {
// get the default value
if (defaultValue != null) {
// get element definition node
NamedNodeMap elements = ((DocumentTypeImpl)fDocumentType).getElements();
ElementDefinitionImpl elementDef = (ElementDefinitionImpl)elements.getNamedItem(elementName);
if (elementDef == null) {
elementDef = fDocumentImpl.createElementDefinition(elementName);
((DocumentTypeImpl)fDocumentType).getElements().setNamedItem(elementDef);
}
// REVISIT: Check for uniqueness of element name? -Ac
// create attribute and set properties
boolean nsEnabled = fNamespaceAware;
AttrImpl attr;
if (nsEnabled) {
String namespaceURI = null;
// DOM Level 2 wants all namespace declaration attributes
// to be bound to "http://www.w3.org/2000/xmlns/"
// So as long as the XML parser doesn't do it, it needs to
// done here.
if (attributeName.startsWith("xmlns:") ||
attributeName.equals("xmlns")) {
namespaceURI = NamespaceContext.XMLNS_URI;
}
attr = (AttrImpl)fDocumentImpl.createAttributeNS(namespaceURI,
attributeName);
}
else {
attr = (AttrImpl)fDocumentImpl.createAttribute(attributeName);
}
attr.setValue(defaultValue.toString());
attr.setSpecified(false);
attr.setIdAttribute(type.equals("ID"));
// add default attribute to element definition
if (nsEnabled){
elementDef.getAttributes().setNamedItemNS(attr);
}
else {
elementDef.getAttributes().setNamedItem(attr);
}
}
} // if NOT defer-node-expansion
} // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
/**
* The start of an attribute list.
*
* @param elementName The name of the element that this attribute
* list is associated with.
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startAttlist(String elementName, Augmentations augs) throws XNIException {
} // startAttlist(String)
/**
* The end of an attribute list.
*
* @param augs Additional information that may include infoset
* augmentations.
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endAttlist(Augmentations augs) throws XNIException {
} // endAttlist()
// method to create an element node.
// subclasses can override this method to create element nodes in other ways.
protected Element createElementNode(QName element) {
Element el = null;
if (fNamespaceAware) {
// if we are using xerces DOM implementation, call our
// own constructor to reuse the strings we have here.
if (fDocumentImpl != null) {
el = fDocumentImpl.createElementNS(element.uri, element.rawname,
element.localpart);
}
else {
el = fDocument.createElementNS(element.uri, element.rawname);
}
}
else {
el = fDocument.createElement(element.rawname);
}
return el;
}
// method to create an attribute node.
// subclasses can override this method to create attribute nodes in other ways.
protected Attr createAttrNode(QName attrQName) {
Attr attr = null;
if (fNamespaceAware) {
if (fDocumentImpl != null) {
// if we are using xerces DOM implementation, call our
// own constructor to reuse the strings we have here.
attr = fDocumentImpl.createAttributeNS(attrQName.uri,
attrQName.rawname,
attrQName.localpart);
}
else {
attr = fDocument.createAttributeNS(attrQName.uri,
attrQName.rawname);
}
}
else {
attr = fDocument.createAttribute(attrQName.rawname);
}
return attr;
}
/*
* When the first characters() call is received, the data is stored in
* a new Text node. If right after the first characters() we receive another chunk of data,
* the data from the Text node, following the new characters are appended
* to the fStringBuffer and the text node data is set to empty.
*
* This function is called when the state is changed and the
* data must be appended to the current node.
*
* Note: if DOMFilter is set, you must make sure that if Node is skipped,
* or removed fFistChunk must be set to true, otherwise some data can be lost.
*
*/
protected void setCharacterData(boolean sawChars){
// handle character data
fFirstChunk = sawChars;
// if we have data in the buffer we must have created
// a text node already.
Node child = fCurrentNode.getLastChild();
if (child != null) {
if (fStringBuffer.length() > 0) {
// REVISIT: should this check be performed?
if (child.getNodeType() == Node.TEXT_NODE) {
if (fDocumentImpl != null) {
((TextImpl)child).replaceData(fStringBuffer.toString());
}
else {
((Text)child).setData(fStringBuffer.toString());
}
}
// reset string buffer
fStringBuffer.setLength(0);
}
if (fDOMFilter !=null) {
if ((fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT)!= 0) {
short code = fDOMFilter.acceptNode(child);
switch (code) {
case DOMBuilderFilter.FILTER_INTERRUPT:{
throw new RuntimeException("The normal processing of the document was interrupted.");
}
case DOMBuilderFilter.FILTER_REJECT:{
// fall through to SKIP since Comment has no children.
}
case DOMBuilderFilter.FILTER_SKIP: {
fCurrentNode.removeChild(child);
return;
}
default: {
// accept node -- do nothing
}
}
}
} // end-if fDOMFilter !=null
} // end-if child !=null
}
/**
* @see org.w3c.dom.ls.DOMBuilder#abort()
*/
public void abort() {
throw new RuntimeException();
}
} // class AbstractDOMParser