让我们说在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函数来做到这一点(我猜它更快)。
答案 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版本的支持,那么您将能够在getByXPath
和getFirstByXPath
方法中使用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引擎。