dom2dtm.java

来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,770 行 · 第 1/4 页

JAVA
1,770
字号
    if(next==null)      {        m_nextsib.setElementAt(NULL,0);        m_nodesAreProcessed = true;        m_pos=null;                        if(JJK_DEBUG)          {            System.out.println("***** DOM2DTM Crosscheck:");            for(int i=0;i<m_nodes.size();++i)              System.out.println(i+":\t"+m_firstch.elementAt(i)+"\t"+m_nextsib.elementAt(i));          }                        return false;      }    // Text needs some special handling:    //    // DTM may skip whitespace. This is handled by the suppressNode flag, which    // when true will keep the DTM node from being created.    //    // DTM only directly records the first DOM node of any logically-contiguous    // sequence. The lastTextNode value will be set to the last node in the     // contiguous sequence, and -- AFTER the DTM addNode -- can be used to     // advance next over this whole block. Should be simpler than special-casing    // the above loop for "Was the logically-preceeding sibling a text node".    //     // Finally, a DTM node should be considered a CDATASection only if all the    // contiguous text it covers is CDATASections. The first Text should    // force DTM to Text.            boolean suppressNode=false;    Node lastTextNode=null;    nexttype=next.getNodeType();            // nexttype=pos.getNodeType();    if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype)      {        // If filtering, initially assume we're going to suppress the node        suppressNode=((null != m_wsfilter) && getShouldStripWhitespace());        // Scan logically contiguous text (siblings, plus "flattening"        // of entity reference boundaries).        Node n=next;        while(n!=null)          {            lastTextNode=n;            // Any Text node means DTM considers it all Text            if(TEXT_NODE == n.getNodeType())              nexttype=TEXT_NODE;            // Any non-whitespace in this sequence blocks whitespace            // suppression            suppressNode &=              XMLCharacterRecognizer.isWhiteSpace(n.getNodeValue());                                    n=logicalNextDOMTextNode(n);          }      }            // Special handling for PIs: Some DOMs represent the XML    // Declaration as a PI. This is officially incorrect, per the DOM    // spec, but is considered a "wrong but tolerable" temporary    // workaround pending proper handling of these fields in DOM Level    // 3. We want to recognize and reject that case.    else if(PROCESSING_INSTRUCTION_NODE==nexttype)      {        suppressNode = (pos.getNodeName().toLowerCase().equals("xml"));      }                    if(!suppressNode)      {        // Inserting next. NOTE that we force the node type; for        // coalesced Text, this records CDATASections adjacent to        // ordinary Text as Text.        int nextindex=addNode(next,m_last_parent,m_last_kid,			      nexttype);	        m_last_kid=nextindex;        if(ELEMENT_NODE == nexttype)          {            int attrIndex=NULL; // start with no previous sib            // Process attributes _now_, rather than waiting.            // Simpler control flow, makes NS cache available immediately.            NamedNodeMap attrs=next.getAttributes();            int attrsize=(attrs==null) ? 0 : attrs.getLength();            if(attrsize>0)              {                for(int i=0;i<attrsize;++i)                  {                    // No need to force nodetype in this case;                    // addNode() will take care of switching it from                    // Attr to Namespace if necessary.                    attrIndex=addNode(attrs.item(i),                                      nextindex,attrIndex,NULL);                    m_firstch.setElementAt(DTM.NULL,attrIndex);                    // If the xml: prefix is explicitly declared                    // we don't need to synthesize one.		    //		    // NOTE that XML Namespaces were not originally		    // defined as being namespace-aware (grrr), and		    // while the W3C is planning to fix this it's		    // safer for now to test the QName and trust the		    // parsers to prevent anyone from redefining the		    // reserved xmlns: prefix                    if(!m_processedFirstElement                       && "xmlns:xml".equals(attrs.item(i).getNodeName()))                      m_processedFirstElement=true;                   }                // Terminate list of attrs, and make sure they aren't                // considered children of the element              } // if attrs exist            if(!m_processedFirstElement)            {              // The DOM might not have an explicit declaration for the              // implicit "xml:" prefix, but the XPath data model              // requires that this appear as a Namespace Node so we              // have to synthesize one. You can think of this as              // being a default attribute defined by the XML              // Namespaces spec rather than by the DTD.              attrIndex=addNode(new DOM2DTMdefaultNamespaceDeclarationNode(																	(Element)next,"xml",NAMESPACE_DECL_NS,																	makeNodeHandle(((attrIndex==NULL)?nextindex:attrIndex)+1)																	),                                nextindex,attrIndex,NULL);                    m_firstch.setElementAt(DTM.NULL,attrIndex);              m_processedFirstElement=true;            }            if(attrIndex!=NULL)              m_nextsib.setElementAt(DTM.NULL,attrIndex);          } //if(ELEMENT_NODE)      } // (if !suppressNode)    // Text postprocessing: Act on values stored above    if(TEXT_NODE == nexttype || CDATA_SECTION_NODE == nexttype)      {        // %TBD% If nexttype was forced to TEXT, patch the DTM node                        next=lastTextNode;      // Advance the DOM cursor over contiguous text      }            // Remember where we left off.    m_pos=next;    return true;  }    /**   * Return an DOM node for the given node.   *   * @param nodeHandle The node ID.   *   * @return A node representation of the DTM node.   */  public Node getNode(int nodeHandle)  {    int identity = makeNodeIdentity(nodeHandle);    return (Node) m_nodes.elementAt(identity);  }  /**   * Get a Node from an identity index.   *   * NEEDSDOC @param nodeIdentity   *   * NEEDSDOC ($objectName$) @return   */  protected Node lookupNode(int nodeIdentity)  {    return (Node) m_nodes.elementAt(nodeIdentity);  }  /**   * Get the next node identity value in the list, and call the iterator   * if it hasn't been added yet.   *   * @param identity The node identity (index).   * @return identity+1, or DTM.NULL.   */  protected int getNextNodeIdentity(int identity)  {    identity += 1;    if (identity >= m_nodes.size())    {      if (!nextNode())        identity = DTM.NULL;    }    return identity;  }  /**   * Get the handle from a Node.   * <p>%OPT% This will be pretty slow.</p>   *   * <p>%OPT% An XPath-like search (walk up DOM to root, tracking path;   * walk down DTM reconstructing path) might be considerably faster   * on later nodes in large documents. That might also imply improving   * this call to handle nodes which would be in this DTM but   * have not yet been built, which might or might not be a Good Thing.</p>   *    * %REVIEW% This relies on being able to test node-identity via   * object-identity. DTM2DOM proxying is a great example of a case where   * that doesn't work. DOM Level 3 will provide the isSameNode() method   * to fix that, but until then this is going to be flaky.   *   * @param node A node, which may be null.   *   * @return The node handle or <code>DTM.NULL</code>.   */  private int getHandleFromNode(Node node)  {    if (null != node)    {      int len = m_nodes.size();              boolean isMore;      int i = 0;      do      {                  for (; i < len; i++)        {          if (m_nodes.elementAt(i) == node)            return makeNodeHandle(i);        }        isMore = nextNode();          len = m_nodes.size();                  }       while(isMore || i < len);    }        return DTM.NULL;  }  /** Get the handle from a Node. This is a more robust version of   * getHandleFromNode, intended to be usable by the public.   *   * <p>%OPT% This will be pretty slow.</p>   *    * %REVIEW% This relies on being able to test node-identity via   * object-identity. DTM2DOM proxying is a great example of a case where   * that doesn't work. DOM Level 3 will provide the isSameNode() method   * to fix that, but until then this is going to be flaky.   *   * @param node A node, which may be null.   *   * @return The node handle or <code>DTM.NULL</code>.  */  public int getHandleOfNode(Node node)  {    if (null != node)    {      // Is Node actually within the same document? If not, don't search!      // This would be easier if m_root was always the Document node, but      // we decided to allow wrapping a DTM around a subtree.      if((m_root==node) ||         (m_root.getNodeType()==DOCUMENT_NODE &&          m_root==node.getOwnerDocument()) ||         (m_root.getNodeType()!=DOCUMENT_NODE &&          m_root.getOwnerDocument()==node.getOwnerDocument())         )        {          // If node _is_ in m_root's tree, find its handle          //          // %OPT% This check may be improved significantly when DOM          // Level 3 nodeKey and relative-order tests become          // available!          for(Node cursor=node;              cursor!=null;              cursor=                (cursor.getNodeType()!=ATTRIBUTE_NODE)                ? cursor.getParentNode()                : ((org.w3c.dom.Attr)cursor).getOwnerElement())            {              if(cursor==m_root)                // We know this node; find its handle.                return getHandleFromNode(node);             } // for ancestors of node        } // if node and m_root in same Document    } // if node!=null    return DTM.NULL;  }  /**   * Retrieves an attribute node by by qualified name and namespace URI.   *   * @param nodeHandle int Handle of the node upon which to look up this attribute..   * @param namespaceURI The namespace URI of the attribute to   *   retrieve, or null.   * @param name The local name of the attribute to   *   retrieve.   * @return The attribute node handle with the specified name (   *   <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such   *   attribute.   */  public int getAttributeNode(int nodeHandle, String namespaceURI,                              String name)  {    // %OPT% This is probably slower than it needs to be.    if (null == namespaceURI)      namespaceURI = "";    int type = getNodeType(nodeHandle);    if (DTM.ELEMENT_NODE == type)    {      // Assume that attributes immediately follow the element.      int identity = makeNodeIdentity(nodeHandle);      while (DTM.NULL != (identity = getNextNodeIdentity(identity)))      {        // Assume this can not be null.        type = _type(identity);				// %REVIEW%				// Should namespace nodes be retrievable DOM-style as attrs?				// If not we need a separate function... which may be desirable				// architecturally, but which is ugly from a code point of view.				// (If we REALLY insist on it, this code should become a subroutine				// of both -- retrieve the node, then test if the type matches				// what you're looking for.)        if (type == DTM.ATTRIBUTE_NODE || type==DTM.NAMESPACE_NODE)        {          Node node = lookupNode(identity);          String nodeuri = node.getNamespaceURI();          if (null == nodeuri)            nodeuri = "";          String nodelocalname = node.getLocalName();          if (nodeuri.equals(namespaceURI) && name.equals(nodelocalname))            return makeNodeHandle(identity);        }				        else // if (DTM.NAMESPACE_NODE != type)        {          break;        }      }    }    return DTM.NULL;  }  /**   * Get the string-value of a node as a String object   * (see http://www.w3.org/TR/xpath#data-model   * for the definition of a node's string-value).   *   * @param nodeHandle The node ID.   *   * @return A string object that represents the string-value of the given node.   */  public XMLString getStringValue(int nodeHandle)  {    int type = getNodeType(nodeHandle);    Node node = getNode(nodeHandle);    // %TBD% If an element only has one text node, we should just use it     // directly.    if(DTM.ELEMENT_NODE == type || DTM.DOCUMENT_NODE == type     || DTM.DOCUMENT_FRAGMENT_NODE == type)    {      FastStringBuffer buf = StringBufferPool.get();      String s;        try      {        getNodeData(node, buf);          s = (buf.length() > 0) ? buf.toString() : "";      }      finally      {        StringBufferPool.free(buf);      }        return m_xstrf.newstr( s );    }    else if(TEXT_NODE == type || CDATA_SECTION_NODE == type)    {      // If this is a DTM text node, it may be made of multiple DOM text      // nodes -- including navigating into Entity References. DOM2DTM      // records the first node in the sequence and requires that we      // pick up the others when we retrieve the DTM node's value.      //      // %REVIEW% DOM Level 3 is expected to add a "whole text"      // retrieval method which performs this function for us.      FastStringBuffer buf = StringBufferPool.get();      while(node!=null)      {        buf.append(node.getNodeValue());        node=logicalNextDOMTextNode(node);      }      String s=(buf.length() > 0) ? buf.toString() : "";      StringBufferPool.free(buf);      return m_xstrf.newstr( s );    }    else      return m_xstrf.newstr( node.getNodeValue() );  }    /**   * Determine if the string-value of a node is whitespace   *   * @param nodeHandle The node Handle.   *   * @return Return true if the given node is whitespace.   */  public boolean isWhitespace(int nodeHandle)  {  	int type = getNodeType(nodeHandle);    Node node = getNode(nodeHandle);  	if(TEXT_NODE == type || CDATA_SECTION_NODE == type)    {      // If this is a DTM text node, it may be made of multiple DOM text      // nodes -- including navigating into Entity References. DOM2DTM      // records the first node in the sequence and requires that we      // pick up the others when we retrieve the DTM node's value.      //      // %REVIEW% DOM Level 3 is expected to add a "whole text"      // retrieval method which performs this function for us.      FastStringBuffer buf = StringBufferPool.get();      while(node!=null)      {        buf.append(node.getNodeValue());        node=logicalNextDOMTextNode(node);      }     boolean b = buf.isWhitespace(0, buf.length());      StringBufferPool.free(buf);     return b;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?