domhelper.java

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

JAVA
1,333
字号
  public boolean isIgnorableWhitespace(Text node)  {    boolean isIgnorable = false;  // return value    // TODO: I can probably do something to figure out if this     // space is ignorable from just the information in    // the DOM tree.        // -- You need to be able to distinguish whitespace        // that is #PCDATA from whitespace that isn't.  That requires        // DTD support, which won't be standardized until DOM Level 3.    return isIgnorable;  }  /**   * Get the first unparented node in the ancestor chain.   * @deprecated   *   * @param node Starting node, to specify which chain to chase   *   * @return the topmost ancestor.   */  public Node getRoot(Node node)  {    Node root = null;    while (node != null)    {      root = node;      node = getParentOfNode(node);    }    return root;  }  /**   * Get the root node of the document tree, regardless of   * whether or not the node passed in is a document node.   * <p>   * TODO: This doesn't handle DocumentFragments or "orphaned" subtrees   * -- it's currently returning ownerDocument even when the tree is   * not actually part of the main Document tree. We should either   * rewrite the description to say that it finds the Document node,   * or change the code to walk up the ancestor chain.   *   * @param n Node to be examined   *   * @return the Document node. Note that this is not the correct answer   * if n was (or was a child of) a DocumentFragment or an orphaned node,   * as can arise if the DOM has been edited rather than being generated   * by a parser.   */  public Node getRootNode(Node n)  {    int nt = n.getNodeType();    return ( (Node.DOCUMENT_NODE == nt) || (Node.DOCUMENT_FRAGMENT_NODE == nt) )            ? n : n.getOwnerDocument();  }  /**   * Test whether the given node is a namespace decl node. In DOM Level 2   * this can be done in a namespace-aware manner, but in Level 1 DOMs   * it has to be done by testing the node name.   *   * @param n Node to be examined.   *   * @return boolean -- true iff the node is an Attr whose name is    * "xmlns" or has the "xmlns:" prefix.   */  public boolean isNamespaceNode(Node n)  {    if (Node.ATTRIBUTE_NODE == n.getNodeType())    {      String attrName = n.getNodeName();      return (attrName.startsWith("xmlns:") || attrName.equals("xmlns"));    }    return false;  }  /**   * Obtain the XPath-model parent of a DOM node -- ownerElement for Attrs,   * parent for other nodes.    * <p>   * Background: The DOM believes that you must be your Parent's   * Child, and thus Attrs don't have parents. XPath said that Attrs   * do have their owning Element as their parent. This function   * bridges the difference, either by using the DOM Level 2 ownerElement   * function or by using a "silly and expensive function" in Level 1   * DOMs.   * <p>   * (There's some discussion of future DOMs generalizing ownerElement    * into ownerNode and making it work on all types of nodes. This   * still wouldn't help the users of Level 1 or Level 2 DOMs)   * <p>   *   * @param node Node whose XPath parent we want to obtain   *   * @return the parent of the node, or the ownerElement if it's an   * Attr node, or null if the node is an orphan.   *   * @throws RuntimeException if the Document has no root element.   * This can't arise if the Document was created   * via the DOM Level 2 factory methods, but is possible if other   * mechanisms were used to obtain it   */  public static Node getParentOfNode(Node node) throws RuntimeException  {    Node parent;    short nodeType = node.getNodeType();    if (Node.ATTRIBUTE_NODE == nodeType)    {      Document doc = node.getOwnerDocument();          /*      TBD:      if(null == doc)      {        throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CHILD_HAS_NO_OWNER_DOCUMENT, null));//"Attribute child does not have an owner document!");      }      */          // Given how expensive the tree walk may be, we should first ask           // whether this DOM can answer the question for us. The additional          // test does slow down Level 1 DOMs slightly. DOMHelper2, which          // is currently specialized for Xerces, assumes it can use the          // Level 2 solution. We might want to have an intermediate stage,          // which would assume DOM Level 2 but not assume Xerces.          //          // (Shouldn't have to check whether impl is null in a compliant DOM,          // but let's be paranoid for a moment...)          DOMImplementation impl=doc.getImplementation();          if(impl!=null && impl.hasFeature("Core","2.0"))          {                  parent=((Attr)node).getOwnerElement();                  return parent;          }          // DOM Level 1 solution, as fallback. Hugely expensive.       Element rootElem = doc.getDocumentElement();      if (null == rootElem)      {        throw new RuntimeException(          XMLMessages.createXMLMessage(            XMLErrorResources.ER_CHILD_HAS_NO_OWNER_DOCUMENT_ELEMENT,            null));  //"Attribute child does not have an owner document element!");      }      parent = locateAttrParent(rootElem, node);        }    else    {      parent = node.getParentNode();      // if((Node.DOCUMENT_NODE != nodeType) && (null == parent))      // {      //   throw new RuntimeException("Child does not have parent!");      // }    }    return parent;  }  /**   * Given an ID, return the element. This can work only if the document   * is interpreted in the context of a DTD or Schema, since otherwise   * we don't know which attributes are or aren't IDs.   * <p>   * Note that DOM Level 1 had no ability to retrieve this information.   * DOM Level 2 introduced it but does not promise that it will be   * supported in all DOMs; those which can't support it will always   * return null.   * <p>   * TODO: getElementByID is currently unimplemented. Support DOM Level 2?   *   * @param id The unique identifier to be searched for.   * @param doc The document to search within.   * @return CURRENTLY HARDCODED TO NULL, but it should be:   * The node which has this unique identifier, or null if there   * is no such node or this DOM can't reliably recognize it.   */  public Element getElementByID(String id, Document doc)  {    return null;  }  /**   * The getUnparsedEntityURI function returns the URI of the unparsed   * entity with the specified name in the same document as the context   * node (see [3.3 Unparsed Entities]). It returns the empty string if   * there is no such entity.   * <p>   * XML processors may choose to use the System Identifier (if one   * is provided) to resolve the entity, rather than the URI in the   * Public Identifier. The details are dependent on the processor, and   * we would have to support some form of plug-in resolver to handle   * this properly. Currently, we simply return the System Identifier if   * present, and hope that it a usable URI or that our caller can   * map it to one.   * TODO: Resolve Public Identifiers... or consider changing function name.   * <p>   * If we find a relative URI    * reference, XML expects it to be resolved in terms of the base URI    * of the document. The DOM doesn't do that for us, and it isn't    * entirely clear whether that should be done here; currently that's   * pushed up to a higher levelof our application. (Note that DOM Level    * 1 didn't store the document's base URI.)   * TODO: Consider resolving Relative URIs.   * <p>   * (The DOM's statement that "An XML processor may choose to   * completely expand entities before the structure model is passed   * to the DOM" refers only to parsed entities, not unparsed, and hence   * doesn't affect this function.)   *   * @param name A string containing the Entity Name of the unparsed   * entity.   * @param doc Document node for the document to be searched.   *   * @return String containing the URI of the Unparsed Entity, or an   * empty string if no such entity exists.   */  public String getUnparsedEntityURI(String name, Document doc)  {    String url = "";    DocumentType doctype = doc.getDoctype();    if (null != doctype)    {      NamedNodeMap entities = doctype.getEntities();      if(null == entities)        return url;      Entity entity = (Entity) entities.getNamedItem(name);      if(null == entity)        return url;            String notationName = entity.getNotationName();      if (null != notationName)  // then it's unparsed      {        // The draft says: "The XSLT processor may use the public         // identifier to generate a URI for the entity instead of the URI         // specified in the system identifier. If the XSLT processor does         // not use the public identifier to generate the URI, it must use         // the system identifier; if the system identifier is a relative         // URI, it must be resolved into an absolute URI using the URI of         // the resource containing the entity declaration as the base         // URI [RFC2396]."        // So I'm falling a bit short here.        url = entity.getSystemId();        if (null == url)        {          url = entity.getPublicId();        }        else        {          // This should be resolved to an absolute URL, but that's hard           // to do from here.        }              }    }    return url;  }  /**   * Support for getParentOfNode; walks a DOM tree until it finds   * the Element which owns the Attr. This is hugely expensive, and   * if at all possible you should use the DOM Level 2 Attr.ownerElement()   * method instead.   *  <p>   * The DOM Level 1 developers expected that folks would keep track   * of the last Element they'd seen and could recover the info from   * that source. Obviously that doesn't work very well if the only   * information you've been presented with is the Attr. The DOM Level 2   * getOwnerElement() method fixes that, but only for Level 2 and   * later DOMs.   *   * @param elem Element whose subtree is to be searched for this Attr   * @param attr Attr whose owner is to be located.   *   * @return the first Element whose attribute list includes the provided   * attr. In modern DOMs, this will also be the only such Element. (Early   * DOMs had some hope that Attrs might be sharable, but this idea has   * been abandoned.)   */  private static Node locateAttrParent(Element elem, Node attr)  {    Node parent = null;        // This should only be called for Level 1 DOMs, so we don't have to        // worry about namespace issues. In later levels, it's possible        // for a DOM to have two Attrs with the same NodeName but        // different namespaces, and we'd need to get getAttributeNodeNS...        // but later levels also have Attr.getOwnerElement.        Attr check=elem.getAttributeNode(attr.getNodeName());        if(check==attr)                parent = elem;    if (null == parent)    {      for (Node node = elem.getFirstChild(); null != node;              node = node.getNextSibling())      {        if (Node.ELEMENT_NODE == node.getNodeType())        {          parent = locateAttrParent((Element) node, attr);          if (null != parent)            break;        }      }    }    return parent;  }  /**   * The factory object used for creating nodes   * in the result tree.   */  protected Document m_DOMFactory = null;  /**   * Store the factory object required to create DOM nodes   * in the result tree. In fact, that's just the result tree's   * Document node...   *   * @param domFactory The DOM Document Node within whose context   * the result tree will be built.   */  public void setDOMFactory(Document domFactory)  {    this.m_DOMFactory = domFactory;  }  /**   * Retrieve the factory object required to create DOM nodes   * in the result tree.   *   * @return The result tree's DOM Document Node.   */  public Document getDOMFactory()  {    if (null == this.m_DOMFactory)    {      this.m_DOMFactory = createDocument();    }    return this.m_DOMFactory;  }  /**   * Get the textual contents of the node. See   * getNodeData(Node,FastStringBuffer) for discussion of how   * whitespace nodes are handled.   *   * @param node DOM Node to be examined   * @return String containing a concatenation of all the    * textual content within that node.    * @see #getNodeData(Node,FastStringBuffer)   *    */  public static String getNodeData(Node node)  {    FastStringBuffer buf = StringBufferPool.get();    String s;    try    {      getNodeData(node, buf);      s = (buf.length() > 0) ? buf.toString() : "";    }    finally    {      StringBufferPool.free(buf);    }    return s;  }  /**   * Retrieve the text content of a DOM subtree, appending it into a   * user-supplied FastStringBuffer object. Note that attributes are   * not considered part of the content of an element.   * <p>   * There are open questions regarding whitespace stripping.    * Currently we make no special effort in that regard, since the standard   * DOM doesn't yet provide DTD-based information to distinguish   * whitespace-in-element-context from genuine #PCDATA. Note that we   * should probably also consider xml:space if/when we address this.   * DOM Level 3 may solve the problem for us.   *   * @param node Node whose subtree is to be walked, gathering the   * contents of all Text or CDATASection nodes.   * @param buf FastStringBuffer into which the contents of the text   * nodes are to be concatenated.   */  public static void getNodeData(Node node, FastStringBuffer buf)  {    switch (node.getNodeType())    {    case Node.DOCUMENT_FRAGMENT_NODE :    case Node.DOCUMENT_NODE :    case Node.ELEMENT_NODE :    {      for (Node child = node.getFirstChild(); null != child;              child = child.getNextSibling())      {        getNodeData(child, buf);      }    }    break;    case Node.TEXT_NODE :    case Node.CDATA_SECTION_NODE :      buf.append(node.getNodeValue());      break;    case Node.ATTRIBUTE_NODE :      buf.append(node.getNodeValue());      break;    case Node.PROCESSING_INSTRUCTION_NODE :      // warning(XPATHErrorResources.WG_PARSING_AND_PREPARING);              break;    default :      // ignore      break;    }  }}

⌨️ 快捷键说明

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