java – 手动创建所有Document节点的NodeList
我当前手动生成所有Document节点的NodeList(按文档顺序).获取此NodeList的XPath表达式是
//. | //@* | //namespace::* 我第一次尝试手动遍历DOM并收集节点(NodeSet是一个委托给List的原始NodeList实现): private static void walkRecursive(Node cur,NodeSet nodes) { nodes.add(cur); if (cur.hasAttributes()) { NamedNodeMap attrs = cur.getAttributes(); for (int i=0; i < attrs.getLength(); i++) { Node child = attrs.item(i); walkRecursive(child,nodes); } } int type = cur.getNodeType(); if (type == Node.ELEMENT_NODE || type == Node.DOCUMENT_NODE) { NodeList children = cur.getChildNodes(); if (children == null) return; for (int i=0; i < children.getLength(); i++) { Node child = children.item(i); walkRecursive(child,list); } } } 我将通过调用walkRecursive(doc,nodes)开始递归,其中doc是org.w3c.Document,节点是(但是为空)NodeSet. 我使用这个原始XML文档测试了这个: <?xml version="1.0"?> <myns:root xmlns:myns="http://www.my.ns/#"> <myns:element/> </myns:root> 例如,如果我规范化我手动创建的NodeSet和最初提到的XPath表达式生成的NodeList,并比较两个字节的字节,那么结果是相等的,似乎工作得很好. 但是,如果我遍历两个NodeLists并打印调试信息(typeString只是生成一个字符串表示) for (int i=0; i < nodes.getLength(); i++) { Node child = nodes.item(i); System.out.println("Type: " + typeString(child.getNodeType()) + " Name:" + child.getNodeName() + " Local name: " + child.getLocalName() + " NS: " + child.getNamespaceURI()); } 然后我收到XPath生成的NodeList的输出: Type: DocumentNode Name:#document Local name: null NS: null Type: Element Name:myns:root Local name: root NS: http://www.my.ns/# Type: Attribute Name:xmlns:myns Local name: myns NS: http://www.w3.org/2000/xmlns/ Type: Attribute Name:xmlns:xml Local name: xml NS: http://www.w3.org/2000/xmlns/ Type: Text Name:#text Local name: null NS: null Type: Element Name:myns:element Local name: element NS: http://www.my.ns/# Type: Text Name:#text Local name: null NS: null 这对于手动生成的NodeList: Type: DocumentNode Name:#document Local name: null NS: null Type: Element Name:myns:root Local name: root NS: http://www.my.ns/# Type: Attribute Name:xmlns:myns Local name: myns NS: http://www.w3.org/2000/xmlns/ Type: Text Name:#text Local name: null NS: null Type: Element Name:myns:element Local name: element NS: http://www.my.ns/# Type: Text Name:#text Local name: null NS: null 因此,正如您所看到的,在第一个示例中,NodeList还包含XML命名空间的节点: Type: Attribute Name:xmlns:xml Local name: xml NS: http://www.w3.org/2000/xmlns/ 现在我的问题: a)如果我正确解释xml-names11,那么我不需要xmlns:xml声明:
我对么? (至少c)提示那个方向) b)但是,为什么XPath评估无论如何都要添加它 – 它不应该仅仅包含那里的内容而不是自动添加内容吗? c)这可能会导致XML canonicalization出现问题,尽管它在shouldn’t中 – 在规范化期间应该省略xml命名空间的声明.有没有人知道(Java)实现会出错? 编辑: 这是我用来评估包含’xml’命名空间节点的XPath表达式的代码: DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); dbf.setValidating(false); InputStream in = ...; try { Document doc = dbf.newDocumentBuilder().parse(in); XPathFactory fac = XPathFactory.newInstance(); XPath xp = fac.newXPath(); XPathExpression exp = xp.compile("//. | //@* | //namespace::*"); NodeList nodes = (NodeList)exp.evaluate(doc,XPathConstants.NODESET); } finally { in.close(); } 解决方法
既然你可以写
<myns:root xml:space="preserve" xmlns:myns="http://www.my.ns/#"> <myns:element/> </myns:root> 在没有声明“xml”前缀的情况下,它必须是隐含的.因此,在// namespace:* location步骤中包含此命名空间声明的命名空间节点是正确的 所以, a)你错了,你需要它(好吧,取决于你的代码的目的) b)见上文 c)没有,但我已经看到了其他事情变得混乱的其他名称空间角落案例(例如Problem with conversion of org.dom4j.Document to org.w3c.dom.Document and XML Signature (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |