Nokogiri和Xpath:查找两个标签之间的所有文本



我不确定这是语法问题还是版本差异,但我似乎无法弄清楚。我想从h2标签到h3标签中获取(非关闭)td内部的数据。下面是HTML的样子:

<td valign="top" width="350">
    <br><h2>NameIWant</h2><br>
    <br>Town<br>
    PhoneNumber<br>
    <a href="mailto:emailIwant@nowhere.com" class="links">emailIwant@nowhere.com</a>
    <br>
    <a href="http://websiteIwant.com" class="links">websiteIwant.com</a>
    <br><br>    
    <br><img src="images/spacer.gif"/><br>
    <h3><b>I want to stop before this!</b></h3>
    Lorem Ipsum Yadda Yadda<br>
    <img src="images/spacer.gif" border="0" width="20" height="11" alt=""/><br>
    <td width="25">
        <img src="images/spacer.gif" border="0" width="20" height="8" alt=""/>
        <td valign="top" width="200"><img src="images/spacer.gif"/>
            <br>
            <br>
            <table cellspacing="0" cellpadding="0" border="0"/>205"&gt;<tr><td>
                <a href="http://dontneedthis.com">
                </a></td></tr><br>
            <table border="0" cellpadding="3" cellspacing="0" width="200">
            ...

<td valign>不关闭,直到页面的底部,我认为这可能是为什么我有问题。

我的Ruby代码如下:

require 'open-uri'
require 'nokogiri'
@doc = Nokogiri::XML(open("http://www.url.com"))
content = @doc.css('//td[valign="top"] [width="350"]')
name = content.xpath('//h2').text
puts name // Returns NameIwant
townNumberLinks = content.search('//following::h2')
puts content // Returns <h2> NameIWant </h2>

正如我所理解的,下面的语法应该"选择当前节点结束标记之后的文档中的所有内容"。如果我尝试使用preceding,如:

townNumberLinks = content.search('//preceding::h3')
// I get: <h3><b>I want to stop before this!</b></h3>

希望我把我要做的说清楚了。谢谢!

这可不是小事。在您选择的节点(td)的上下文中,要获得两个元素之间的所有内容,您需要执行这两个集合的交集:

  1. Set A:在第一个之前的所有节点 h3: //h3[1]/preceding::node()
  2. Set B:所有节点第一个 h2: //h2[1]/following::node()

要执行交集,您可以使用Kaysian方法(以Michael Kay提出的名称命名)。基本公式是:

A[count(.|B) = count(B)]

将其应用于上面定义的集合,其中A = //h3[1]/preceding::node()B = //h2[1]/following::node(),我们有:

//h3[1]/preceding::node()[ count( . | //h2[1]/following::node()) = count(//h2[1]/following::node()) ]

将选择所有元素和文本节点</h2>标记后的第一个<br>开始,到最后一个<br>之后的空白文本节点,就在下一个<h3>标记之前。

您可以轻松地选择仅在h2h3之间的文本节点将表达式中的text()替换为node()。这个命令将返回两个标题之间的所有文本节点(包括空格和换行符):

//h3[1]/preceding::text()[ count( . | //h2[1]/following::text()) = count(//h2[1]/following::text()) ]

查找单元格中第一个<h3>之前的所有元素,然后检索之前没有<h2>标记的所有兄弟元素。用XPath表达式替换//td以准确地检索这个表单元格。

//td/h3[1]/preceding-sibling::*[preceding-sibling::h2]

相关内容

  • 没有找到相关文章

最新更新