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 + -
显示快捷键?