使用HtmlUnit在XPath中选择默认命名空间

时间:2011-05-24 13:31:30

标签: xpath groovy namespaces xml-namespaces htmlunit

我想用HtmlUnit解析Feedburner Feed。 Feed是这个:http://feeds.feedburner.com/alcoanewsreleases

从这个Feed我想读取所有 item 节点,所以通常//item XPath应该可以解决这个问题。不幸的是,在这种情况下不起作用。

groovy代码段:

def page = webClient.getPage("http://feeds.feedburner.com/alcoanewsreleases")
def elements = page.getByXPath("//item")

XML Feed示例:

<?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 Parser)。 使用Nokogiri,我可以使用XPath //xmlns:item,它可以工作并返回Feed中的所有节点。

我尝试过与HtmlUnit相同的XPath,但它不起作用。

所以我想我可以将我的问题说成: 如何使用HtmlUnit从默认命名空间中选择节点?

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

答案 1 :(得分:0)

这听起来很熟悉,我很确定我过去曾使用HtmlUnit成功使用名称空间和XPath,但当然我找不到代码。我怀疑它一定只用于HTML页面:示例中的page引用是XmlPage,它有许多特定于命名空间的方法,所有这些方法都会抛出“尚未实现”的异常用过的。 : - (

HtmlUnit的当前版本(2.8)已有近一年的历史,因此在支持XML命名空间的同时可能已经完成了一些工作。 "HtmlUnit Users" mailing list将成为查找的地方。

与此同时,一如往常有解决方法:

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工作后很痛苦......; - )