使用XPath函数number()和string()的HtmlUnit错误

时间:2013-09-08 14:00:50

标签: java xpath htmlunit

让我们说在html页面内有这三个锚点。 使用htmlunit我想得到这些锚点内的数字(数字不是文本)。

<a class="someclass" href="http://someaddress1.com">3.14</a>
<a class="someclass" href="http://someaddress2.com">1.22</a>
<a class="someclass" href="http://someaddress3.com">6.66</a>

作业必须通过以下testXPath方法完成:

public static void testXPath () {

  WebClient webClient = new WebClient();
  webClient.setJavaScriptEnabled(false);
  webClient.setCssEnabled(false);

  try {

        final HtmlPage page = (HtmlPage) webClient.getPage("pageurl");

        String XPath="//a[@class='someclass']/number()";

        List<Object> list = (List<Object>) page.getByXPath(XPath);

        for (Objects : list) {
             System.out.println(s);
        }

  } catch (Exception e) {   
     e.printStackTrace();
  }
}

当我运行时,我得到:

java.lang.RuntimeException: Could not retrieve XPath 
Caused by: javax.xml.transform.TransformerException: Unknown nodetype: number

当我只想获得href值(作为String)时,会发生同样的错误。在这种情况下:

String XPath="//a[@class='someclass']/@href/string()";

但是什么时候,

String XPath="string(//a[@class='someclass']/@href)";

我只得到第一个href值http://someaddress1.com


我知道我可以将这些数字作为字符串,然后将它们解析为Double

List<DomText> list = (List<DomText>) page.getByXPath("//a[@class='someclass']/text()");
for (DomText d : list) {
  System.out.println(Double.parseDouble(list.get(i).toString()));
}

我可以使用.getValue()来获取hrefs

List<DomAttr> list = (List<DomAttr>) page.getByXPath("//a[@class='someclass']/@href");
for (DomAttr d : list) {
  System.out.println(list.get(i).getValue());
}

但事实并非如此。我想使用XPath函数来做到这一点(我猜它更快)。

2 个答案:

答案 0 :(得分:1)

正如Martin所说,这是一个XPath 2.0功能。 HtmlUnit目前不支持XPath 2.0。这意味着您无法使用该表达式。

我建议通过在XPath外部添加解析来解决它。它看起来并不那么糟糕,实际上它是唯一的出路。当然,您可以将其提取到某些方法中以执行字段提取和解析,它看起来会更好。

关于为什么不支持XPath 2.0的更多细节:实际上,HtmlUnit不支持XPath 2.0。只是XPath正在org.apache.xpath.*处理,它目前不支持2.0。如果在那里添加了对较新XPath版本的支持,那么您将能够在getByXPathgetFirstByXPath方法中使用XPath 2.0表达式。

答案 1 :(得分:0)

表达式//a[@class='someclass']/number()在XPath 2.0中是合法的,但在XPath 1.0中不合法,因此如果要使用该语法,则需要确保Java应用程序插入像Saxon 9这样的XPath 2.0引擎。但我怀疑您使用的API(如getByXPath)在设计时考虑了XPath 2.0,并允许您返回值序列。 JAXP允许您插入Saxon而不是Xalan,但它的API确实不允许您返回原始值序列。

通常,您需要更改XPath引擎。