Nokogiri 相当于 jQuery Closest() 方法,用于在树中查找第一个匹配的祖先

发布于 2024-12-13 17:38:35 字数 818 浏览 3 评论 0 原文

jQuery 有一个可爱的方法,虽然命名有些错误,称为 closest() ,它会沿着 DOM 树查找匹配的方法元素。例如,如果我有以下 HTML:

<table src="foo">
  <tr>
    <td>Yay</td>
  </tr>
</table>

假设 element 设置为 ,那么我可以算出 src 的值像这样:

element.closest('table')['src']

如果 table 元素或其 src 属性丢失,那么将干净地返回“undefined”。

在 Javascriptland 中习惯了这一点后,我很想在 Rubyland 中找到与 Nokogiri 等效的东西,但我能想到的最接近的是使用 ancestors()

ancestors = element.ancestors('table')
src = ancestors.any? ? first['src'] : nil

需要三元,因为如果调用空数组。更好的想法?

jQuery has a lovely if somewhat misnamed method called closest() that walks up the DOM tree looking for a matching element. For example, if I've got this HTML:

<table src="foo">
  <tr>
    <td>Yay</td>
  </tr>
</table>

Assuming element is set to <td>, then I can figure the value of src like this:

element.closest('table')['src']

And that will cleanly return "undefined" if either of the table element or its src attribute are missing.

Having gotten used to this in Javascriptland, I'd love to find something equivalent for Nokogiri in Rubyland, but the closest I've been able to come up with is this distinctly inelegant hack using ancestors():

ancestors = element.ancestors('table')
src = ancestors.any? ? first['src'] : nil

The ternary is needed because first returns nil if called on an empty array. Better ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

依 靠 2024-12-20 17:38:35

您可以在空数组上调用 first ,问题是它将返回 nil 并且您不能说 nil['src']没有悲伤。你可以这样做:

src = (element.ancestors('table').first || { })['src']

如果你在Rails中,你可以这样使用try

src = element.ancestors('table').first.try(:fetch, 'src')

如果你经常做这种事情,那么将丑陋的地方隐藏在一个方法中:

def closest_attr_from(e, selector, attr)
  a = e.closest(selector)
  a ? a[attr] : nil
end

然后

src = closest_attr_from(element, 'table', 'src')

你也可以将其直接修补到 Nokogiri::XML::Node (但我不推荐它):

class Nokogiri::XML::Node
  def closest(selector)
    ancestors(selector).first
  end
  def closest_attr(selector, attr)
    a = closest(selector)
    a ? a[attr] : nil
  end
end

You can call first on an empty array, the problem is that it will return nil and you can't say nil['src'] without getting sad. You could do this:

src = (element.ancestors('table').first || { })['src']

And if you're in Rails, you could use try thusly:

src = element.ancestors('table').first.try(:fetch, 'src')

If you're doing this sort of thing a lot then hide the ugliness in a method:

def closest_attr_from(e, selector, attr)
  a = e.closest(selector)
  a ? a[attr] : nil
end

and then

src = closest_attr_from(element, 'table', 'src')

You could also patch it right into Nokogiri::XML::Node (but I wouldn't recommend it):

class Nokogiri::XML::Node
  def closest(selector)
    ancestors(selector).first
  end
  def closest_attr(selector, attr)
    a = closest(selector)
    a ? a[attr] : nil
  end
end
江城子 2024-12-20 17:38:35

您还可以使用 xpath 执行此操作:

element.xpath('./ancestor::table[1]')

You can also do this with xpath:

element.xpath('./ancestor::table[1]')
情感失落者 2024-12-20 17:38:35

您想要最接近的表祖先的 src 属性(如果存在)?不是通过 XPath 获取可能存在的元素,然后通过 Ruby 获取属性,而是直接在 XPath 中请求属性:

./ancestor::table[1]/@src

您将得到属性或 nil:

irb(main):001:0> require 'nokogiri'
#=> true

irb(main):002:0> xml = '<r><a/><table src="foo"><tr><td /></tr></table></r>'
#=> "<r><a/><table src=\"foo\"><tr><td /></tr></table></r>"

irb(main):003:0> doc = Nokogiri.XML(xml)
#=> #<Nokogiri::XML::Document:0x195f66c name="document" children=…

irb(main):004:0> doc.at('td').at_xpath( './ancestor::table[1]/@src' )
#=> #<Nokogiri::XML::Attr:0x195f1bc name="src" value="foo">

irb(main):005:0> doc.at('a').at_xpath( './ancestor::table[1]/@src' )
#=> nil

You want the src attribute of the closest table ancestor, if it exists? Instead of getting an element that might exist via XPath and then maybe getting the attribute via Ruby, ask for the attribute directly in XPath:

./ancestor::table[1]/@src

You'll get either the attribute or nil:

irb(main):001:0> require 'nokogiri'
#=> true

irb(main):002:0> xml = '<r><a/><table src="foo"><tr><td /></tr></table></r>'
#=> "<r><a/><table src=\"foo\"><tr><td /></tr></table></r>"

irb(main):003:0> doc = Nokogiri.XML(xml)
#=> #<Nokogiri::XML::Document:0x195f66c name="document" children=…

irb(main):004:0> doc.at('td').at_xpath( './ancestor::table[1]/@src' )
#=> #<Nokogiri::XML::Attr:0x195f1bc name="src" value="foo">

irb(main):005:0> doc.at('a').at_xpath( './ancestor::table[1]/@src' )
#=> nil
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文