使用HtmlUnit选择XPath中的默认名称空间

| 我想用HtmlUnit解析Feedburner供稿。 提要是这样的:http://feeds.feedburner.com/alcoanewsreleases 从此提要中,我想读取所有项目节点,因此通常应使用
//item
XPath。不幸的是,在这种情况下不起作用。 常规代码段:
def page = webClient.getPage(\"http://feeds.feedburner.com/alcoanewsreleases\")
def elements = page.getByXPath(\"//item\")
XML提要样本:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<?xml-stylesheet type=\"text/xsl\" media=\"screen\" href=\"/~d/styles/rss1full.xsl\"?>
<?xml-stylesheet type=\"text/css\" media=\"screen\" href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\"?>

<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns=\"http://purl.org/rss/1.0/\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\">

[...SNIP...]

<item rdf:about=\"http://www.alcoa.com/global/en/news/news_detail.asp?newsYear=2011&amp;pageID=20110518006002en\">
    <title>Chris L. Ayers Named President, Alcoa Global Primary Products</title>
    <dc:date>2011-05-18</dc:date
    <link>http://feedproxy.google.com/~r/alcoanewsreleases/~3/PawvdhpJrkc/news_detail.asp</link>
    <description>NEW YORK--(BUSINESS WIRE)--Alcoa (NYSE:AA) announced today that Chris L. Ayers has been named President of Alcoa’s Global Primary Products (GPP) business, effective May 18, 2011. Ayers, previously Chief Operating Officer of GPP, succeeds John Thuestad, who will be handling special projects for the Company. Ayers joined Alcoa in February 2010 as Chief Operating Officer of Alcoa Cast, Forged and Extruded Products, a new position. He was elected a Vice President of Alcoa in April 2010 and Executive</description>
    <feedburner:origLink xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\">http://www.alcoa.com/global/en/news/news_detail.asp?newsYear=2010&amp;pageID=20100104006194en</feedburner:origLink>
</item>

[...SNIP...]

</rdf:RDF>
我怀疑这是名称空间的问题,因为此文档有4个名称空间。命名空间是 (这是默认设置)xmlns = \“ http://purl.org/rss/1.0/ \” xmlns:rdf = \“ http://www.w3.org/1999/02/22-rdf-syntax-ns# \” xmlns:dc = \“ http://purl.org/dc/elements/1.1/ \” xmlns:feedburner = \“ http://rssnamespace.org/feedburner/ext/1.0 \” 我试图与此一起使用Nokogiri(我用于ruby脚本的另一个XML解析器)。 使用Nokogiri,我们可以使用XPath
//xmlns:item
,它可以工作并返回提要中的所有节点。 我已经用HtmlUnit尝试了相同的XPath,但是它不起作用。 所以我想我的问题可以表达为: 如何使用HtmlUnit从默认名称空间中选择一个节点? 有任何想法吗?     
已邀请:
我想从这个提要中阅读所有项目   节点,所以通常是“ 0” XPath   应该可以。不幸   在这种情况下不起作用。 在XPath中,这意味着\“选择所有名称空间中没有本地名称为namespace5 namespace的元素\”。在RSS中,“ 5”个元素必须位于名称空间中。因此,以上内容绝对不能与兼容的XML解析器和XPath引擎一起使用。 令人困惑的是,在XML中,“ 7”的意思是“在默认名称空间中有一个名为item的元素,即文档中此位置范围内的任何默认名称空间;”而在XPath中,“ \ item \”表示没有命名空间的元素。 (或者,您可以说这意味着默认名称空间中的一个元素,但是除非您有办法告诉XPath默认名称空间是什么,否则默认名称空间就没有名称空间。通常(总是?)在XPath 1.0中是无法实现的声明XPath表达式的默认名称空间。) 初学者的另一个困惑是,XPath处理器认为源XML文档中的名称空间前缀映射不重要。解析XML文档时,将建立一个数据结构,该数据结构会记住每个元素(和其他节点)的名称和名称空间。所使用的名称空间前缀(包括默认名称空间的空前缀)仅被视为语法上的便利。下面的更多内容...   有了Nokogiri,我就可以   可以工作的XPath
//xmlns:item
  返回提要中的所有节点。 不管是什么,它都不是XPath。也许它是对它的Nokogiri扩展(一种非常方便的扩展,但其语法确实违反直觉)。   所以我想我可以提出我的问题   如:我如何从中选择一个节点   HtmlUnit的默认名称空间? 让我们用它来表述为:如何使用HtmlUnit选择RSS项目元素?之所以这样说是因为RSS规范(实际上通常是任何符合XML的词汇规范)都不需要其元素位于默认名称空间中。在您收到的样本中,这确实是正确的,但是服务提供商可能会在明天改变这种情况,并且仍然完全符合RSS。明天,服务提供商可以为该名称空间使用\“ rss \”名称空间前缀。或任何其他任意前缀。 RSS确实指定了其元素将位于哪个名称空间:URI为“ 9”的名称空间。 就像是在问:“我如何编写一个函数(使用Javascript,C,Java等),可以告诉我变量
a
的值?\”通常,一个函数不知道变量名是什么用于呼叫者中的内容。它所知道的只是其参数的值。如果您呼叫
sqrt(4)
,您将得到与
a = 4; sqrt(a)
rumpelstiltzkin = 4; sqrt(rumpelstiltzkin)
相同的答案。显然,变量参数的名称对函数调用的结果没有直接影响。它只需要是拥有正确值的变量的名称。如果编译器抱怨是因为您编写了
b = 4; return sqrt(b)
而不是使用ѭ10complain,那么您会认为编译器很疯狂。只要使用有效的标识符,就不应该在意变量名。 同样,在处理RSS时,我们不必关心使用什么名称空间前缀,只要它是标识正确名称空间的前缀即可。它不能是前缀(标识默认名称空间)。 在XPath 2.0中,可以通配名称空间。如果您知道不需要歧义空间,这将非常方便。在这种情况下,您可以选择
//*:item
。但是,我不认为HTMLUnit支持XPath 2.0。同样在XPath 2.0环境(例如XSLT 2.0)中,您可以为XPath表达式指定默认的命名空间,但这在HTMLUnit中无济于事。 因此,您有两种选择: 使用一个忽略名称空间的XPath表达式,例如ѭ17。 要么 健壮的方法:为
http://purl.org/rss/1.0/
注册一个名称空间前缀,并在您的XPath表达式
//rss:item
中使用它。问题就变成了,如何在HTMLUnit中注册名称空间前缀并将其传递给XPath处理器?我快速浏览了一下文档,却没有找到执行此操作的任何工具。 警告:我还要补充一点,以上内容是关于符合标准的XPath处理器的。我不知道HTMLUnit使用什么XPath处理器。有一些XPath处理器忽略了规范,使每个人都感到困惑。 我在这里看到有人对HTMLUnit的默认名称空间中的元素使用了以下语法:
//:item
但出于以下三个原因,我不建议您这样做: 它不是有效的XPath,因此您不能指望它可以与其他程序一起使用。 它仅适用于声明RSS名称空间为默认名称空间的RSS feed。使用名称空间前缀的RSS feed将导致以上操作失败。 它将使您不了解XML命名空间的真正工作原理,并有助于保持那些不充分支持命名空间的工具的现状。 HTMLUnit主要是为HTML设计的,因此可以理解XML的不完整处理。但是声称支持XPath然后不提供声明名称空间前缀的方法是一个错误。 HTMLUnit使用的XPath包似乎是Xalan-J的一部分。该程序包提供了到XPath的名称空间映射的方法,但是我不知道HTMLUnit是否公开了该功能。     
这听起来很熟悉,我可以确定自己过去已经成功地将名称空间和XPath与HtmlUnit一起使用了,但是我当然找不到代码。我怀疑它一定只与HTML页面有关:示例中的ѭ21引用是一个ѭ22,它具有许多特定于名称空间的方法,所有这些方法在使用时都会引发“未实现”异常。 :-( HtmlUnit的当前版本(2.8)已经使用了将近一年,因此可能在此期间已经完成了一些工作来支持XML名称空间。 \“ HtmlUnit Users \”邮件列表将是查找的地方。 同时,与往常一样,有一种解决方法:
final XmlPage page = webClient.getPage(\"http://feeds.feedburner.com/alcoanewsreleases\");

// no good
List elements = page.getByXPath(\"//item\");
System.out.println( elements.size() ) ;

// ugly, but it works
DomElement de = (DomElement)page.getFirstByXPath( \"//rdf:RDF\" );
List<DomNode> items = new ArrayList<DomNode>() ;
for( DomNode dn : de.getChildNodes() )
{
    String name = dn.getLocalName() ;
    if( ( name != null ) && ( name.equals( \"item\" ) ) )
        items.add( dn ) ;
}
System.out.println( \"found \" + items.size() ) ;
哦,Java小子在Scala工作后很痛苦... ;-)     

要回复问题请先登录注册