使用XPath从具有不必要的命名空间的文档中提取XOM元素
问题描述:
我想解析由XOM的外部系统返回的一些HTML。该HTML如下:(其实它显著理出头绪,但它有这个DOCTYPE声明,这些名字空间和语言的声明,以上展品HTML同样的问题,因为真正的HTML)使用XPath从具有不必要的命名空间的文档中提取XOM元素
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<body>
<div>
Help I am trapped in a fortune cookie factory
</div>
</body>
</html>
我想要做的是提取<div>
的内容,但命名空间声明似乎令XPath变得令人困惑。如果我带出空间声明(用手,从文件),下面的代码查找<div>
,没问题:
Document document = ...
Nodes divs = document.query("//div");
但与命名空间,返回Nodes
的大小为0。
好的,如果我以编程方式剥离命名空间,怎么样?
Element rootElement = document.getRootElement();
rootElement.removeNamespaceDeclaration(rootElement.getNamespacePrefix());
...看起来应该可以工作,但什么都不做。从javadoc:
此方法仅删除与
addNamespaceDeclaration.
好增加额外的命名空间,我想,我会提供命名空间查询:
XPathContext context =
XPathContext.makeNamespaceContext(document.getRootElement());
Nodes divs = document.query("//div", context);
大小仍为零。
如何手动构建名称空间上下文?
XPathContext context = context = new XPathContext(
rootElement.getNamespacePrefix(), rootElement.getNamespaceURI());
Nodes divs = document.query("//div", context);
的XPathContext
构造吹了:
nu.xom.NamespaceConflictException:
XPath expressions do not use the default namespace
所以,我在寻找之一:
- 一个方法,使这项工作查询,或
- 方式以编程方式剥离名称空间声明或
- 解释正确的a pproach,假设这两个都是错误的。
更新:基于上Lev Levitsky's answer和Jaxen FAQ我想出了下面的技巧:
XPathContext context = new XPathContext(
"foo",
document.getRootElement().getNamespaceURI());
Nodes divs = document.query("//foo:div");
这仍似乎有点疯狂的给我,但我想它的方式Jaxen的要你做事。
更新#2:正如下面和all over the Internet指出,这不是Jaxen的的错;它只是XPath的XPath。
所以,虽然这个黑客的作品,我仍然喜欢一种方式来剥离命名空间声明。最好不要XSLT。
答
您应接受什么直接指定命名空间像
Nodes divs = document.query("//{http://www.w3.org/1999/xhtml}div");
或使用映射到相应的命名空间前缀(我猜这就是NamespaceContext
是,但是没有前缀在查询)。
不幸的是,我不知道它是如何在Java中实现的,但是如果有帮助的话,我可以提供一个Python示例。
答
你可以写:
Nodes divs = document.query("//*[local-name()='div' and namespace-uri()='http://www.w3.org/1999/xhtml']");
这是XPath的工作原理与命名空间的方式,它不依赖于Jaxen的:如果你想匹配与命名空间的东西,你必须在XPath – MiMo 2012-03-13 01:21:33
使用一个明确的前缀是的,在进一步的阅读中我看到了。所以,好吧,Jaxen没有责备,但它似乎仍然有点疯狂。或者,充其量是迂腐的,主要是为了在不切实际的用例中达到最大的正确性。 – 2012-03-14 23:17:54