XPath和否定搜索

时间:2013-05-07 06:58:50

标签: ruby xpath nokogiri

我在xmlns root中有以下代码示例:

<ol class="stan">
    <li>Item one.</li>
    <li>
        <p>Paragraph one.</p>
        <p>Paragraph two.</p>
    </li>
    <li>
        <pre>Preformated one.</pre>
        <p>Paragraph one.</p>
    </li>
</ol>

我想对<li>中的第一项执行不同的操作,具体取决于它所在的标记类型,或者没有标记,即样本中的第一个<li>


编辑:

我追求这项任务的逻辑证明是错误的。

  1. 如何查询第一个列表项中没有后代的<li>
  2. 我试过否定:

    @doc.xpath("//xmlns:ol[@class='stan']//xmlns:li/xmlns:*[1][not(p|pre)]")
    

    这让我与我想要的完全相反。

    我认为我的表达更加复杂,因为我找不到合适的解决方案。


    更新:

    Navin Rawat在评论中回答了这个问题。正确的代码是:

    @doc.xpath("//xmlns:ol[@class='stan']/xmlns:li[not(xmlns:*)]")
    

    CORRECTION:

    正确的问题涉及XPath搜索和Nokogiri方法。

    鉴于上述xhtml代码,如何使用xpath搜索第一个后代?如何在条件语句中使用xpath,例如:

    @doc.xpath("//xmlns:ol[@class='stan']/xmlns:li").each do |e|
        if e.xpath("e has no descendants")
            perform task
        elsif e.xpath("e first descendant is <p>")
            perform second task
        elsif e.xpath("e first descendant is <pre>")
            perform third task
        end
    end
    

    我不是要求完整的代码。只是上面Nokogiri代码中括号中的部分。

1 个答案:

答案 0 :(得分:1)

Pure XPath回答......

如果您有以下XML:

<ol class="stan">
    <li>Item one.</li>
    <li>
        <p>Paragraph one.</p>
        <p>Paragraph two.</p>
    </li>
    <li>
        <pre>Preformated one.</pre>
        <p>Paragraph one.</p>
    </li>
</ol>

如果要选择第一个列表项中没有子元素的<li>,请使用:

//ol/li[count(*)=0]

如果您遇到名称空间问题,请提供整个XML(使用根元素和名称空间声明),以便我们可以帮助您处理它。

我们讨论后编辑,这是您最终测试的代码:):

@doc.xpath("//xmlns:ol[@class='footnotes']/xmlns:li").each do |e|
  if e.xpath("count(*)=0")
    puts "No children"
  elsif e.xpath("count(*[1]/self::xmlns:p)=1")
    puts "First child is <p>"
  elsif e.xpath("count(*[1]/self::xmlns:pre)=1")
    puts "First child is <pre>"
  end
end