2012-03-12 48 views
2

我想解析由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 

所以,我在寻找之一:

  1. 一个方法,使这项工作查询,或
  2. 方式以编程方式剥离名称空间声明或
  3. 解释正确的a pproach,假设这两个都是错误的。

更新:基于Lev Levitsky's answerJaxen 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。

+0

这是XPath的工作原理与命名空间的方式,它不依赖于Jaxen的:如果你想匹配与命名空间的东西,你必须在XPath – MiMo 2012-03-13 01:21:33

+0

使用一个明确的前缀是的,在进一步的阅读中我看到了。所以,好吧,Jaxen没有责备,但它似乎仍然有点疯狂。或者,充其量是迂腐的,主要是为了在不切实际的用例中达到最大的正确性。 – 2012-03-14 23:17:54

回答

1

您应接受什么直接指定命名空间像

Nodes divs = document.query("//{http://www.w3.org/1999/xhtml}div"); 

或使用映射到相应的命名空间前缀(我猜这就是NamespaceContext是,但是没有前缀在查询)。

不幸的是,我不知道它是如何在Java中实现的,但是如果有帮助的话,我可以提供一个Python示例。

2

你可以写:

Nodes divs = document.query("//*[local-name()='div' and namespace-uri()='http://www.w3.org/1999/xhtml']"); 
相关问题