加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 手动创建所有Document节点的NodeList

发布时间:2020-12-15 02:27:13 所属栏目:Java 来源:网络整理
导读:我当前手动生成所有Document节点的NodeList(按文档顺序).获取此NodeList的XPath表达式是 //. | //@* | //namespace::* 我第一次尝试手动遍历DOM并收集节点(NodeSet是一个委托给List的原始NodeList实现): private static void walkRecursive(Node cur,NodeSe
我当前手动生成所有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声明:

The prefix xml is by definition bound to the namespace name 07001. It MAY,but need not,be declared,and MUST NOT be undeclared or bound to any other namespace name. Other prefixes MUST NOT be bound to this namespace name,and it MUST NOT be declared as the default namespace.

我对么? (至少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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读