19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: DOM2DTM.java 478671 2006-11-23 21:00:31Z minchau $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xml.dtm.ref.dom2dtm;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Vector;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.SourceLocator;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.dom.DOMSource;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTM;
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTMManager;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTMWSFilter;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.ref.DTMDefaultBaseIterators;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.ref.DTMManagerDefault;
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.ref.ExpandedNameTable;
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.ref.IncrementalSAXSource;
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.res.XMLErrorResources;
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.res.XMLMessages;
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.FastStringBuffer;
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.QName;
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.StringBufferPool;
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.TreeWalker;
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.XMLCharacterRecognizer;
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.XMLString;
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.XMLStringFactory;
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Attr;
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Document;
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.DocumentType;
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Element;
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Entity;
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.NamedNodeMap;
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.w3c.dom.Node;
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.xml.sax.ContentHandler;
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/** The <code>DOM2DTM</code> class serves up a DOM's contents via the
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * DTM API.
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Note that it doesn't necessarily represent a full Document
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * tree. You can wrap a DOM2DTM around a specific node and its subtree
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and the right things should happen. (I don't _think_ we currently
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * support DocumentFrgment nodes as roots, though that might be worth
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * considering.)
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Note too that we do not currently attempt to track document
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * mutation. If you alter the DOM after wrapping DOM2DTM around it,
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * all bets are off.
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * */
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class DOM2DTM extends DTMDefaultBaseIterators
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final boolean JJK_DEBUG=false;
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final boolean JJK_NEWCODE=true;
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** Manefest constant
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final String NAMESPACE_DECL_NS="http://www.w3.org/XML/1998/namespace";
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The current position in the DOM tree. Last node examined for
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * possible copying to DTM. */
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  transient private Node m_pos;
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The current position in the DTM tree. Who children get appended to. */
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private int m_last_parent=0;
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The current position in the DTM tree. Who children reference as their
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * previous sib. */
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private int m_last_kid=NULL;
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The top of the subtree.
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW%: 'may not be the same as m_context if "//foo" pattern.'
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * */
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  transient private Node m_root;
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** True iff the first element has been processed. This is used to control
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      synthesis of the implied xml: namespace declaration node. */
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  boolean m_processedFirstElement=false;
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** true if ALL the nodes in the m_root subtree have been processed;
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * false if our incremental build has not yet finished scanning the
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DOM tree.  */
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  transient private boolean m_nodesAreProcessed;
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The node objects.  The instance part of the handle indexes
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * directly into this vector.  Each DTM node may actually be
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * composed of several DOM nodes (for example, if logically-adjacent
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Text/CDATASection nodes in the DOM have been coalesced into a
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * single DTM Text node); this table points only to the first in
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * that sequence. */
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected Vector m_nodes = new Vector();
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Construct a DOM2DTM object from a DOM node.
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param mgr The DTMManager who owns this DTM.
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param domSource the DOM source that this DTM will wrap.
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param dtmIdentity The DTM identity ID for this DTM.
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param whiteSpaceFilter The white space filter for this DTM, which may
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                         be null.
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xstringfactory XMLString factory for creating character content.
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param doIndexing true if the caller considers it worth it to use
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                   indexing schemes.
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public DOM2DTM(DTMManager mgr, DOMSource domSource,
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                 int dtmIdentity, DTMWSFilter whiteSpaceFilter,
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                 XMLStringFactory xstringfactory,
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                 boolean doIndexing)
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    super(mgr, domSource, dtmIdentity, whiteSpaceFilter,
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          xstringfactory, doIndexing);
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Initialize DOM navigation
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_pos=m_root = domSource.getNode();
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Initialize DTM navigation
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_last_parent=m_last_kid=NULL;
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_last_kid=addNode(m_root, m_last_parent,m_last_kid, NULL);
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Apparently the domSource root may not actually be the
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Document node. If it's an Element node, we need to immediately
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // add its attributes. Adapted from nextNode().
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW% Move this logic into addNode and recurse? Cleaner!
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (If it's an EntityReference node, we're probably in
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // seriously bad trouble. For now
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // I'm just hoping nobody is ever quite that foolish... %REVIEW%)
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		//
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		// %ISSUE% What about inherited namespaces in this case?
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		// Do we need to special-case initialize them into the DTM model?
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(ELEMENT_NODE == m_root.getNodeType())
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      NamedNodeMap attrs=m_root.getAttributes();
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int attrsize=(attrs==null) ? 0 : attrs.getLength();
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(attrsize>0)
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int attrIndex=NULL; // start with no previous sib
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        for(int i=0;i<attrsize;++i)
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // No need to force nodetype in this case;
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // addNode() will take care of switching it from
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // Attr to Namespace if necessary.
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          attrIndex=addNode(attrs.item(i),0,attrIndex,NULL);
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_firstch.setElementAt(DTM.NULL,attrIndex);
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Terminate list of attrs, and make sure they aren't
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // considered children of the element
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_nextsib.setElementAt(DTM.NULL,attrIndex);
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // IMPORTANT: This does NOT change m_last_parent or m_last_kid!
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      } // if attrs exist
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } //if(ELEMENT_NODE)
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Initialize DTM-completed status
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_nodesAreProcessed = false;
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Construct the node map from the node.
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node The node that is to be added to the DTM.
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param parentIndex The current parent index.
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param previousSibling The previous sibling index.
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param forceNodeType If not DTM.NULL, overrides the DOM node type.
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *	Used to force nodes to Text rather than CDATASection when their
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *	coalesced value includes ordinary Text nodes (current DTM behavior).
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The index identity of the node that was added.
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int addNode(Node node, int parentIndex,
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        int previousSibling, int forceNodeType)
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int nodeIndex = m_nodes.size();
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Have we overflowed a DTM Identity's addressing range?
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      try
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(m_mgr==null)
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throw new ClassCastException();
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                // Handle as Extended Addressing
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr;
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int id=mgrD.getFirstFreeDTMID();
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        mgrD.addDTM(this,id,nodeIndex);
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_dtmIdent.addElement(id<<DTMManager.IDENT_DTM_NODE_BITS);
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      catch(ClassCastException e)
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // %REVIEW% Wrong error message, but I've been told we're trying
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // not to add messages right not for I18N reasons.
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // %REVIEW% Should this be a Fatal Error?
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available";
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_size++;
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // ensureSize(nodeIndex);
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int type;
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(NULL==forceNodeType)
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        type = node.getNodeType();
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        type=forceNodeType;
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW% The Namespace Spec currently says that Namespaces are
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // processed in a non-namespace-aware manner, by matching the
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // QName, even though there is in fact a namespace assigned to
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // these nodes in the DOM. If and when that changes, we will have
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // to consider whether we check the namespace-for-namespaces
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // rather than the node name.
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %TBD% Note that the DOM does not necessarily explicitly declare
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // all the namespaces it uses. DOM Level 3 will introduce a
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // namespace-normalization operation which reconciles that, and we
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // can request that users invoke it or otherwise ensure that the
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // tree is namespace-well-formed before passing the DOM to Xalan.
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // But if they don't, what should we do about it? We probably
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // don't want to alter the source DOM (and may not be able to do
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // so if it's read-only). The best available answer might be to
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // synthesize additional DTM Namespace Nodes that don't correspond
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // to DOM Attr Nodes.
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (Node.ATTRIBUTE_NODE == type)
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String name = node.getNodeName();
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (name.startsWith("xmlns:") || name.equals("xmlns"))
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        type = DTM.NAMESPACE_NODE;
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_nodes.addElement(node);
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_firstch.setElementAt(NOTPROCESSED,nodeIndex);
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_nextsib.setElementAt(NOTPROCESSED,nodeIndex);
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_prevsib.setElementAt(previousSibling,nodeIndex);
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_parent.setElementAt(parentIndex,nodeIndex);
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(DTM.NULL != parentIndex &&
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson       type != DTM.ATTRIBUTE_NODE &&
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson       type != DTM.NAMESPACE_NODE)
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // If the DTM parent had no children, this becomes its first child.
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(NOTPROCESSED == m_firstch.elementAt(parentIndex))
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_firstch.setElementAt(nodeIndex,parentIndex);
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String nsURI = node.getNamespaceURI();
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Deal with the difference between Namespace spec and XSLT
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // definitions of local name. (The former says PIs don't have
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // localnames; the latter says they do.)
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String localName =  (type == Node.PROCESSING_INSTRUCTION_NODE) ?
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                         node.getNodeName() :
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                         node.getLocalName();
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Hack to make DOM1 sort of work...
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(((type == Node.ELEMENT_NODE) || (type == Node.ATTRIBUTE_NODE))
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        && null == localName)
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      localName = node.getNodeName(); // -sb
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    ExpandedNameTable exnt = m_expandedNameTable;
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %TBD% Nodes created with the old non-namespace-aware DOM
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // calls createElement() and createAttribute() will never have a
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // localname. That will cause their expandedNameID to be just the
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // nodeType... which will keep them from being matched
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // successfully by name. Since the DOM makes no promise that
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // those will participate in namespace processing, this is
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // officially accepted as Not Our Fault. But it might be nice to
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // issue a diagnostic message!
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(node.getLocalName()==null &&
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson       (type==Node.ELEMENT_NODE || type==Node.ATTRIBUTE_NODE))
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // warning("DOM 'level 1' node "+node.getNodeName()+" won't be mapped properly in DOM2DTM.");
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int expandedNameID = (null != localName)
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson       ? exnt.getExpandedTypeID(nsURI, localName, type) :
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         exnt.getExpandedTypeID(type);
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_exptype.setElementAt(expandedNameID,nodeIndex);
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    indexNode(expandedNameID, nodeIndex);
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (DTM.NULL != previousSibling)
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_nextsib.setElementAt(nodeIndex,previousSibling);
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // This should be done after m_exptype has been set, and probably should
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // always be the last thing we do
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (type == DTM.NAMESPACE_NODE)
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        declareNamespaceInContext(parentIndex,nodeIndex);
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return nodeIndex;
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the number of nodes that have been added.
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getNumberOfNodes()
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return m_nodes.size();
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /**
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This method iterates to the next node that will be added to the table.
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Each call to this method adds a new node to the table, unless the end
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * is reached, in which case it returns null.
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The true if a next node is found or false if
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         there are no more nodes.
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean nextNode()
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Non-recursive one-fetch-at-a-time depth-first traversal with
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // attribute/namespace nodes and white-space stripping.
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Navigating the DOM is simple, navigating the DTM is simple;
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // keeping track of both at once is a trifle baroque but at least
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // we've avoided most of the special cases.
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_nodesAreProcessed)
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return false;
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW% Is this local copy Really Useful from a performance
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // point of view?  Or is this a false microoptimization?
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node pos=m_pos;
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node next=null;
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int nexttype=NULL;
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Navigate DOM tree
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    do
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Look down to first child.
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (pos.hasChildNodes())
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            next = pos.getFirstChild();
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // %REVIEW% There's probably a more elegant way to skip
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // the doctype. (Just let it go and Suppress it?
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(next!=null && DOCUMENT_TYPE_NODE==next.getNodeType())
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              next=next.getNextSibling();
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Push DTM context -- except for children of Entity References,
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // which have no DTM equivalent and cause no DTM navigation.
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(ENTITY_REFERENCE_NODE!=pos.getNodeType())
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              {
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                m_last_parent=m_last_kid;
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                m_last_kid=NULL;
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Whitespace-handler context stacking
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(null != m_wsfilter)
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                {
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  short wsv =
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    m_wsfilter.getShouldStripSpace(makeNodeHandle(m_last_parent),this);
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    ? getShouldStripWhitespace()
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    : (DTMWSFilter.STRIP == wsv);
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  pushShouldStripWhitespace(shouldStrip);
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                } // if(m_wsfilter)
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              }
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // If that fails, look up and right (but not past root!)
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(m_last_kid!=NULL)
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              {
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Last node posted at this level had no more children
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // If it has _no_ children, we need to record that.
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(m_firstch.elementAt(m_last_kid)==NOTPROCESSED)
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  m_firstch.setElementAt(NULL,m_last_kid);
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              }
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            while(m_last_parent != NULL)
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              {
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // %REVIEW% There's probably a more elegant way to
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // skip the doctype. (Just let it go and Suppress it?
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                next = pos.getNextSibling();
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(next!=null && DOCUMENT_TYPE_NODE==next.getNodeType())
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  next=next.getNextSibling();
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(next!=null)
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  break; // Found it!
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // No next-sibling found. Pop the DOM.
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                pos=pos.getParentNode();
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(pos==null)
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // %TBD% Should never arise, but I want to be sure of that...
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(JJK_DEBUG)
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      {
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        System.out.println("***** DOM2DTM Pop Control Flow problem");
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        for(;;); // Freeze right here!
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      }
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // The only parents in the DTM are Elements.  However,
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // the DOM could contain EntityReferences.  If we
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // encounter one, pop it _without_ popping DTM.
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(pos!=null && ENTITY_REFERENCE_NODE == pos.getNodeType())
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // Nothing needs doing
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(JJK_DEBUG)
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      System.out.println("***** DOM2DTM popping EntRef");
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                else
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    popShouldStripWhitespace();
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // Fix and pop DTM
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(m_last_kid==NULL)
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      m_firstch.setElementAt(NULL,m_last_parent); // Popping from an element
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    else
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      m_nextsib.setElementAt(NULL,m_last_kid); // Popping from anything else
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    m_last_parent=m_parent.elementAt(m_last_kid=m_last_parent);
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              }
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(m_last_parent==NULL)
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              next=null;
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(next!=null)
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nexttype=next.getNodeType();
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // If it's an entity ref, advance past it.
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // %REVIEW% Should we let this out the door and just suppress it?
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // More work, but simpler code, more likely to be correct, and
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // it doesn't happen very often. We'd get rid of the loop too.
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (ENTITY_REFERENCE_NODE == nexttype)
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          pos=next;
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (ENTITY_REFERENCE_NODE == nexttype);
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Did we run out of the tree?
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(next==null)
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_nextsib.setElementAt(NULL,0);
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_nodesAreProcessed = true;
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_pos=null;
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(JJK_DEBUG)
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            System.out.println("***** DOM2DTM Crosscheck:");
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            for(int i=0;i<m_nodes.size();++i)
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              System.out.println(i+":\t"+m_firstch.elementAt(i)+"\t"+m_nextsib.elementAt(i));
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return false;
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Text needs some special handling:
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // DTM may skip whitespace. This is handled by the suppressNode flag, which
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // when true will keep the DTM node from being created.
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // DTM only directly records the first DOM node of any logically-contiguous
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // sequence. The lastTextNode value will be set to the last node in the
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // contiguous sequence, and -- AFTER the DTM addNode -- can be used to
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // advance next over this whole block. Should be simpler than special-casing
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // the above loop for "Was the logically-preceeding sibling a text node".
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Finally, a DTM node should be considered a CDATASection only if all the
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // contiguous text it covers is CDATASections. The first Text should
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // force DTM to Text.
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean suppressNode=false;
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node lastTextNode=null;
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    nexttype=next.getNodeType();
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // nexttype=pos.getNodeType();
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype)
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // If filtering, initially assume we're going to suppress the node
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        suppressNode=((null != m_wsfilter) && getShouldStripWhitespace());
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Scan logically contiguous text (siblings, plus "flattening"
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // of entity reference boundaries).
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Node n=next;
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while(n!=null)
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            lastTextNode=n;
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Any Text node means DTM considers it all Text
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(TEXT_NODE == n.getNodeType())
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              nexttype=TEXT_NODE;
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Any non-whitespace in this sequence blocks whitespace
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // suppression
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            suppressNode &=
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              XMLCharacterRecognizer.isWhiteSpace(n.getNodeValue());
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            n=logicalNextDOMTextNode(n);
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Special handling for PIs: Some DOMs represent the XML
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Declaration as a PI. This is officially incorrect, per the DOM
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // spec, but is considered a "wrong but tolerable" temporary
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // workaround pending proper handling of these fields in DOM Level
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // 3. We want to recognize and reject that case.
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if(PROCESSING_INSTRUCTION_NODE==nexttype)
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        suppressNode = (pos.getNodeName().toLowerCase().equals("xml"));
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(!suppressNode)
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Inserting next. NOTE that we force the node type; for
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // coalesced Text, this records CDATASections adjacent to
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // ordinary Text as Text.
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int nextindex=addNode(next,m_last_parent,m_last_kid,
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson			      nexttype);
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_last_kid=nextindex;
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(ELEMENT_NODE == nexttype)
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            int attrIndex=NULL; // start with no previous sib
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Process attributes _now_, rather than waiting.
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Simpler control flow, makes NS cache available immediately.
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            NamedNodeMap attrs=next.getAttributes();
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            int attrsize=(attrs==null) ? 0 : attrs.getLength();
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(attrsize>0)
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              {
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                for(int i=0;i<attrsize;++i)
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // No need to force nodetype in this case;
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // addNode() will take care of switching it from
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // Attr to Namespace if necessary.
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    attrIndex=addNode(attrs.item(i),
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                      nextindex,attrIndex,NULL);
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    m_firstch.setElementAt(DTM.NULL,attrIndex);
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // If the xml: prefix is explicitly declared
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // we don't need to synthesize one.
5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    //
5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // NOTE that XML Namespaces were not originally
5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // defined as being namespace-aware (grrr), and
5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // while the W3C is planning to fix this it's
5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // safer for now to test the QName and trust the
5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // parsers to prevent anyone from redefining the
5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		    // reserved xmlns: prefix
5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(!m_processedFirstElement
5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                       && "xmlns:xml".equals(attrs.item(i).getNodeName()))
5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      m_processedFirstElement=true;
5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Terminate list of attrs, and make sure they aren't
5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // considered children of the element
5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              } // if attrs exist
5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(!m_processedFirstElement)
5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            {
5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // The DOM might not have an explicit declaration for the
5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // implicit "xml:" prefix, but the XPath data model
5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // requires that this appear as a Namespace Node so we
5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // have to synthesize one. You can think of this as
5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // being a default attribute defined by the XML
5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              // Namespaces spec rather than by the DTD.
5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              attrIndex=addNode(new DOM2DTMdefaultNamespaceDeclarationNode(
5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson																	(Element)next,"xml",NAMESPACE_DECL_NS,
5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson																	makeNodeHandle(((attrIndex==NULL)?nextindex:attrIndex)+1)
5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson																	),
5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                nextindex,attrIndex,NULL);
5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              m_firstch.setElementAt(DTM.NULL,attrIndex);
5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              m_processedFirstElement=true;
5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(attrIndex!=NULL)
5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              m_nextsib.setElementAt(DTM.NULL,attrIndex);
5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          } //if(ELEMENT_NODE)
5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      } // (if !suppressNode)
5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Text postprocessing: Act on values stored above
5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype)
5859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // %TBD% If nexttype was forced to TEXT, patch the DTM node
5879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        next=lastTextNode;      // Advance the DOM cursor over contiguous text
5899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Remember where we left off.
5929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_pos=next;
5939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return true;
5949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return an DOM node for the given node.
5999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node ID.
6019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return A node representation of the DTM node.
6039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public Node getNode(int nodeHandle)
6059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int identity = makeNodeIdentity(nodeHandle);
6089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return (Node) m_nodes.elementAt(identity);
6109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
6139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a Node from an identity index.
6149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NEEDSDOC @param nodeIdentity
6169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NEEDSDOC ($objectName$) @return
6189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected Node lookupNode(int nodeIdentity)
6209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return (Node) m_nodes.elementAt(nodeIdentity);
6229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
6259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the next node identity value in the list, and call the iterator
6269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * if it hasn't been added yet.
6279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param identity The node identity (index).
6299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return identity+1, or DTM.NULL.
6309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int getNextNodeIdentity(int identity)
6329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    identity += 1;
6359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (identity >= m_nodes.size())
6379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!nextNode())
6399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        identity = DTM.NULL;
6409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return identity;
6439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
6469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the handle from a Node.
6479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>%OPT% This will be pretty slow.</p>
6489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>%OPT% An XPath-like search (walk up DOM to root, tracking path;
6509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * walk down DTM reconstructing path) might be considerably faster
6519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * on later nodes in large documents. That might also imply improving
6529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this call to handle nodes which would be in this DTM but
6539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * have not yet been built, which might or might not be a Good Thing.</p>
6549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% This relies on being able to test node-identity via
6569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * object-identity. DTM2DOM proxying is a great example of a case where
6579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * that doesn't work. DOM Level 3 will provide the isSameNode() method
6589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to fix that, but until then this is going to be flaky.
6599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node A node, which may be null.
6619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The node handle or <code>DTM.NULL</code>.
6639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private int getHandleFromNode(Node node)
6659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != node)
6679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int len = m_nodes.size();
6699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      boolean isMore;
6709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int i = 0;
6719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      do
6729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
6739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        for (; i < len; i++)
6749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
6759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (m_nodes.elementAt(i) == node)
6769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return makeNodeHandle(i);
6779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
6789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        isMore = nextNode();
6809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        len = m_nodes.size();
6829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
6849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while(isMore || i < len);
6859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return DTM.NULL;
6889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** Get the handle from a Node. This is a more robust version of
6919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * getHandleFromNode, intended to be usable by the public.
6929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>%OPT% This will be pretty slow.</p>
6949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% This relies on being able to test node-identity via
6969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * object-identity. DTM2DOM proxying is a great example of a case where
6979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * that doesn't work. DOM Level 3 will provide the isSameNode() method
6989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to fix that, but until then this is going to be flaky.
6999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node A node, which may be null.
7019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The node handle or <code>DTM.NULL</code>.  */
7039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getHandleOfNode(Node node)
7049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != node)
7069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Is Node actually within the same document? If not, don't search!
7089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // This would be easier if m_root was always the Document node, but
7099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // we decided to allow wrapping a DTM around a subtree.
7109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if((m_root==node) ||
7119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         (m_root.getNodeType()==DOCUMENT_NODE &&
7129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_root==node.getOwnerDocument()) ||
7139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         (m_root.getNodeType()!=DOCUMENT_NODE &&
7149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_root.getOwnerDocument()==node.getOwnerDocument())
7159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         )
7169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
7179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // If node _is_ in m_root's tree, find its handle
7189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          //
7199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // %OPT% This check may be improved significantly when DOM
7209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // Level 3 nodeKey and relative-order tests become
7219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // available!
7229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          for(Node cursor=node;
7239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              cursor!=null;
7249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              cursor=
7259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                (cursor.getNodeType()!=ATTRIBUTE_NODE)
7269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                ? cursor.getParentNode()
7279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                : ((org.w3c.dom.Attr)cursor).getOwnerElement())
7289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            {
7299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              if(cursor==m_root)
7309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // We know this node; find its handle.
7319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return getHandleFromNode(node);
7329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            } // for ancestors of node
7339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } // if node and m_root in same Document
7349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // if node!=null
7359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return DTM.NULL;
7379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieves an attribute node by by qualified name and namespace URI.
7419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle int Handle of the node upon which to look up this attribute..
7439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param namespaceURI The namespace URI of the attribute to
7449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   retrieve, or null.
7459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param name The local name of the attribute to
7469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   retrieve.
7479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The attribute node handle with the specified name (
7489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
7499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   attribute.
7509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
7519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getAttributeNode(int nodeHandle, String namespaceURI,
7529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                              String name)
7539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %OPT% This is probably slower than it needs to be.
7569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null == namespaceURI)
7579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      namespaceURI = "";
7589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int type = getNodeType(nodeHandle);
7609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (DTM.ELEMENT_NODE == type)
7629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Assume that attributes immediately follow the element.
7659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int identity = makeNodeIdentity(nodeHandle);
7669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
7689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
7699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Assume this can not be null.
7709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        type = _type(identity);
7719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// %REVIEW%
7739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// Should namespace nodes be retrievable DOM-style as attrs?
7749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// If not we need a separate function... which may be desirable
7759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// architecturally, but which is ugly from a code point of view.
7769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// (If we REALLY insist on it, this code should become a subroutine
7779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// of both -- retrieve the node, then test if the type matches
7789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				// what you're looking for.)
7799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (type == DTM.ATTRIBUTE_NODE || type==DTM.NAMESPACE_NODE)
7809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
7819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Node node = lookupNode(identity);
7829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          String nodeuri = node.getNamespaceURI();
7839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (null == nodeuri)
7859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            nodeuri = "";
7869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          String nodelocalname = node.getLocalName();
7889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (nodeuri.equals(namespaceURI) && name.equals(nodelocalname))
7909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return makeNodeHandle(identity);
7919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
7929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else // if (DTM.NAMESPACE_NODE != type)
7949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
7959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          break;
7969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
7979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
7989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
7999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return DTM.NULL;
8019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
8029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
8049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the string-value of a node as a String object
8059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * (see http://www.w3.org/TR/xpath#data-model
8069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * for the definition of a node's string-value).
8079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node ID.
8099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return A string object that represents the string-value of the given node.
8119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
8129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XMLString getStringValue(int nodeHandle)
8139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
8149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int type = getNodeType(nodeHandle);
8169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node node = getNode(nodeHandle);
8179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %TBD% If an element only has one text node, we should just use it
8189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // directly.
8199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(DTM.ELEMENT_NODE == type || DTM.DOCUMENT_NODE == type
8209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    || DTM.DOCUMENT_FRAGMENT_NODE == type)
8219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      FastStringBuffer buf = StringBufferPool.get();
8239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String s;
8249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      try
8269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        getNodeData(node, buf);
8289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        s = (buf.length() > 0) ? buf.toString() : "";
8309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      finally
8329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        StringBufferPool.free(buf);
8349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return m_xstrf.newstr( s );
8379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
8389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if(TEXT_NODE == type || CDATA_SECTION_NODE == type)
8399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // If this is a DTM text node, it may be made of multiple DOM text
8419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // nodes -- including navigating into Entity References. DOM2DTM
8429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // records the first node in the sequence and requires that we
8439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // pick up the others when we retrieve the DTM node's value.
8449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      //
8459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // %REVIEW% DOM Level 3 is expected to add a "whole text"
8469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // retrieval method which performs this function for us.
8479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      FastStringBuffer buf = StringBufferPool.get();
8489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while(node!=null)
8499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        buf.append(node.getNodeValue());
8519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        node=logicalNextDOMTextNode(node);
8529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String s=(buf.length() > 0) ? buf.toString() : "";
8549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      StringBufferPool.free(buf);
8559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return m_xstrf.newstr( s );
8569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
8579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
8589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return m_xstrf.newstr( node.getNodeValue() );
8599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
8609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
8629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Determine if the string-value of a node is whitespace
8639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node Handle.
8659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return Return true if the given node is whitespace.
8679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
8689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public boolean isWhitespace(int nodeHandle)
8699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
8709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	int type = getNodeType(nodeHandle);
8719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node node = getNode(nodeHandle);
8729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  	if(TEXT_NODE == type || CDATA_SECTION_NODE == type)
8739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // If this is a DTM text node, it may be made of multiple DOM text
8759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // nodes -- including navigating into Entity References. DOM2DTM
8769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // records the first node in the sequence and requires that we
8779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // pick up the others when we retrieve the DTM node's value.
8789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      //
8799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // %REVIEW% DOM Level 3 is expected to add a "whole text"
8809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // retrieval method which performs this function for us.
8819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      FastStringBuffer buf = StringBufferPool.get();
8829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while(node!=null)
8839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        buf.append(node.getNodeValue());
8859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        node=logicalNextDOMTextNode(node);
8869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     boolean b = buf.isWhitespace(0, buf.length());
8889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      StringBufferPool.free(buf);
8899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     return b;
8909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
8919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return false;
8929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
8939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
8959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve the text content of a DOM subtree, appending it into a
8969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * user-supplied FastStringBuffer object. Note that attributes are
8979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * not considered part of the content of an element.
8989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
8999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * There are open questions regarding whitespace stripping.
9009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Currently we make no special effort in that regard, since the standard
9019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DOM doesn't yet provide DTD-based information to distinguish
9029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * whitespace-in-element-context from genuine #PCDATA. Note that we
9039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * should probably also consider xml:space if/when we address this.
9049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DOM Level 3 may solve the problem for us.
9059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
9069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% Actually, since this method operates on the DOM side of the
9079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * fence rather than the DTM side, it SHOULDN'T do
9089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * any special handling. The DOM does what the DOM does; if you want
9099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DTM-level abstractions, use DTM-level methods.
9109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node Node whose subtree is to be walked, gathering the
9129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * contents of all Text or CDATASection nodes.
9139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param buf FastStringBuffer into which the contents of the text
9149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * nodes are to be concatenated.
9159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
9169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected static void getNodeData(Node node, FastStringBuffer buf)
9179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
9189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    switch (node.getNodeType())
9209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
9219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.DOCUMENT_FRAGMENT_NODE :
9229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.DOCUMENT_NODE :
9239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.ELEMENT_NODE :
9249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
9259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      for (Node child = node.getFirstChild(); null != child;
9269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              child = child.getNextSibling())
9279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
9289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        getNodeData(child, buf);
9299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
9309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
9319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
9329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.TEXT_NODE :
9339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.CDATA_SECTION_NODE :
9349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.ATTRIBUTE_NODE :	// Never a child but might be our starting node
9359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      buf.append(node.getNodeValue());
9369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
9379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.PROCESSING_INSTRUCTION_NODE :
9389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING);
9399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
9409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    default :
9419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // ignore
9429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
9439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
9449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
9459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
9479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return its DOM-style node name. This will
9489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * include names such as #text or #document.
9499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle the id of the node.
9519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String Name of this node, which may be an empty string.
9529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% Document when empty string is possible...
9539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW-COMMENT% It should never be empty, should it?
9549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
9559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getNodeName(int nodeHandle)
9569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
9579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node node = getNode(nodeHandle);
9599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Assume non-null.
9619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return node.getNodeName();
9629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
9639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
9659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return the XPath node name.  This should be
9669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the name as described by the XPath data model, NOT the DOM-style
9679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * name.
9689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle the id of the node.
9709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String Name of this node, which may be an empty string.
9719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
9729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getNodeNameX(int nodeHandle)
9739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
9749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String name;
9769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    short type = getNodeType(nodeHandle);
9779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    switch (type)
9799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
9809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.NAMESPACE_NODE :
9819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
9829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
9839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // assume not null.
9859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      name = node.getNodeName();
9869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(name.startsWith("xmlns:"))
9879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
9889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        name = QName.getLocalPart(name);
9899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
9909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if(name.equals("xmlns"))
9919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
9929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        name = "";
9939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
9949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
9959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
9969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.ATTRIBUTE_NODE :
9979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.ELEMENT_NODE :
9989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.ENTITY_REFERENCE_NODE :
9999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.PROCESSING_INSTRUCTION_NODE :
10009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
10019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
10029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // assume not null.
10049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      name = node.getNodeName();
10059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
10069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
10079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    default :
10089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      name = "";
10099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
10109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return name;
10129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
10139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
10159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return its XPath-style localname.
10169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * (As defined in Namespaces, this is the portion of the name after any
10179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * colon character).
10189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle the id of the node.
10209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String Local name of this node.
10219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
10229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getLocalName(int nodeHandle)
10239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
10249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(JJK_NEWCODE)
10259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
10269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int id=makeNodeIdentity(nodeHandle);
10279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(NULL==id) return null;
10289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node newnode=(Node)m_nodes.elementAt(id);
10299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String newname=newnode.getLocalName();
10309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null == newname)
10319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// XSLT treats PIs, and possibly other things, as having QNames.
10339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	String qname = newnode.getNodeName();
10349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	if('#'==qname.charAt(0))
10359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
10369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  //  Match old default for this function
10379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // This conversion may or may not be necessary
10389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  newname="";
10399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
10409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	else
10419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
10429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  int index = qname.indexOf(':');
10439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  newname = (index < 0) ? qname : qname.substring(index + 1);
10449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
10459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return newname;
10479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
10489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
10499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
10509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String name;
10519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      short type = getNodeType(nodeHandle);
10529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      switch (type)
10539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ATTRIBUTE_NODE :
10559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ELEMENT_NODE :
10569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ENTITY_REFERENCE_NODE :
10579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.NAMESPACE_NODE :
10589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.PROCESSING_INSTRUCTION_NODE :
10599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
10609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  Node node = getNode(nodeHandle);
10619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // assume not null.
10639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  name = node.getLocalName();
10649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  if (null == name)
10669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  {
10679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	    String qname = node.getNodeName();
10689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	    int index = qname.indexOf(':');
10699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	    name = (index < 0) ? qname : qname.substring(index + 1);
10719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  }
10729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
10739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	break;
10749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      default :
10759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	name = "";
10769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return name;
10789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
10799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
10809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
10829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a namespace handle, return the prefix that the namespace decl is
10839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * mapping.
10849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return the prefix used to map to the namespace.
10859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p> %REVIEW% Are you sure you want "" for no prefix?  </p>
10879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb  </p>
10889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle the id of the node.
10909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String prefix of this node's name, or "" if no explicit
10919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * namespace prefix was given.
10929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
10939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getPrefix(int nodeHandle)
10949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
10959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String prefix;
10979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    short type = getNodeType(nodeHandle);
10989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    switch (type)
11009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.NAMESPACE_NODE :
11029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
11049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // assume not null.
11069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String qname = node.getNodeName();
11079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int index = qname.indexOf(':');
11089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      prefix = (index < 0) ? "" : qname.substring(index + 1);
11109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
11129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.ATTRIBUTE_NODE :
11139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case DTM.ELEMENT_NODE :
11149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
11169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // assume not null.
11189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String qname = node.getNodeName();
11199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int index = qname.indexOf(':');
11209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      prefix = (index < 0) ? "" : qname.substring(0, index);
11229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
11249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    default :
11259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      prefix = "";
11269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return prefix;
11299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
11329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return its DOM-style namespace URI
11339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * (As defined in Namespaces, this is the declared URI which this node's
11349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * prefix -- or default in lieu thereof -- was mapped to.)
11359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>%REVIEW% Null or ""? -sb</p>
11379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle the id of the node.
11399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String URI value of this node's namespace, or null if no
11409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * namespace was resolved.
11419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
11429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getNamespaceURI(int nodeHandle)
11439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
11449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(JJK_NEWCODE)
11459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int id=makeNodeIdentity(nodeHandle);
11479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(id==NULL) return null;
11489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node=(Node)m_nodes.elementAt(id);
11499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return node.getNamespaceURI();
11509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
11529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String nsuri;
11549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      short type = getNodeType(nodeHandle);
11559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      switch (type)
11579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
11589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ATTRIBUTE_NODE :
11599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ELEMENT_NODE :
11609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.ENTITY_REFERENCE_NODE :
11619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.NAMESPACE_NODE :
11629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case DTM.PROCESSING_INSTRUCTION_NODE :
11639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
11649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  Node node = getNode(nodeHandle);
11659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // assume not null.
11679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  nsuri = node.getNamespaceURI();
11689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // %TBD% Handle DOM1?
11709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
11719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	break;
11729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      default :
11739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	nsuri = null;
11749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
11759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return nsuri;
11779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** Utility function: Given a DOM Text node, determine whether it is
11829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * logically followed by another Text or CDATASection node. This may
11839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * involve traversing into Entity References.
11849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% DOM Level 3 is expected to add functionality which may
11869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * allow us to retire this.
11879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
11889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private Node logicalNextDOMTextNode(Node n)
11899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
11909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Node p=n.getNextSibling();
11919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(p==null)
11929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
11939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Walk out of any EntityReferenceNodes that ended with text
11949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                for(n=n.getParentNode();
11959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        n!=null && ENTITY_REFERENCE_NODE == n.getNodeType();
11969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        n=n.getParentNode())
11979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                {
11989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        p=n.getNextSibling();
11999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        if(p!=null)
12009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                break;
12019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
12029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
12039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        n=p;
12049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while(n!=null && ENTITY_REFERENCE_NODE == n.getNodeType())
12059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
12069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Walk into any EntityReferenceNodes that start with text
12079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(n.hasChildNodes())
12089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        n=n.getFirstChild();
12099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                else
12109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        n=n.getNextSibling();
12119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
12129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(n!=null)
12139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
12149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Found a logical next sibling. Is it text?
12159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                int ntype=n.getNodeType();
12169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(TEXT_NODE != ntype && CDATA_SECTION_NODE != ntype)
12179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        n=null;
12189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
12199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return n;
12209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
12219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
12239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a node handle, return its node value. This is mostly
12249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * as defined by the DOM, but may ignore some conveniences.
12259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
12269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node id.
12289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String Value of this node, or null if not
12299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * meaningful for this node type.
12309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
12319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getNodeValue(int nodeHandle)
12329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
12339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // The _type(nodeHandle) call was taking the lion's share of our
12349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // time, and was wrong anyway since it wasn't coverting handle to
12359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // identity. Inlined it.
12369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int type = _exptype(makeNodeIdentity(nodeHandle));
12379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    type=(NULL != type) ? getNodeType(nodeHandle) : NULL;
12389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(TEXT_NODE!=type && CDATA_SECTION_NODE!=type)
12409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return getNode(nodeHandle).getNodeValue();
12419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // If this is a DTM text node, it may be made of multiple DOM text
12439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // nodes -- including navigating into Entity References. DOM2DTM
12449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // records the first node in the sequence and requires that we
12459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // pick up the others when we retrieve the DTM node's value.
12469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
12479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW% DOM Level 3 is expected to add a "whole text"
12489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // retrieval method which performs this function for us.
12499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node node = getNode(nodeHandle);
12509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Node n=logicalNextDOMTextNode(node);
12519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(n==null)
12529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return node.getNodeValue();
12539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    FastStringBuffer buf = StringBufferPool.get();
12559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        buf.append(node.getNodeValue());
12569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while(n!=null)
12579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
12589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      buf.append(n.getNodeValue());
12599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      n=logicalNextDOMTextNode(n);
12609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
12619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String s = (buf.length() > 0) ? buf.toString() : "";
12629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    StringBufferPool.free(buf);
12639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return s;
12649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
12659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
12679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *   A document type declaration information item has the following properties:
12689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *     1. [system identifier] The system identifier of the external subset, if
12709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *        it exists. Otherwise this property has no value.
12719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the system identifier String object, or null if there is none.
12739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
12749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getDocumentTypeDeclarationSystemIdentifier()
12759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
12769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Document doc;
12789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_root.getNodeType() == Node.DOCUMENT_NODE)
12809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      doc = (Document) m_root;
12819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
12829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      doc = m_root.getOwnerDocument();
12839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != doc)
12859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
12869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DocumentType dtd = doc.getDoctype();
12879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != dtd)
12899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
12909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return dtd.getSystemId();
12919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
12929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
12939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
12959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
12969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
12989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return the public identifier of the external subset,
12999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * normalized as described in 4.2.2 External Entities [XML]. If there is
13009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * no external subset or if it has no public identifier, this property
13019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * has no value.
13029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the public identifier String object, or null if there is none.
13049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
13059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getDocumentTypeDeclarationPublicIdentifier()
13069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
13079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Document doc;
13099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_root.getNodeType() == Node.DOCUMENT_NODE)
13119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      doc = (Document) m_root;
13129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
13139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      doc = m_root.getOwnerDocument();
13149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != doc)
13169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
13179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DocumentType dtd = doc.getDoctype();
13189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != dtd)
13209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
13219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return dtd.getPublicId();
13229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
13269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
13279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
13299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Returns the <code>Element</code> whose <code>ID</code> is given by
13309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <code>elementId</code>. If no such element exists, returns
13319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <code>DTM.NULL</code>. Behavior is not defined if more than one element
13329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * has this <code>ID</code>. Attributes (including those
13339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * with the name "ID") are not of type ID unless so defined by DTD/Schema
13349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * information available to the DTM implementation.
13359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Implementations that do not know whether attributes are of type ID or
13369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * not are expected to return <code>DTM.NULL</code>.
13379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>%REVIEW% Presumably IDs are still scoped to a single document,
13399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * and this operation searches only within a single document, right?
13409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Wouldn't want collisions between DTMs in the same process.</p>
13419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param elementId The unique <code>id</code> value for an element.
13439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The handle of the matching element.
13449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
13459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getElementById(String elementId)
13469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
13479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Document doc = (m_root.getNodeType() == Node.DOCUMENT_NODE)
13499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ? (Document) m_root : m_root.getOwnerDocument();
13509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(null != doc)
13529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
13539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node elem = doc.getElementById(elementId);
13549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(null != elem)
13559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
13569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int elemHandle = getHandleFromNode(elem);
13579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(DTM.NULL == elemHandle)
13599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
13609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          int identity = m_nodes.size()-1;
13619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
13629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
13639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Node node = getNode(identity);
13649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(node == elem)
13659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            {
13669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              elemHandle = getHandleFromNode(elem);
13679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              break;
13689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
13699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson           }
13709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
13719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return elemHandle;
13739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return DTM.NULL;
13779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
13789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
13809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The getUnparsedEntityURI function returns the URI of the unparsed
13819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * entity with the specified name in the same document as the context
13829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * node (see [3.3 Unparsed Entities]). It returns the empty string if
13839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * there is no such entity.
13849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
13859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * XML processors may choose to use the System Identifier (if one
13869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * is provided) to resolve the entity, rather than the URI in the
13879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Public Identifier. The details are dependent on the processor, and
13889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * we would have to support some form of plug-in resolver to handle
13899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this properly. Currently, we simply return the System Identifier if
13909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * present, and hope that it a usable URI or that our caller can
13919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * map it to one.
13929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * TODO: Resolve Public Identifiers... or consider changing function name.
13939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
13949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * If we find a relative URI
13959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * reference, XML expects it to be resolved in terms of the base URI
13969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of the document. The DOM doesn't do that for us, and it isn't
13979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * entirely clear whether that should be done here; currently that's
13989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * pushed up to a higher level of our application. (Note that DOM Level
13999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * 1 didn't store the document's base URI.)
14009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * TODO: Consider resolving Relative URIs.
14019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
14029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * (The DOM's statement that "An XML processor may choose to
14039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * completely expand entities before the structure model is passed
14049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to the DOM" refers only to parsed entities, not unparsed, and hence
14059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * doesn't affect this function.)
14069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param name A string containing the Entity Name of the unparsed
14089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * entity.
14099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return String containing the URI of the Unparsed Entity, or an
14119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * empty string if no such entity exists.
14129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
14139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public String getUnparsedEntityURI(String name)
14149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
14159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String url = "";
14179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Document doc = (m_root.getNodeType() == Node.DOCUMENT_NODE)
14189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ? (Document) m_root : m_root.getOwnerDocument();
14199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != doc)
14219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DocumentType doctype = doc.getDoctype();
14239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != doctype)
14259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
14269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        NamedNodeMap entities = doctype.getEntities();
14279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(null == entities)
14289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          return url;
14299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Entity entity = (Entity) entities.getNamedItem(name);
14309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if(null == entity)
14319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          return url;
14329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String notationName = entity.getNotationName();
14349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (null != notationName)  // then it's unparsed
14369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
14379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // The draft says: "The XSLT processor may use the public
14389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // identifier to generate a URI for the entity instead of the URI
14399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // specified in the system identifier. If the XSLT processor does
14409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // not use the public identifier to generate the URI, it must use
14419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // the system identifier; if the system identifier is a relative
14429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // URI, it must be resolved into an absolute URI using the URI of
14439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // the resource containing the entity declaration as the base
14449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // URI [RFC2396]."
14459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // So I'm falling a bit short here.
14469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          url = entity.getSystemId();
14479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (null == url)
14499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
14509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            url = entity.getPublicId();
14519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
14529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          else
14539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
14549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // This should be resolved to an absolute URL, but that's hard
14559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // to do from here.
14569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
14579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
14589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
14599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return url;
14629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
14639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
14659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *     5. [specified] A flag indicating whether this attribute was actually
14669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *        specified in the start-tag of its element, or was defaulted from the
14679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *        DTD.
14689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param attributeHandle the attribute handle
14709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return <code>true</code> if the attribute was specified;
14719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         <code>false</code> if it was defaulted.
14729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
14739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public boolean isAttributeSpecified(int attributeHandle)
14749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
14759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int type = getNodeType(attributeHandle);
14769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (DTM.ATTRIBUTE_NODE == type)
14789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Attr attr = (Attr)getNode(attributeHandle);
14809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return attr.getSpecified();
14819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return false;
14839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
14849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** Bind an IncrementalSAXSource to this DTM. NOT RELEVANT for DOM2DTM, since
14869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * we're wrapped around an existing DOM.
14879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param source The IncrementalSAXSource that we want to recieve events from
14899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * on demand.
14909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
14919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setIncrementalSAXSource(IncrementalSAXSource source)
14929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
14939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
14949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** getContentHandler returns "our SAX builder" -- the thing that
14969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * someone else should send SAX events to in order to extend this
14979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DTM model.
14989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to SAX events,
15009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * "this" if the DTM object has a built-in SAX ContentHandler,
15019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the IncrmentalSAXSource if we're bound to one and should receive
15029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the SAX stream via it for incremental build purposes...
15039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * */
15049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.ContentHandler getContentHandler()
15059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return null;
15079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return this DTM's lexical handler.
15119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% Should this return null if constrution already done/begun?
15139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to lexical SAX events,
15159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * "this" if the DTM object has a built-in SAX ContentHandler,
15169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the IncrementalSAXSource if we're bound to one and should receive
15179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the SAX stream via it for incremental build purposes...
15189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.ext.LexicalHandler getLexicalHandler()
15209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
15239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return this DTM's EntityResolver.
15289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to SAX entity ref events.
15309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.EntityResolver getEntityResolver()
15329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
15359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return this DTM's DTDHandler.
15399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to SAX dtd events.
15419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.DTDHandler getDTDHandler()
15439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
15469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return this DTM's ErrorHandler.
15509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to SAX error events.
15529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.ErrorHandler getErrorHandler()
15549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
15579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return this DTM's DeclHandler.
15619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null if this model doesn't respond to SAX Decl events.
15639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public org.xml.sax.ext.DeclHandler getDeclHandler()
15659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
15689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** @return true iff we're building this model incrementally (eg
15719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * we're partnered with a IncrementalSAXSource) and thus require that the
15729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * transformation and the parse run simultaneously. Guidance to the
15739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DTMManager.
15749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * */
15759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public boolean needsTwoThreads()
15769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return false;
15789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // ========== Direct SAX Dispatch, for optimization purposes ========
15819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Returns whether the specified <var>ch</var> conforms to the XML 1.0 definition
15849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of whitespace.  Refer to <A href="http://www.w3.org/TR/1998/REC-xml-19980210#NT-S">
15859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the definition of <CODE>S</CODE></A> for details.
15869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param   ch      Character to check as XML whitespace.
15879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return          =true if <var>ch</var> is XML whitespace; otherwise =false.
15889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private static boolean isSpace(char ch)
15909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return XMLCharacterRecognizer.isWhiteSpace(ch);  // Take the easy way out for now.
15929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Directly call the
15969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * characters method on the passed ContentHandler for the
15979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
15989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * for the definition of a node's string-value). Multiple calls to the
15999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * ContentHandler's characters methods may well occur for a single call to
16009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this method.
16019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node ID.
16039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param ch A non-null reference to a ContentHandler.
16049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws org.xml.sax.SAXException
16069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
16079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void dispatchCharactersEvents(
16089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          int nodeHandle, org.xml.sax.ContentHandler ch,
16099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          boolean normalize)
16109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws org.xml.sax.SAXException
16119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
16129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(normalize)
16139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      XMLString str = getStringValue(nodeHandle);
16159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      str = str.fixWhiteSpace(true, true, false);
16169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      str.dispatchCharactersEvents(ch);
16179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
16199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int type = getNodeType(nodeHandle);
16219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
16229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      dispatchNodeData(node, ch, 0);
16239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // Text coalition -- a DTM text node may represent multiple
16249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // DOM nodes.
16259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if(TEXT_NODE == type || CDATA_SECTION_NODE == type)
16269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
16279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  while( null != (node=logicalNextDOMTextNode(node)) )
16289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  {
16299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                      dispatchNodeData(node, ch, 0);
16309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  }
16319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
16329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
16349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
16369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve the text content of a DOM subtree, appending it into a
16379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * user-supplied FastStringBuffer object. Note that attributes are
16389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * not considered part of the content of an element.
16399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
16409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * There are open questions regarding whitespace stripping.
16419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Currently we make no special effort in that regard, since the standard
16429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DOM doesn't yet provide DTD-based information to distinguish
16439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * whitespace-in-element-context from genuine #PCDATA. Note that we
16449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * should probably also consider xml:space if/when we address this.
16459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * DOM Level 3 may solve the problem for us.
16469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
16479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * %REVIEW% Note that as a DOM-level operation, it can be argued that this
16489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * routine _shouldn't_ perform any processing beyond what the DOM already
16499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * does, and that whitespace stripping and so on belong at the DTM level.
16509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * If you want a stripped DOM view, wrap DTM2DOM around DOM2DTM.
16519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node Node whose subtree is to be walked, gathering the
16539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * contents of all Text or CDATASection nodes.
16549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
16559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected static void dispatchNodeData(Node node,
16569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                         org.xml.sax.ContentHandler ch,
16579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                         int depth)
16589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws org.xml.sax.SAXException
16599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
16609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    switch (node.getNodeType())
16629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.DOCUMENT_FRAGMENT_NODE :
16649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.DOCUMENT_NODE :
16659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.ELEMENT_NODE :
16669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      for (Node child = node.getFirstChild(); null != child;
16689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              child = child.getNextSibling())
16699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
16709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        dispatchNodeData(child, ch, depth+1);
16719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    break;
16749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.PROCESSING_INSTRUCTION_NODE : // %REVIEW%
16759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.COMMENT_NODE :
16769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(0 != depth)
16779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        break;
16789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // NOTE: Because this operation works in the DOM space, it does _not_ attempt
16799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // to perform Text Coalition. That should only be done in DTM space.
16809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.TEXT_NODE :
16819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.CDATA_SECTION_NODE :
16829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    case Node.ATTRIBUTE_NODE :
16839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String str = node.getNodeValue();
16849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(ch instanceof CharacterNodeHandler)
16859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
16869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ((CharacterNodeHandler)ch).characters(node);
16879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
16899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
16909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ch.characters(str.toCharArray(), 0, str.length());
16919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
16939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//    /* case Node.PROCESSING_INSTRUCTION_NODE :
16949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//      // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING);
16959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//      break; */
16969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    default :
16979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // ignore
16989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
16999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  TreeWalker m_walker = new TreeWalker(null);
17039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
17059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Directly create SAX parser events from a subtree.
17069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeHandle The node ID.
17089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param ch A non-null reference to a ContentHandler.
17099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws org.xml.sax.SAXException
17119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
17129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch)
17139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws org.xml.sax.SAXException
17149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
17159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    TreeWalker treeWalker = m_walker;
17169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    ContentHandler prevCH = treeWalker.getContentHandler();
17179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(null != prevCH)
17199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      treeWalker = new TreeWalker(null);
17219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    treeWalker.setContentHandler(ch);
17239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
17259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Node node = getNode(nodeHandle);
17279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      treeWalker.traverseFragment(node);
17289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    finally
17309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      treeWalker.setContentHandler(null);
17329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public interface CharacterNodeHandler
17369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
17379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public void characters(Node node)
17389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws org.xml.sax.SAXException;
17399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
17429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * For the moment all the run time properties are ignored by this
17439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * class.
17449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param property a <code>String</code> value
17469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param value an <code>Object</code> value
17479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
17489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setProperty(String property, Object value)
17499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
17509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
17539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * No source information is available for DOM2DTM, so return
17549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <code>null</code> here.
17559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param node an <code>int</code> value
17579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return null
17589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
17599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public SourceLocator getSourceLocatorFor(int node)
17609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
17619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return null;
17629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
17659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1767