ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-07-10 01:02:42  阅读:524  来源: 互联网

标签:java dom xml xpath canonicalization


我当前手动生成所有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

标签:java,dom,xml,xpath,canonicalization
来源: https://codeday.me/bug/20190710/1418785.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有