ruby - XPath 查找所有后续 sibling ,直到特定类型的下一个 sibling

标签 ruby xml xpath nokogiri

鉴于此 XML/HTML:

<dl>
  <dt>Label1</dt><dd>Value1</dd>
  <dt>Label2</dt><dd>Value2</dd>
  <dt>Label3</dt><dd>Value3a</dd><dd>Value3b</dd>
  <dt>Label4</dt><dd>Value4</dd>
</dl>

我想找到所有 <dt> ,然后为每个找到以下 <dd> 直到下一个 <dt>

使用 Ruby 的 Nokogiri 我可以这样完成:

dl.xpath('dt').each do |dt|
  ct  = dt.xpath('count(following-sibling::dt)')
  dds = dt.xpath("following-sibling::dd[count(following-sibling::dt)=#{ct}]")
  puts "#{dt.text}: #{dds.map(&:text).join(', ')}"
end
#=> Label1: Value1
#=> Label2: Value2
#=> Label3: Value3a, Value3b
#=> Label4: Value4

但是,正如您所看到的,我在 Ruby 中创建了一个变量,然后使用它编写了一个 XPath。我如何编写一个具有等效功能的 XPath 表达式?

我猜到了:
following-sibling::dd[count(following-sibling::dt)=count(self/following-sibling::dt)]

但显然我不明白 self 在那里意味着什么。

此问题与 XPath : select all following siblings until another sibling 类似,只是“停止”节点没有唯一标识符。

这个问题与 xpath to find all following sibling adjacent nodes up til another type 几乎相同,只是我要求的是 XPath-only 解决方案。

最佳答案

一种可能的解决方案:

dl.xpath('dt').each_with_index do |dt, i|
  dds = dt.xpath("following-sibling::dd[not(../dt[#{i + 2}]) or " +
                     "following-sibling::dt[1]=../dt[#{i + 2}]]")
  puts "#{dt.text}: #{dds.map(&:text).join(', ')}"
end

这依赖于 dt 元素的值比较,并且在重复时会失败。以下(更复杂的)表达式不依赖于唯一的 dt 值:
following-sibling::dd[not(../dt[$n]) or 
    (following-sibling::dt[1] and count(following-sibling::dt[1]|../dt[$n])=1)]

注意: 您使用 self 失败,因为您没有正确地将其用作轴 ( self:: )。此外,self 始终只包含上下文节点,因此它会引用表达式检查的每个 dd,而不是返回原始 dt

关于ruby - XPath 查找所有后续 sibling ,直到特定类型的下一个 sibling ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8492304/

相关文章:

python - 无法使用 scrapy 访问 xpath 属性

ruby-on-rails - 在添加关联 Cocoon 之前修改 Nested_Field

ruby - 我如何以编程方式查询 Vagrant 的配置状态?

ruby-on-rails - Sidekiq 作业应该持续多长时间?

.net - 如何控制复杂对象的反序列化

android - Android 运行时中的水平和垂直 ScrollView

ruby - 在 CLI 程序中自动执行命令

android - ListView 图形布局中的自定义列表行

java - 通过 XPath 获取 HTML 元素的子元素

java - 如果使用 selenium 未找到则跳过表