diff options
Diffstat (limited to 'src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java')
-rw-r--r-- | src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java | 1765 |
1 files changed, 0 insertions, 1765 deletions
diff --git a/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java b/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java deleted file mode 100644 index 0e871e0..0000000 --- a/src/com/sun/org/apache/xml/internal/dtm/ref/dom2dtm/DOM2DTM.java +++ /dev/null @@ -1,1765 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: DOM2DTM.java,v 1.2.4.1 2005/09/15 08:15:10 suresh_emailid Exp $ - */ -package com.sun.org.apache.xml.internal.dtm.ref.dom2dtm; - -import java.util.Vector; - -import javax.xml.transform.SourceLocator; -import javax.xml.transform.dom.DOMSource; - -import com.sun.org.apache.xml.internal.dtm.DTM; -import com.sun.org.apache.xml.internal.dtm.DTMManager; -import com.sun.org.apache.xml.internal.dtm.DTMWSFilter; -import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators; -import com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault; -import com.sun.org.apache.xml.internal.dtm.ref.ExpandedNameTable; -import com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource; -import com.sun.org.apache.xml.internal.res.XMLErrorResources; -import com.sun.org.apache.xml.internal.res.XMLMessages; -import com.sun.org.apache.xml.internal.utils.FastStringBuffer; -import com.sun.org.apache.xml.internal.utils.QName; -import com.sun.org.apache.xml.internal.utils.StringBufferPool; -import com.sun.org.apache.xml.internal.utils.TreeWalker; -import com.sun.org.apache.xml.internal.utils.XMLCharacterRecognizer; -import com.sun.org.apache.xml.internal.utils.XMLString; -import com.sun.org.apache.xml.internal.utils.XMLStringFactory; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentType; -import org.w3c.dom.Element; -import org.w3c.dom.Entity; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.ContentHandler; - -/** The <code>DOM2DTM</code> class serves up a DOM's contents via the - * DTM API. - * - * Note that it doesn't necessarily represent a full Document - * tree. You can wrap a DOM2DTM around a specific node and its subtree - * and the right things should happen. (I don't _think_ we currently - * support DocumentFrgment nodes as roots, though that might be worth - * considering.) - * - * Note too that we do not currently attempt to track document - * mutation. If you alter the DOM after wrapping DOM2DTM around it, - * all bets are off. - * */ -public class DOM2DTM extends DTMDefaultBaseIterators -{ - static final boolean JJK_DEBUG=false; - static final boolean JJK_NEWCODE=true; - - /** Manefest constant - */ - static final String NAMESPACE_DECL_NS="http://www.w3.org/XML/1998/namespace"; - - /** The current position in the DOM tree. Last node examined for - * possible copying to DTM. */ - transient private Node m_pos; - /** The current position in the DTM tree. Who children get appended to. */ - private int m_last_parent=0; - /** The current position in the DTM tree. Who children reference as their - * previous sib. */ - private int m_last_kid=NULL; - - /** The top of the subtree. - * %REVIEW%: 'may not be the same as m_context if "//foo" pattern.' - * */ - transient private Node m_root; - - /** True iff the first element has been processed. This is used to control - synthesis of the implied xml: namespace declaration node. */ - boolean m_processedFirstElement=false; - - /** true if ALL the nodes in the m_root subtree have been processed; - * false if our incremental build has not yet finished scanning the - * DOM tree. */ - transient private boolean m_nodesAreProcessed; - - /** The node objects. The instance part of the handle indexes - * directly into this vector. Each DTM node may actually be - * composed of several DOM nodes (for example, if logically-adjacent - * Text/CDATASection nodes in the DOM have been coalesced into a - * single DTM Text node); this table points only to the first in - * that sequence. */ - protected Vector m_nodes = new Vector(); - - /** - * Construct a DOM2DTM object from a DOM node. - * - * @param mgr The DTMManager who owns this DTM. - * @param domSource the DOM source that this DTM will wrap. - * @param dtmIdentity The DTM identity ID for this DTM. - * @param whiteSpaceFilter The white space filter for this DTM, which may - * be null. - * @param xstringfactory XMLString factory for creating character content. - * @param doIndexing true if the caller considers it worth it to use - * indexing schemes. - */ - public DOM2DTM(DTMManager mgr, DOMSource domSource, - int dtmIdentity, DTMWSFilter whiteSpaceFilter, - XMLStringFactory xstringfactory, - boolean doIndexing) - { - super(mgr, domSource, dtmIdentity, whiteSpaceFilter, - xstringfactory, doIndexing); - - // Initialize DOM navigation - m_pos=m_root = domSource.getNode(); - // Initialize DTM navigation - m_last_parent=m_last_kid=NULL; - m_last_kid=addNode(m_root, m_last_parent,m_last_kid, NULL); - - // Apparently the domSource root may not actually be the - // Document node. If it's an Element node, we need to immediately - // add its attributes. Adapted from nextNode(). - // %REVIEW% Move this logic into addNode and recurse? Cleaner! - // - // (If it's an EntityReference node, we're probably scrod. For now - // I'm just hoping nobody is ever quite that foolish... %REVIEW%) - // - // %ISSUE% What about inherited namespaces in this case? - // Do we need to special-case initialize them into the DTM model? - if(ELEMENT_NODE == m_root.getNodeType()) - { - NamedNodeMap attrs=m_root.getAttributes(); - int attrsize=(attrs==null) ? 0 : attrs.getLength(); - if(attrsize>0) - { - int attrIndex=NULL; // start with no previous sib - for(int i=0;i<attrsize;++i) - { - // No need to force nodetype in this case; - // addNode() will take care of switching it from - // Attr to Namespace if necessary. - attrIndex=addNode(attrs.item(i),0,attrIndex,NULL); - m_firstch.setElementAt(DTM.NULL,attrIndex); - } - // Terminate list of attrs, and make sure they aren't - // considered children of the element - m_nextsib.setElementAt(DTM.NULL,attrIndex); - - // IMPORTANT: This does NOT change m_last_parent or m_last_kid! - } // if attrs exist - } //if(ELEMENT_NODE) - - // Initialize DTM-completed status - m_nodesAreProcessed = false; - } - - /** - * Construct the node map from the node. - * - * @param node The node that is to be added to the DTM. - * @param parentIndex The current parent index. - * @param previousSibling The previous sibling index. - * @param forceNodeType If not DTM.NULL, overrides the DOM node type. - * Used to force nodes to Text rather than CDATASection when their - * coalesced value includes ordinary Text nodes (current DTM behavior). - * - * @return The index identity of the node that was added. - */ - protected int addNode(Node node, int parentIndex, - int previousSibling, int forceNodeType) - { - int nodeIndex = m_nodes.size(); - - // Have we overflowed a DTM Identity's addressing range? - if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS)) - { - try - { - if(m_mgr==null) - throw new ClassCastException(); - - // Handle as Extended Addressing - DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr; - int id=mgrD.getFirstFreeDTMID(); - mgrD.addDTM(this,id,nodeIndex); - m_dtmIdent.addElement(id<<DTMManager.IDENT_DTM_NODE_BITS); - } - catch(ClassCastException e) - { - // %REVIEW% Wrong error message, but I've been told we're trying - // not to add messages right not for I18N reasons. - // %REVIEW% Should this be a Fatal Error? - error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available"; - } - } - - m_size++; - // ensureSize(nodeIndex); - - int type; - if(NULL==forceNodeType) - type = node.getNodeType(); - else - type=forceNodeType; - - // %REVIEW% The Namespace Spec currently says that Namespaces are - // processed in a non-namespace-aware manner, by matching the - // QName, even though there is in fact a namespace assigned to - // these nodes in the DOM. If and when that changes, we will have - // to consider whether we check the namespace-for-namespaces - // rather than the node name. - // - // %TBD% Note that the DOM does not necessarily explicitly declare - // all the namespaces it uses. DOM Level 3 will introduce a - // namespace-normalization operation which reconciles that, and we - // can request that users invoke it or otherwise ensure that the - // tree is namespace-well-formed before passing the DOM to Xalan. - // But if they don't, what should we do about it? We probably - // don't want to alter the source DOM (and may not be able to do - // so if it's read-only). The best available answer might be to - // synthesize additional DTM Namespace Nodes that don't correspond - // to DOM Attr Nodes. - if (Node.ATTRIBUTE_NODE == type) - { - String name = node.getNodeName(); - - if (name.startsWith("xmlns:") || name.equals("xmlns")) - { - type = DTM.NAMESPACE_NODE; - } - } - - m_nodes.addElement(node); - - m_firstch.setElementAt(NOTPROCESSED,nodeIndex); - m_nextsib.setElementAt(NOTPROCESSED,nodeIndex); - m_prevsib.setElementAt(previousSibling,nodeIndex); - m_parent.setElementAt(parentIndex,nodeIndex); - - if(DTM.NULL != parentIndex && - type != DTM.ATTRIBUTE_NODE && - type != DTM.NAMESPACE_NODE) - { - // If the DTM parent had no children, this becomes its first child. - if(NOTPROCESSED == m_firstch.elementAt(parentIndex)) - m_firstch.setElementAt(nodeIndex,parentIndex); - } - - String nsURI = node.getNamespaceURI(); - - // Deal with the difference between Namespace spec and XSLT - // definitions of local name. (The former says PIs don't have - // localnames; the latter says they do.) - String localName = (type == Node.PROCESSING_INSTRUCTION_NODE) ? - node.getNodeName() : - node.getLocalName(); - - // Hack to make DOM1 sort of work... - if(((type == Node.ELEMENT_NODE) || (type == Node.ATTRIBUTE_NODE)) - && null == localName) - localName = node.getNodeName(); // -sb - - ExpandedNameTable exnt = m_expandedNameTable; - - // %TBD% Nodes created with the old non-namespace-aware DOM - // calls createElement() and createAttribute() will never have a - // localname. That will cause their expandedNameID to be just the - // nodeType... which will keep them from being matched - // successfully by name. Since the DOM makes no promise that - // those will participate in namespace processing, this is - // officially accepted as Not Our Fault. But it might be nice to - // issue a diagnostic message! - if(node.getLocalName()==null && - (type==Node.ELEMENT_NODE || type==Node.ATTRIBUTE_NODE)) - { - // warning("DOM 'level 1' node "+node.getNodeName()+" won't be mapped properly in DOM2DTM."); - } - - int expandedNameID = (null != localName) - ? exnt.getExpandedTypeID(nsURI, localName, type) : - exnt.getExpandedTypeID(type); - - m_exptype.setElementAt(expandedNameID,nodeIndex); - - indexNode(expandedNameID, nodeIndex); - - if (DTM.NULL != previousSibling) - m_nextsib.setElementAt(nodeIndex,previousSibling); - - // This should be done after m_exptype has been set, and probably should - // always be the last thing we do - if (type == DTM.NAMESPACE_NODE) - declareNamespaceInContext(parentIndex,nodeIndex); - - return nodeIndex; - } - - /** - * Get the number of nodes that have been added. - */ - public int getNumberOfNodes() - { - return m_nodes.size(); - } - - /** - * This method iterates to the next node that will be added to the table. - * Each call to this method adds a new node to the table, unless the end - * is reached, in which case it returns null. - * - * @return The true if a next node is found or false if - * there are no more nodes. - */ - protected boolean nextNode() - { - // Non-recursive one-fetch-at-a-time depth-first traversal with - // attribute/namespace nodes and white-space stripping. - // Navigating the DOM is simple, navigating the DTM is simple; - // keeping track of both at once is a trifle baroque but at least - // we've avoided most of the special cases. - if (m_nodesAreProcessed) - return false; - - // %REVIEW% Is this local copy Really Useful from a performance - // point of view? Or is this a false microoptimization? - Node pos=m_pos; - Node next=null; - int nexttype=NULL; - - // Navigate DOM tree - do - { - // Look down to first child. - if (pos.hasChildNodes()) - { - next = pos.getFirstChild(); - - // %REVIEW% There's probably a more elegant way to skip - // the doctype. (Just let it go and Suppress it? - if(next!=null && DOCUMENT_TYPE_NODE==next.getNodeType()) - next=next.getNextSibling(); - - // Push DTM context -- except for children of Entity References, - // which have no DTM equivalent and cause no DTM navigation. - if(ENTITY_REFERENCE_NODE!=pos.getNodeType()) - { - m_last_parent=m_last_kid; - m_last_kid=NULL; - // Whitespace-handler context stacking - if(null != m_wsfilter) - { - short wsv = - m_wsfilter.getShouldStripSpace(makeNodeHandle(m_last_parent),this); - boolean shouldStrip = (DTMWSFilter.INHERIT == wsv) - ? getShouldStripWhitespace() - : (DTMWSFilter.STRIP == wsv); - pushShouldStripWhitespace(shouldStrip); - } // if(m_wsfilter) - } - } - - // If that fails, look up and right (but not past root!) - else - { - if(m_last_kid!=NULL) - { - // Last node posted at this level had no more children - // If it has _no_ children, we need to record that. - if(m_firstch.elementAt(m_last_kid)==NOTPROCESSED) - m_firstch.setElementAt(NULL,m_last_kid); - } - - while(m_last_parent != NULL) - { - // %REVIEW% There's probably a more elegant way to - // skip the doctype. (Just let it go and Suppress it? - next = pos.getNextSibling(); - if(next!=null && DOCUMENT_TYPE_NODE==next.getNodeType()) - next=next.getNextSibling(); - - if(next!=null) - break; // Found it! - - // No next-sibling found. Pop the DOM. - pos=pos.getParentNode(); - if(pos==null) - { - // %TBD% Should never arise, but I want to be sure of that... - if(JJK_DEBUG) - { - System.out.println("***** DOM2DTM Pop Control Flow problem"); - for(;;); // Freeze right here! - } - } - - // The only parents in the DTM are Elements. However, - // the DOM could contain EntityReferences. If we - // encounter one, pop it _without_ popping DTM. - if(pos!=null && ENTITY_REFERENCE_NODE == pos.getNodeType()) - { - // Nothing needs doing - if(JJK_DEBUG) - System.out.println("***** DOM2DTM popping EntRef"); - } - else - { - popShouldStripWhitespace(); - // Fix and pop DTM - if(m_last_kid==NULL) - m_firstch.setElementAt(NULL,m_last_parent); // Popping from an element - else - m_nextsib.setElementAt(NULL,m_last_kid); // Popping from anything else - m_last_parent=m_parent.elementAt(m_last_kid=m_last_parent); - } - } - if(m_last_parent==NULL) - next=null; - } - - if(next!=null) - nexttype=next.getNodeType(); - - // If it's an entity ref, advance past it. - // - // %REVIEW% Should we let this out the door and just suppress it? - // More work, but simpler code, more likely to be correct, and - // it doesn't happen very often. We'd get rid of the loop too. - if (ENTITY_REFERENCE_NODE == nexttype) - pos=next; - } - while (ENTITY_REFERENCE_NODE == nexttype); - - // Did we run out of the tree? - if(next==null) - { - m_nextsib.setElementAt(NULL,0); - m_nodesAreProcessed = true; - m_pos=null; - - if(JJK_DEBUG) - { - System.out.println("***** DOM2DTM Crosscheck:"); - for(int i=0;i<m_nodes.size();++i) - System.out.println(i+":\t"+m_firstch.elementAt(i)+"\t"+m_nextsib.elementAt(i)); - } - - return false; - } - - // Text needs some special handling: - // - // DTM may skip whitespace. This is handled by the suppressNode flag, which - // when true will keep the DTM node from being created. - // - // DTM only directly records the first DOM node of any logically-contiguous - // sequence. The lastTextNode value will be set to the last node in the - // contiguous sequence, and -- AFTER the DTM addNode -- can be used to - // advance next over this whole block. Should be simpler than special-casing - // the above loop for "Was the logically-preceeding sibling a text node". - // - // Finally, a DTM node should be considered a CDATASection only if all the - // contiguous text it covers is CDATASections. The first Text should - // force DTM to Text. - - boolean suppressNode=false; - Node lastTextNode=null; - - nexttype=next.getNodeType(); - - // nexttype=pos.getNodeType(); - if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype) - { - // If filtering, initially assume we're going to suppress the node - suppressNode=((null != m_wsfilter) && getShouldStripWhitespace()); - - // Scan logically contiguous text (siblings, plus "flattening" - // of entity reference boundaries). - Node n=next; - while(n!=null) - { - lastTextNode=n; - // Any Text node means DTM considers it all Text - if(TEXT_NODE == n.getNodeType()) - nexttype=TEXT_NODE; - // Any non-whitespace in this sequence blocks whitespace - // suppression - suppressNode &= - XMLCharacterRecognizer.isWhiteSpace(n.getNodeValue()); - - n=logicalNextDOMTextNode(n); - } - } - - // Special handling for PIs: Some DOMs represent the XML - // Declaration as a PI. This is officially incorrect, per the DOM - // spec, but is considered a "wrong but tolerable" temporary - // workaround pending proper handling of these fields in DOM Level - // 3. We want to recognize and reject that case. - else if(PROCESSING_INSTRUCTION_NODE==nexttype) - { - suppressNode = (pos.getNodeName().toLowerCase().equals("xml")); - } - - - if(!suppressNode) - { - // Inserting next. NOTE that we force the node type; for - // coalesced Text, this records CDATASections adjacent to - // ordinary Text as Text. - int nextindex=addNode(next,m_last_parent,m_last_kid, - nexttype); - - m_last_kid=nextindex; - - if(ELEMENT_NODE == nexttype) - { - int attrIndex=NULL; // start with no previous sib - // Process attributes _now_, rather than waiting. - // Simpler control flow, makes NS cache available immediately. - NamedNodeMap attrs=next.getAttributes(); - int attrsize=(attrs==null) ? 0 : attrs.getLength(); - if(attrsize>0) - { - for(int i=0;i<attrsize;++i) - { - // No need to force nodetype in this case; - // addNode() will take care of switching it from - // Attr to Namespace if necessary. - attrIndex=addNode(attrs.item(i), - nextindex,attrIndex,NULL); - m_firstch.setElementAt(DTM.NULL,attrIndex); - - // If the xml: prefix is explicitly declared - // we don't need to synthesize one. - // - // NOTE that XML Namespaces were not originally - // defined as being namespace-aware (grrr), and - // while the W3C is planning to fix this it's - // safer for now to test the QName and trust the - // parsers to prevent anyone from redefining the - // reserved xmlns: prefix - if(!m_processedFirstElement - && "xmlns:xml".equals(attrs.item(i).getNodeName())) - m_processedFirstElement=true; - } - // Terminate list of attrs, and make sure they aren't - // considered children of the element - } // if attrs exist - if(!m_processedFirstElement) - { - // The DOM might not have an explicit declaration for the - // implicit "xml:" prefix, but the XPath data model - // requires that this appear as a Namespace Node so we - // have to synthesize one. You can think of this as - // being a default attribute defined by the XML - // Namespaces spec rather than by the DTD. - attrIndex=addNode(new DOM2DTMdefaultNamespaceDeclarationNode( - (Element)next,"xml",NAMESPACE_DECL_NS, - makeNodeHandle(((attrIndex==NULL)?nextindex:attrIndex)+1) - ), - nextindex,attrIndex,NULL); - m_firstch.setElementAt(DTM.NULL,attrIndex); - m_processedFirstElement=true; - } - if(attrIndex!=NULL) - m_nextsib.setElementAt(DTM.NULL,attrIndex); - } //if(ELEMENT_NODE) - } // (if !suppressNode) - - // Text postprocessing: Act on values stored above - if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype) - { - // %TBD% If nexttype was forced to TEXT, patch the DTM node - - next=lastTextNode; // Advance the DOM cursor over contiguous text - } - - // Remember where we left off. - m_pos=next; - return true; - } - - - /** - * Return an DOM node for the given node. - * - * @param nodeHandle The node ID. - * - * @return A node representation of the DTM node. - */ - public Node getNode(int nodeHandle) - { - - int identity = makeNodeIdentity(nodeHandle); - - return (Node) m_nodes.elementAt(identity); - } - - /** - * Get a Node from an identity index. - * - * NEEDSDOC @param nodeIdentity - * - * NEEDSDOC ($objectName$) @return - */ - protected Node lookupNode(int nodeIdentity) - { - return (Node) m_nodes.elementAt(nodeIdentity); - } - - /** - * Get the next node identity value in the list, and call the iterator - * if it hasn't been added yet. - * - * @param identity The node identity (index). - * @return identity+1, or DTM.NULL. - */ - protected int getNextNodeIdentity(int identity) - { - - identity += 1; - - if (identity >= m_nodes.size()) - { - if (!nextNode()) - identity = DTM.NULL; - } - - return identity; - } - - /** - * Get the handle from a Node. - * <p>%OPT% This will be pretty slow.</p> - * - * <p>%OPT% An XPath-like search (walk up DOM to root, tracking path; - * walk down DTM reconstructing path) might be considerably faster - * on later nodes in large documents. That might also imply improving - * this call to handle nodes which would be in this DTM but - * have not yet been built, which might or might not be a Good Thing.</p> - * - * %REVIEW% This relies on being able to test node-identity via - * object-identity. DTM2DOM proxying is a great example of a case where - * that doesn't work. DOM Level 3 will provide the isSameNode() method - * to fix that, but until then this is going to be flaky. - * - * @param node A node, which may be null. - * - * @return The node handle or <code>DTM.NULL</code>. - */ - private int getHandleFromNode(Node node) - { - if (null != node) - { - int len = m_nodes.size(); - boolean isMore; - int i = 0; - do - { - for (; i < len; i++) - { - if (m_nodes.elementAt(i) == node) - return makeNodeHandle(i); - } - - isMore = nextNode(); - - len = m_nodes.size(); - - } - while(isMore || i < len); - } - - return DTM.NULL; - } - - /** Get the handle from a Node. This is a more robust version of - * getHandleFromNode, intended to be usable by the public. - * - * <p>%OPT% This will be pretty slow.</p> - * - * %REVIEW% This relies on being able to test node-identity via - * object-identity. DTM2DOM proxying is a great example of a case where - * that doesn't work. DOM Level 3 will provide the isSameNode() method - * to fix that, but until then this is going to be flaky. - * - * @param node A node, which may be null. - * - * @return The node handle or <code>DTM.NULL</code>. */ - public int getHandleOfNode(Node node) - { - if (null != node) - { - // Is Node actually within the same document? If not, don't search! - // This would be easier if m_root was always the Document node, but - // we decided to allow wrapping a DTM around a subtree. - if((m_root==node) || - (m_root.getNodeType()==DOCUMENT_NODE && - m_root==node.getOwnerDocument()) || - (m_root.getNodeType()!=DOCUMENT_NODE && - m_root.getOwnerDocument()==node.getOwnerDocument()) - ) - { - // If node _is_ in m_root's tree, find its handle - // - // %OPT% This check may be improved significantly when DOM - // Level 3 nodeKey and relative-order tests become - // available! - for(Node cursor=node; - cursor!=null; - cursor= - (cursor.getNodeType()!=ATTRIBUTE_NODE) - ? cursor.getParentNode() - : ((org.w3c.dom.Attr)cursor).getOwnerElement()) - { - if(cursor==m_root) - // We know this node; find its handle. - return getHandleFromNode(node); - } // for ancestors of node - } // if node and m_root in same Document - } // if node!=null - - return DTM.NULL; - } - - /** - * Retrieves an attribute node by by qualified name and namespace URI. - * - * @param nodeHandle int Handle of the node upon which to look up this attribute.. - * @param namespaceURI The namespace URI of the attribute to - * retrieve, or null. - * @param name The local name of the attribute to - * retrieve. - * @return The attribute node handle with the specified name ( - * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such - * attribute. - */ - public int getAttributeNode(int nodeHandle, String namespaceURI, - String name) - { - - // %OPT% This is probably slower than it needs to be. - if (null == namespaceURI) - namespaceURI = ""; - - int type = getNodeType(nodeHandle); - - if (DTM.ELEMENT_NODE == type) - { - - // Assume that attributes immediately follow the element. - int identity = makeNodeIdentity(nodeHandle); - - while (DTM.NULL != (identity = getNextNodeIdentity(identity))) - { - // Assume this can not be null. - type = _type(identity); - - // %REVIEW% - // Should namespace nodes be retrievable DOM-style as attrs? - // If not we need a separate function... which may be desirable - // architecturally, but which is ugly from a code point of view. - // (If we REALLY insist on it, this code should become a subroutine - // of both -- retrieve the node, then test if the type matches - // what you're looking for.) - if (type == DTM.ATTRIBUTE_NODE || type==DTM.NAMESPACE_NODE) - { - Node node = lookupNode(identity); - String nodeuri = node.getNamespaceURI(); - - if (null == nodeuri) - nodeuri = ""; - - String nodelocalname = node.getLocalName(); - - if (nodeuri.equals(namespaceURI) && name.equals(nodelocalname)) - return makeNodeHandle(identity); - } - - else // if (DTM.NAMESPACE_NODE != type) - { - break; - } - } - } - - return DTM.NULL; - } - - /** - * Get the string-value of a node as a String object - * (see http://www.w3.org/TR/xpath#data-model - * for the definition of a node's string-value). - * - * @param nodeHandle The node ID. - * - * @return A string object that represents the string-value of the given node. - */ - public XMLString getStringValue(int nodeHandle) - { - - int type = getNodeType(nodeHandle); - Node node = getNode(nodeHandle); - // %TBD% If an element only has one text node, we should just use it - // directly. - if(DTM.ELEMENT_NODE == type || DTM.DOCUMENT_NODE == type - || DTM.DOCUMENT_FRAGMENT_NODE == type) - { - FastStringBuffer buf = StringBufferPool.get(); - String s; - - try - { - getNodeData(node, buf); - - s = (buf.length() > 0) ? buf.toString() : ""; - } - finally - { - StringBufferPool.free(buf); - } - - return m_xstrf.newstr( s ); - } - else if(TEXT_NODE == type || CDATA_SECTION_NODE == type) - { - // If this is a DTM text node, it may be made of multiple DOM text - // nodes -- including navigating into Entity References. DOM2DTM - // records the first node in the sequence and requires that we - // pick up the others when we retrieve the DTM node's value. - // - // %REVIEW% DOM Level 3 is expected to add a "whole text" - // retrieval method which performs this function for us. - FastStringBuffer buf = StringBufferPool.get(); - while(node!=null) - { - buf.append(node.getNodeValue()); - node=logicalNextDOMTextNode(node); - } - String s=(buf.length() > 0) ? buf.toString() : ""; - StringBufferPool.free(buf); - return m_xstrf.newstr( s ); - } - else - return m_xstrf.newstr( node.getNodeValue() ); - } - - /** - * Determine if the string-value of a node is whitespace - * - * @param nodeHandle The node Handle. - * - * @return Return true if the given node is whitespace. - */ - public boolean isWhitespace(int nodeHandle) - { - int type = getNodeType(nodeHandle); - Node node = getNode(nodeHandle); - if(TEXT_NODE == type || CDATA_SECTION_NODE == type) - { - // If this is a DTM text node, it may be made of multiple DOM text - // nodes -- including navigating into Entity References. DOM2DTM - // records the first node in the sequence and requires that we - // pick up the others when we retrieve the DTM node's value. - // - // %REVIEW% DOM Level 3 is expected to add a "whole text" - // retrieval method which performs this function for us. - FastStringBuffer buf = StringBufferPool.get(); - while(node!=null) - { - buf.append(node.getNodeValue()); - node=logicalNextDOMTextNode(node); - } - boolean b = buf.isWhitespace(0, buf.length()); - StringBufferPool.free(buf); - return b; - } - return false; - } - - /** - * Retrieve the text content of a DOM subtree, appending it into a - * user-supplied FastStringBuffer object. Note that attributes are - * not considered part of the content of an element. - * <p> - * There are open questions regarding whitespace stripping. - * Currently we make no special effort in that regard, since the standard - * DOM doesn't yet provide DTD-based information to distinguish - * whitespace-in-element-context from genuine #PCDATA. Note that we - * should probably also consider xml:space if/when we address this. - * DOM Level 3 may solve the problem for us. - * <p> - * %REVIEW% Actually, since this method operates on the DOM side of the - * fence rather than the DTM side, it SHOULDN'T do - * any special handling. The DOM does what the DOM does; if you want - * DTM-level abstractions, use DTM-level methods. - * - * @param node Node whose subtree is to be walked, gathering the - * contents of all Text or CDATASection nodes. - * @param buf FastStringBuffer into which the contents of the text - * nodes are to be concatenated. - */ - protected static void getNodeData(Node node, FastStringBuffer buf) - { - - switch (node.getNodeType()) - { - case Node.DOCUMENT_FRAGMENT_NODE : - case Node.DOCUMENT_NODE : - case Node.ELEMENT_NODE : - { - for (Node child = node.getFirstChild(); null != child; - child = child.getNextSibling()) - { - getNodeData(child, buf); - } - } - break; - case Node.TEXT_NODE : - case Node.CDATA_SECTION_NODE : - case Node.ATTRIBUTE_NODE : // Never a child but might be our starting node - buf.append(node.getNodeValue()); - break; - case Node.PROCESSING_INSTRUCTION_NODE : - // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING); - break; - default : - // ignore - break; - } - } - - /** - * Given a node handle, return its DOM-style node name. This will - * include names such as #text or #document. - * - * @param nodeHandle the id of the node. - * @return String Name of this node, which may be an empty string. - * %REVIEW% Document when empty string is possible... - * %REVIEW-COMMENT% It should never be empty, should it? - */ - public String getNodeName(int nodeHandle) - { - - Node node = getNode(nodeHandle); - - // Assume non-null. - return node.getNodeName(); - } - - /** - * Given a node handle, return the XPath node name. This should be - * the name as described by the XPath data model, NOT the DOM-style - * name. - * - * @param nodeHandle the id of the node. - * @return String Name of this node, which may be an empty string. - */ - public String getNodeNameX(int nodeHandle) - { - - String name; - short type = getNodeType(nodeHandle); - - switch (type) - { - case DTM.NAMESPACE_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - name = node.getNodeName(); - if(name.startsWith("xmlns:")) - { - name = QName.getLocalPart(name); - } - else if(name.equals("xmlns")) - { - name = ""; - } - } - break; - case DTM.ATTRIBUTE_NODE : - case DTM.ELEMENT_NODE : - case DTM.ENTITY_REFERENCE_NODE : - case DTM.PROCESSING_INSTRUCTION_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - name = node.getNodeName(); - } - break; - default : - name = ""; - } - - return name; - } - - /** - * Given a node handle, return its XPath-style localname. - * (As defined in Namespaces, this is the portion of the name after any - * colon character). - * - * @param nodeHandle the id of the node. - * @return String Local name of this node. - */ - public String getLocalName(int nodeHandle) - { - if(JJK_NEWCODE) - { - int id=makeNodeIdentity(nodeHandle); - if(NULL==id) return null; - Node newnode=(Node)m_nodes.elementAt(id); - String newname=newnode.getLocalName(); - if (null == newname) - { - // XSLT treats PIs, and possibly other things, as having QNames. - String qname = newnode.getNodeName(); - if('#'==qname.charAt(0)) - { - // Match old default for this function - // This conversion may or may not be necessary - newname=""; - } - else - { - int index = qname.indexOf(':'); - newname = (index < 0) ? qname : qname.substring(index + 1); - } - } - return newname; - } - else - { - String name; - short type = getNodeType(nodeHandle); - switch (type) - { - case DTM.ATTRIBUTE_NODE : - case DTM.ELEMENT_NODE : - case DTM.ENTITY_REFERENCE_NODE : - case DTM.NAMESPACE_NODE : - case DTM.PROCESSING_INSTRUCTION_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - name = node.getLocalName(); - - if (null == name) - { - String qname = node.getNodeName(); - int index = qname.indexOf(':'); - - name = (index < 0) ? qname : qname.substring(index + 1); - } - } - break; - default : - name = ""; - } - return name; - } - } - - /** - * Given a namespace handle, return the prefix that the namespace decl is - * mapping. - * Given a node handle, return the prefix used to map to the namespace. - * - * <p> %REVIEW% Are you sure you want "" for no prefix? </p> - * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb </p> - * - * @param nodeHandle the id of the node. - * @return String prefix of this node's name, or "" if no explicit - * namespace prefix was given. - */ - public String getPrefix(int nodeHandle) - { - - String prefix; - short type = getNodeType(nodeHandle); - - switch (type) - { - case DTM.NAMESPACE_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - String qname = node.getNodeName(); - int index = qname.indexOf(':'); - - prefix = (index < 0) ? "" : qname.substring(index + 1); - } - break; - case DTM.ATTRIBUTE_NODE : - case DTM.ELEMENT_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - String qname = node.getNodeName(); - int index = qname.indexOf(':'); - - prefix = (index < 0) ? "" : qname.substring(0, index); - } - break; - default : - prefix = ""; - } - - return prefix; - } - - /** - * Given a node handle, return its DOM-style namespace URI - * (As defined in Namespaces, this is the declared URI which this node's - * prefix -- or default in lieu thereof -- was mapped to.) - * - * <p>%REVIEW% Null or ""? -sb</p> - * - * @param nodeHandle the id of the node. - * @return String URI value of this node's namespace, or null if no - * namespace was resolved. - */ - public String getNamespaceURI(int nodeHandle) - { - if(JJK_NEWCODE) - { - int id=makeNodeIdentity(nodeHandle); - if(id==NULL) return null; - Node node=(Node)m_nodes.elementAt(id); - return node.getNamespaceURI(); - } - else - { - String nsuri; - short type = getNodeType(nodeHandle); - - switch (type) - { - case DTM.ATTRIBUTE_NODE : - case DTM.ELEMENT_NODE : - case DTM.ENTITY_REFERENCE_NODE : - case DTM.NAMESPACE_NODE : - case DTM.PROCESSING_INSTRUCTION_NODE : - { - Node node = getNode(nodeHandle); - - // assume not null. - nsuri = node.getNamespaceURI(); - - // %TBD% Handle DOM1? - } - break; - default : - nsuri = null; - } - - return nsuri; - } - - } - - /** Utility function: Given a DOM Text node, determine whether it is - * logically followed by another Text or CDATASection node. This may - * involve traversing into Entity References. - * - * %REVIEW% DOM Level 3 is expected to add functionality which may - * allow us to retire this. - */ - private Node logicalNextDOMTextNode(Node n) - { - Node p=n.getNextSibling(); - if(p==null) - { - // Walk out of any EntityReferenceNodes that ended with text - for(n=n.getParentNode(); - n!=null && ENTITY_REFERENCE_NODE == n.getNodeType(); - n=n.getParentNode()) - { - p=n.getNextSibling(); - if(p!=null) - break; - } - } - n=p; - while(n!=null && ENTITY_REFERENCE_NODE == n.getNodeType()) - { - // Walk into any EntityReferenceNodes that start with text - if(n.hasChildNodes()) - n=n.getFirstChild(); - else - n=n.getNextSibling(); - } - if(n!=null) - { - // Found a logical next sibling. Is it text? - int ntype=n.getNodeType(); - if(TEXT_NODE != ntype && CDATA_SECTION_NODE != ntype) - n=null; - } - return n; - } - - /** - * Given a node handle, return its node value. This is mostly - * as defined by the DOM, but may ignore some conveniences. - * <p> - * - * @param nodeHandle The node id. - * @return String Value of this node, or null if not - * meaningful for this node type. - */ - public String getNodeValue(int nodeHandle) - { - // The _type(nodeHandle) call was taking the lion's share of our - // time, and was wrong anyway since it wasn't coverting handle to - // identity. Inlined it. - int type = _exptype(makeNodeIdentity(nodeHandle)); - type=(NULL != type) ? getNodeType(nodeHandle) : NULL; - - if(TEXT_NODE!=type && CDATA_SECTION_NODE!=type) - return getNode(nodeHandle).getNodeValue(); - - // If this is a DTM text node, it may be made of multiple DOM text - // nodes -- including navigating into Entity References. DOM2DTM - // records the first node in the sequence and requires that we - // pick up the others when we retrieve the DTM node's value. - // - // %REVIEW% DOM Level 3 is expected to add a "whole text" - // retrieval method which performs this function for us. - Node node = getNode(nodeHandle); - Node n=logicalNextDOMTextNode(node); - if(n==null) - return node.getNodeValue(); - - FastStringBuffer buf = StringBufferPool.get(); - buf.append(node.getNodeValue()); - while(n!=null) - { - buf.append(n.getNodeValue()); - n=logicalNextDOMTextNode(n); - } - String s = (buf.length() > 0) ? buf.toString() : ""; - StringBufferPool.free(buf); - return s; - } - - /** - * A document type declaration information item has the following properties: - * - * 1. [system identifier] The system identifier of the external subset, if - * it exists. Otherwise this property has no value. - * - * @return the system identifier String object, or null if there is none. - */ - public String getDocumentTypeDeclarationSystemIdentifier() - { - - Document doc; - - if (m_root.getNodeType() == Node.DOCUMENT_NODE) - doc = (Document) m_root; - else - doc = m_root.getOwnerDocument(); - - if (null != doc) - { - DocumentType dtd = doc.getDoctype(); - - if (null != dtd) - { - return dtd.getSystemId(); - } - } - - return null; - } - - /** - * Return the public identifier of the external subset, - * normalized as described in 4.2.2 External Entities [XML]. If there is - * no external subset or if it has no public identifier, this property - * has no value. - * - * @return the public identifier String object, or null if there is none. - */ - public String getDocumentTypeDeclarationPublicIdentifier() - { - - Document doc; - - if (m_root.getNodeType() == Node.DOCUMENT_NODE) - doc = (Document) m_root; - else - doc = m_root.getOwnerDocument(); - - if (null != doc) - { - DocumentType dtd = doc.getDoctype(); - - if (null != dtd) - { - return dtd.getPublicId(); - } - } - - return null; - } - - /** - * Returns the <code>Element</code> whose <code>ID</code> is given by - * <code>elementId</code>. If no such element exists, returns - * <code>DTM.NULL</code>. Behavior is not defined if more than one element - * has this <code>ID</code>. Attributes (including those - * with the name "ID") are not of type ID unless so defined by DTD/Schema - * information available to the DTM implementation. - * Implementations that do not know whether attributes are of type ID or - * not are expected to return <code>DTM.NULL</code>. - * - * <p>%REVIEW% Presumably IDs are still scoped to a single document, - * and this operation searches only within a single document, right? - * Wouldn't want collisions between DTMs in the same process.</p> - * - * @param elementId The unique <code>id</code> value for an element. - * @return The handle of the matching element. - */ - public int getElementById(String elementId) - { - - Document doc = (m_root.getNodeType() == Node.DOCUMENT_NODE) - ? (Document) m_root : m_root.getOwnerDocument(); - - if(null != doc) - { - Node elem = doc.getElementById(elementId); - if(null != elem) - { - int elemHandle = getHandleFromNode(elem); - - if(DTM.NULL == elemHandle) - { - int identity = m_nodes.size()-1; - while (DTM.NULL != (identity = getNextNodeIdentity(identity))) - { - Node node = getNode(identity); - if(node == elem) - { - elemHandle = getHandleFromNode(elem); - break; - } - } - } - - return elemHandle; - } - - } - return DTM.NULL; - } - - /** - * The getUnparsedEntityURI function returns the URI of the unparsed - * entity with the specified name in the same document as the context - * node (see [3.3 Unparsed Entities]). It returns the empty string if - * there is no such entity. - * <p> - * XML processors may choose to use the System Identifier (if one - * is provided) to resolve the entity, rather than the URI in the - * Public Identifier. The details are dependent on the processor, and - * we would have to support some form of plug-in resolver to handle - * this properly. Currently, we simply return the System Identifier if - * present, and hope that it a usable URI or that our caller can - * map it to one. - * TODO: Resolve Public Identifiers... or consider changing function name. - * <p> - * If we find a relative URI - * reference, XML expects it to be resolved in terms of the base URI - * of the document. The DOM doesn't do that for us, and it isn't - * entirely clear whether that should be done here; currently that's - * pushed up to a higher level of our application. (Note that DOM Level - * 1 didn't store the document's base URI.) - * TODO: Consider resolving Relative URIs. - * <p> - * (The DOM's statement that "An XML processor may choose to - * completely expand entities before the structure model is passed - * to the DOM" refers only to parsed entities, not unparsed, and hence - * doesn't affect this function.) - * - * @param name A string containing the Entity Name of the unparsed - * entity. - * - * @return String containing the URI of the Unparsed Entity, or an - * empty string if no such entity exists. - */ - public String getUnparsedEntityURI(String name) - { - - String url = ""; - Document doc = (m_root.getNodeType() == Node.DOCUMENT_NODE) - ? (Document) m_root : m_root.getOwnerDocument(); - - if (null != doc) - { - DocumentType doctype = doc.getDoctype(); - - if (null != doctype) - { - NamedNodeMap entities = doctype.getEntities(); - if(null == entities) - return url; - Entity entity = (Entity) entities.getNamedItem(name); - if(null == entity) - return url; - - String notationName = entity.getNotationName(); - - if (null != notationName) // then it's unparsed - { - // The draft says: "The XSLT processor may use the public - // identifier to generate a URI for the entity instead of the URI - // specified in the system identifier. If the XSLT processor does - // not use the public identifier to generate the URI, it must use - // the system identifier; if the system identifier is a relative - // URI, it must be resolved into an absolute URI using the URI of - // the resource containing the entity declaration as the base - // URI [RFC2396]." - // So I'm falling a bit short here. - url = entity.getSystemId(); - - if (null == url) - { - url = entity.getPublicId(); - } - else - { - // This should be resolved to an absolute URL, but that's hard - // to do from here. - } - } - } - } - - return url; - } - - /** - * 5. [specified] A flag indicating whether this attribute was actually - * specified in the start-tag of its element, or was defaulted from the - * DTD. - * - * @param attributeHandle the attribute handle - * @return <code>true</code> if the attribute was specified; - * <code>false</code> if it was defaulted. - */ - public boolean isAttributeSpecified(int attributeHandle) - { - int type = getNodeType(attributeHandle); - - if (DTM.ATTRIBUTE_NODE == type) - { - Attr attr = (Attr)getNode(attributeHandle); - return attr.getSpecified(); - } - return false; - } - - /** Bind an IncrementalSAXSource to this DTM. NOT RELEVANT for DOM2DTM, since - * we're wrapped around an existing DOM. - * - * @param source The IncrementalSAXSource that we want to recieve events from - * on demand. - */ - public void setIncrementalSAXSource(IncrementalSAXSource source) - { - } - - /** getContentHandler returns "our SAX builder" -- the thing that - * someone else should send SAX events to in order to extend this - * DTM model. - * - * @return null if this model doesn't respond to SAX events, - * "this" if the DTM object has a built-in SAX ContentHandler, - * the IncrmentalSAXSource if we're bound to one and should receive - * the SAX stream via it for incremental build purposes... - * */ - public org.xml.sax.ContentHandler getContentHandler() - { - return null; - } - - /** - * Return this DTM's lexical handler. - * - * %REVIEW% Should this return null if constrution already done/begun? - * - * @return null if this model doesn't respond to lexical SAX events, - * "this" if the DTM object has a built-in SAX ContentHandler, - * the IncrementalSAXSource if we're bound to one and should receive - * the SAX stream via it for incremental build purposes... - */ - public org.xml.sax.ext.LexicalHandler getLexicalHandler() - { - - return null; - } - - - /** - * Return this DTM's EntityResolver. - * - * @return null if this model doesn't respond to SAX entity ref events. - */ - public org.xml.sax.EntityResolver getEntityResolver() - { - - return null; - } - - /** - * Return this DTM's DTDHandler. - * - * @return null if this model doesn't respond to SAX dtd events. - */ - public org.xml.sax.DTDHandler getDTDHandler() - { - - return null; - } - - /** - * Return this DTM's ErrorHandler. - * - * @return null if this model doesn't respond to SAX error events. - */ - public org.xml.sax.ErrorHandler getErrorHandler() - { - - return null; - } - - /** - * Return this DTM's DeclHandler. - * - * @return null if this model doesn't respond to SAX Decl events. - */ - public org.xml.sax.ext.DeclHandler getDeclHandler() - { - - return null; - } - - /** @return true iff we're building this model incrementally (eg - * we're partnered with a IncrementalSAXSource) and thus require that the - * transformation and the parse run simultaneously. Guidance to the - * DTMManager. - * */ - public boolean needsTwoThreads() - { - return false; - } - - // ========== Direct SAX Dispatch, for optimization purposes ======== - - /** - * Returns whether the specified <var>ch</var> conforms to the XML 1.0 definition - * of whitespace. Refer to <A href="http://www.w3.org/TR/1998/REC-xml-19980210#NT-S"> - * the definition of <CODE>S</CODE></A> for details. - * @param ch Character to check as XML whitespace. - * @return =true if <var>ch</var> is XML whitespace; otherwise =false. - */ - private static boolean isSpace(char ch) - { - return XMLCharacterRecognizer.isWhiteSpace(ch); // Take the easy way out for now. - } - - /** - * Directly call the - * characters method on the passed ContentHandler for the - * string-value of the given node (see http://www.w3.org/TR/xpath#data-model - * for the definition of a node's string-value). Multiple calls to the - * ContentHandler's characters methods may well occur for a single call to - * this method. - * - * @param nodeHandle The node ID. - * @param ch A non-null reference to a ContentHandler. - * - * @throws org.xml.sax.SAXException - */ - public void dispatchCharactersEvents( - int nodeHandle, org.xml.sax.ContentHandler ch, - boolean normalize) - throws org.xml.sax.SAXException - { - if(normalize) - { - XMLString str = getStringValue(nodeHandle); - str = str.fixWhiteSpace(true, true, false); - str.dispatchCharactersEvents(ch); - } - else - { - int type = getNodeType(nodeHandle); - Node node = getNode(nodeHandle); - dispatchNodeData(node, ch, 0); - // Text coalition -- a DTM text node may represent multiple - // DOM nodes. - if(TEXT_NODE == type || CDATA_SECTION_NODE == type) - { - while( null != (node=logicalNextDOMTextNode(node)) ) - { - dispatchNodeData(node, ch, 0); - } - } - } - } - - /** - * Retrieve the text content of a DOM subtree, appending it into a - * user-supplied FastStringBuffer object. Note that attributes are - * not considered part of the content of an element. - * <p> - * There are open questions regarding whitespace stripping. - * Currently we make no special effort in that regard, since the standard - * DOM doesn't yet provide DTD-based information to distinguish - * whitespace-in-element-context from genuine #PCDATA. Note that we - * should probably also consider xml:space if/when we address this. - * DOM Level 3 may solve the problem for us. - * <p> - * %REVIEW% Note that as a DOM-level operation, it can be argued that this - * routine _shouldn't_ perform any processing beyond what the DOM already - * does, and that whitespace stripping and so on belong at the DTM level. - * If you want a stripped DOM view, wrap DTM2DOM around DOM2DTM. - * - * @param node Node whose subtree is to be walked, gathering the - * contents of all Text or CDATASection nodes. - */ - protected static void dispatchNodeData(Node node, - org.xml.sax.ContentHandler ch, - int depth) - throws org.xml.sax.SAXException - { - - switch (node.getNodeType()) - { - case Node.DOCUMENT_FRAGMENT_NODE : - case Node.DOCUMENT_NODE : - case Node.ELEMENT_NODE : - { - for (Node child = node.getFirstChild(); null != child; - child = child.getNextSibling()) - { - dispatchNodeData(child, ch, depth+1); - } - } - break; - case Node.PROCESSING_INSTRUCTION_NODE : // %REVIEW% - case Node.COMMENT_NODE : - if(0 != depth) - break; - // NOTE: Because this operation works in the DOM space, it does _not_ attempt - // to perform Text Coalition. That should only be done in DTM space. - case Node.TEXT_NODE : - case Node.CDATA_SECTION_NODE : - case Node.ATTRIBUTE_NODE : - String str = node.getNodeValue(); - if(ch instanceof CharacterNodeHandler) - { - ((CharacterNodeHandler)ch).characters(node); - } - else - { - ch.characters(str.toCharArray(), 0, str.length()); - } - break; -// /* case Node.PROCESSING_INSTRUCTION_NODE : -// // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING); -// break; */ - default : - // ignore - break; - } - } - - TreeWalker m_walker = new TreeWalker(null); - - /** - * Directly create SAX parser events from a subtree. - * - * @param nodeHandle The node ID. - * @param ch A non-null reference to a ContentHandler. - * - * @throws org.xml.sax.SAXException - */ - public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch) - throws org.xml.sax.SAXException - { - TreeWalker treeWalker = m_walker; - ContentHandler prevCH = treeWalker.getContentHandler(); - - if(null != prevCH) - { - treeWalker = new TreeWalker(null); - } - treeWalker.setContentHandler(ch); - - try - { - Node node = getNode(nodeHandle); - treeWalker.traverseFragment(node); - } - finally - { - treeWalker.setContentHandler(null); - } - } - - public interface CharacterNodeHandler - { - public void characters(Node node) - throws org.xml.sax.SAXException; - } - - /** - * For the moment all the run time properties are ignored by this - * class. - * - * @param property a <code>String</code> value - * @param value an <code>Object</code> value - */ - public void setProperty(String property, Object value) - { - } - - /** - * No source information is available for DOM2DTM, so return - * <code>null</code> here. - * - * @param node an <code>int</code> value - * @return null - */ - public SourceLocator getSourceLocatorFor(int node) - { - return null; - } - -} |