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

这篇博客探讨了手动遍历DOM生成NodeList与使用XPath表达式创建NodeList的差异。作者发现XPath生成的NodeList包含了XML命名空间的节点,而手动创建的NodeList没有。文章提出了几个问题:a) xmlns:xml命名空间是否必要;b) 为何XPath会添加这个命名空间节点;c) 是否会影响XML规范化。最后,提供了用于评估XPath表达式的代码示例。
摘要由CSDN通过智能技术生成

我当前手动生成所有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文档测试了这个:

例如,如果我规范化我手动创建的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();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值