代码之家  ›  专栏  ›  技术社区  ›  freelantzer

使用XPath函数number()和string()时出现HtmlUnit错误

  •  0
  • freelantzer  · 技术社区  · 12 年前

    假设在一个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 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 回复  |  直到 12 年前
        1
  •  1
  •   Mosty Mostacho    12 年前

    正如Martin所说,这是XPath 2.0的一个特性。HtmlUnit当前不支持XPath 2.0。这意味着您不能使用该表达式。

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

    关于为什么不支持XPath2.0的更多细节:实际上,HtmlUnit不支持XPPath2.0。只是XPath在 org.apache.xpath.* 并且它目前不支持2.0。如果添加了对较新XPath版本的支持,那么您将能够在 getByXPath getFirstByXPath 方法。

        2
  •  0
  •   Martin Honnen    12 年前

    表达式 //a[@class='someclass']/number() 在XPath2.0中是合法的,但在XPath1.0中是不合法的,所以如果您想使用这种语法,您需要确保您的Java应用程序插入像Saxon 9这样的XPath2.0引擎。但我怀疑你正在使用的API(比如 getByXPath )在设计时考虑到了XPath2.0,并允许您返回例如值序列。JAXP允许您插入Saxon而不是Xalan,但它的API仍然不允许您返回基元值序列。

    通常,您需要更改的不仅仅是XPath引擎。