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