domhelper.java

来自「JAVA 所有包」· Java 代码 · 共 1,333 行 · 第 1/3 页

JAVA
1,333
字号
            break;          }          found2 = true;        }        child = child.getNextSibling();      }    }    return isNodeAfterSibling;  }  // end isNodeAfterSibling(Node parent, Node child1, Node child2)  //==========================================================  // SECTION: Namespace resolution  //==========================================================  /**   * Get the depth level of this node in the tree (equals 1 for   * a parentless node).   *   * @param n Node to be examined.   * @return the number of ancestors, plus one   * @xsl.usage internal   */  public short getLevel(Node n)  {    short level = 1;    while (null != (n = getParentOfNode(n)))    {      level++;    }    return level;  }  /**   * Given an XML Namespace prefix and a context in which the prefix   * is to be evaluated, return the Namespace Name this prefix was    * bound to. Note that DOM Level 3 is expected to provide a version of   * this which deals with the DOM's "early binding" behavior.   *    * Default handling:   *   * @param prefix String containing namespace prefix to be resolved,    * without the ':' which separates it from the localname when used    * in a Node Name. The empty sting signifies the default namespace   * at this point in the document.   * @param namespaceContext Element which provides context for resolution.   * (We could extend this to work for other nodes by first seeking their   * nearest Element ancestor.)   *   * @return a String containing the Namespace URI which this prefix   * represents in the specified context.   */  public String getNamespaceForPrefix(String prefix, Element namespaceContext)  {    int type;    Node parent = namespaceContext;    String namespace = null;    if (prefix.equals("xml"))    {      namespace = QName.S_XMLNAMESPACEURI; // Hardcoded, per Namespace spec    }        else if(prefix.equals("xmlns"))    {          // Hardcoded in the DOM spec, expected to be adopted by          // Namespace spec. NOTE: Namespace declarations _must_ use          // the xmlns: prefix; other prefixes declared as belonging          // to this namespace will not be recognized and should          // probably be rejected by parsers as erroneous declarations.      namespace = "http://www.w3.org/2000/xmlns/";     }    else    {          // Attribute name for this prefix's declaration          String declname=(prefix=="")                        ? "xmlns"                        : "xmlns:"+prefix;                                                     // Scan until we run out of Elements or have resolved the namespace      while ((null != parent) && (null == namespace)             && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)                 || (type == Node.ENTITY_REFERENCE_NODE)))      {        if (type == Node.ELEMENT_NODE)        {                                                // Look for the appropriate Namespace Declaration attribute,                        // either "xmlns:prefix" or (if prefix is "") "xmlns".                        // TODO: This does not handle "implicit declarations"                        // which may be created when the DOM is edited. DOM Level                        // 3 will define how those should be interpreted. But                        // this issue won't arise in freshly-parsed DOMs.                                        // NOTE: declname is set earlier, outside the loop.                        Attr attr=((Element)parent).getAttributeNode(declname);                        if(attr!=null)                        {                namespace = attr.getNodeValue();                break;                        }                }        parent = getParentOfNode(parent);      }    }    return namespace;  }  /**   * An experiment for the moment.   */  Hashtable m_NSInfos = new Hashtable();  /** Object to put into the m_NSInfos table that tells that a node has not been    *  processed, but has xmlns namespace decls.  */  protected static final NSInfo m_NSInfoUnProcWithXMLNS = new NSInfo(false,                                                            true);  /** Object to put into the m_NSInfos table that tells that a node has not been    *  processed, but has no xmlns namespace decls.  */  protected static final NSInfo m_NSInfoUnProcWithoutXMLNS = new NSInfo(false,                                                               false);  /** Object to put into the m_NSInfos table that tells that a node has not been    *  processed, and has no xmlns namespace decls, and has no ancestor decls.  */  protected static final NSInfo m_NSInfoUnProcNoAncestorXMLNS =    new NSInfo(false, false, NSInfo.ANCESTORNOXMLNS);  /** Object to put into the m_NSInfos table that tells that a node has been    *  processed, and has xmlns namespace decls.  */  protected static final NSInfo m_NSInfoNullWithXMLNS = new NSInfo(true,                                                          true);  /** Object to put into the m_NSInfos table that tells that a node has been    *  processed, and has no xmlns namespace decls.  */  protected static final NSInfo m_NSInfoNullWithoutXMLNS = new NSInfo(true,                                                             false);  /** Object to put into the m_NSInfos table that tells that a node has been    *  processed, and has no xmlns namespace decls. and has no ancestor decls.  */  protected static final NSInfo m_NSInfoNullNoAncestorXMLNS =    new NSInfo(true, false, NSInfo.ANCESTORNOXMLNS);  /** Vector of node (odd indexes) and NSInfos (even indexes) that tell if    *  the given node is a candidate for ancestor namespace processing.  */  protected Vector m_candidateNoAncestorXMLNS = new Vector();  /**   * Returns the namespace of the given node. Differs from simply getting   * the node's prefix and using getNamespaceForPrefix in that it attempts   * to cache some of the data in NSINFO objects, to avoid repeated lookup.   * TODO: Should we consider moving that logic into getNamespaceForPrefix?   *   * @param n Node to be examined.   *   * @return String containing the Namespace Name (uri) for this node.   * Note that this is undefined for any nodes other than Elements and   * Attributes.   */  public String getNamespaceOfNode(Node n)  {    String namespaceOfPrefix;    boolean hasProcessedNS;    NSInfo nsInfo;    short ntype = n.getNodeType();    if (Node.ATTRIBUTE_NODE != ntype)    {      Object nsObj = m_NSInfos.get(n);  // return value      nsInfo = (nsObj == null) ? null : (NSInfo) nsObj;      hasProcessedNS = (nsInfo == null) ? false : nsInfo.m_hasProcessedNS;    }    else    {      hasProcessedNS = false;      nsInfo = null;    }    if (hasProcessedNS)    {      namespaceOfPrefix = nsInfo.m_namespace;    }    else    {      namespaceOfPrefix = null;      String nodeName = n.getNodeName();      int indexOfNSSep = nodeName.indexOf(':');      String prefix;      if (Node.ATTRIBUTE_NODE == ntype)      {        if (indexOfNSSep > 0)        {          prefix = nodeName.substring(0, indexOfNSSep);        }        else        {          // Attributes don't use the default namespace, so if           // there isn't a prefix, we're done.          return namespaceOfPrefix;        }      }      else      {        prefix = (indexOfNSSep >= 0)                 ? nodeName.substring(0, indexOfNSSep) : "";      }      boolean ancestorsHaveXMLNS = false;      boolean nHasXMLNS = false;      if (prefix.equals("xml"))      {        namespaceOfPrefix = QName.S_XMLNAMESPACEURI;      }      else      {        int parentType;        Node parent = n;        while ((null != parent) && (null == namespaceOfPrefix))        {          if ((null != nsInfo)                  && (nsInfo.m_ancestorHasXMLNSAttrs                      == NSInfo.ANCESTORNOXMLNS))          {            break;          }          parentType = parent.getNodeType();          if ((null == nsInfo) || nsInfo.m_hasXMLNSAttrs)          {            boolean elementHasXMLNS = false;            if (parentType == Node.ELEMENT_NODE)            {              NamedNodeMap nnm = parent.getAttributes();              for (int i = 0; i < nnm.getLength(); i++)              {                Node attr = nnm.item(i);                String aname = attr.getNodeName();                if (aname.charAt(0) == 'x')                {                  boolean isPrefix = aname.startsWith("xmlns:");                  if (aname.equals("xmlns") || isPrefix)                  {                    if (n == parent)                      nHasXMLNS = true;                    elementHasXMLNS = true;                    ancestorsHaveXMLNS = true;                    String p = isPrefix ? aname.substring(6) : "";                    if (p.equals(prefix))                    {                      namespaceOfPrefix = attr.getNodeValue();                      break;                    }                  }                }              }            }            if ((Node.ATTRIBUTE_NODE != parentType) && (null == nsInfo)                    && (n != parent))            {              nsInfo = elementHasXMLNS                       ? m_NSInfoUnProcWithXMLNS : m_NSInfoUnProcWithoutXMLNS;              m_NSInfos.put(parent, nsInfo);            }          }          if (Node.ATTRIBUTE_NODE == parentType)          {            parent = getParentOfNode(parent);          }          else          {            m_candidateNoAncestorXMLNS.addElement(parent);            m_candidateNoAncestorXMLNS.addElement(nsInfo);            parent = parent.getParentNode();          }          if (null != parent)          {            Object nsObj = m_NSInfos.get(parent);  // return value            nsInfo = (nsObj == null) ? null : (NSInfo) nsObj;          }        }        int nCandidates = m_candidateNoAncestorXMLNS.size();        if (nCandidates > 0)        {          if ((false == ancestorsHaveXMLNS) && (null == parent))          {            for (int i = 0; i < nCandidates; i += 2)            {              Object candidateInfo = m_candidateNoAncestorXMLNS.elementAt(i                                       + 1);              if (candidateInfo == m_NSInfoUnProcWithoutXMLNS)              {                m_NSInfos.put(m_candidateNoAncestorXMLNS.elementAt(i),                              m_NSInfoUnProcNoAncestorXMLNS);              }              else if (candidateInfo == m_NSInfoNullWithoutXMLNS)              {                m_NSInfos.put(m_candidateNoAncestorXMLNS.elementAt(i),                              m_NSInfoNullNoAncestorXMLNS);              }            }          }          m_candidateNoAncestorXMLNS.removeAllElements();        }      }      if (Node.ATTRIBUTE_NODE != ntype)      {        if (null == namespaceOfPrefix)        {          if (ancestorsHaveXMLNS)          {            if (nHasXMLNS)              m_NSInfos.put(n, m_NSInfoNullWithXMLNS);            else              m_NSInfos.put(n, m_NSInfoNullWithoutXMLNS);          }          else          {            m_NSInfos.put(n, m_NSInfoNullNoAncestorXMLNS);          }        }        else        {          m_NSInfos.put(n, new NSInfo(namespaceOfPrefix, nHasXMLNS));        }      }    }    return namespaceOfPrefix;  }  /**   * Returns the local name of the given node. If the node's name begins   * with a namespace prefix, this is the part after the colon; otherwise   * it's the full node name.   *   * @param n the node to be examined.   *   * @return String containing the Local Name   */  public String getLocalNameOfNode(Node n)  {    String qname = n.getNodeName();    int index = qname.indexOf(':');    return (index < 0) ? qname : qname.substring(index + 1);  }  /**   * Returns the element name with the namespace prefix (if any) replaced   * by the Namespace URI it was bound to. This is not a standard    * representation of a node name, but it allows convenient    * single-string comparison of the "universal" names of two nodes.   *   * @param elem Element to be examined.   *   * @return String in the form "namespaceURI:localname" if the node   * belongs to a namespace, or simply "localname" if it doesn't.   * @see #getExpandedAttributeName   */  public String getExpandedElementName(Element elem)  {    String namespace = getNamespaceOfNode(elem);    return (null != namespace)           ? namespace + ":" + getLocalNameOfNode(elem)           : getLocalNameOfNode(elem);  }  /**   * Returns the attribute name with the namespace prefix (if any) replaced   * by the Namespace URI it was bound to. This is not a standard    * representation of a node name, but it allows convenient    * single-string comparison of the "universal" names of two nodes.   *   * @param attr Attr to be examined   *   * @return String in the form "namespaceURI:localname" if the node   * belongs to a namespace, or simply "localname" if it doesn't.   * @see #getExpandedElementName   */  public String getExpandedAttributeName(Attr attr)  {    String namespace = getNamespaceOfNode(attr);    return (null != namespace)           ? namespace + ":" + getLocalNameOfNode(attr)           : getLocalNameOfNode(attr);  }  //==========================================================  // SECTION: DOM Helper Functions  //==========================================================  /**   * Tell if the node is ignorable whitespace. Note that this can   * be determined only in the context of a DTD or other Schema,   * and that DOM Level 2 has nostandardized DOM API which can   * return that information.   * @deprecated   *   * @param node Node to be examined   *   * @return CURRENTLY HARDCODED TO FALSE, but should return true if   * and only if the node is of type Text, contains only whitespace,   * and does not appear as part of the #PCDATA content of an element.   * (Note that determining this last may require allowing for    * Entity References.)   */

⌨️ 快捷键说明

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