gpt4 book ai didi

ruby-on-rails - 如何使用 Nokogiri 过滤数组(搜索、过滤、条件等)

转载 作者:太空宇宙 更新时间:2023-11-03 16:00:07 24 4
gpt4 key购买 nike

我有一个 XML 文档,我需要使用 Nokogiri 对其进行解析,但是我需要过滤掉所有名称与请求不匹配的“角色”节点。

本质上,我想返回一个仅包含名字和姓氏与所需角色匹配的角色的数组。

当前状态:

除了 Controller 中的过滤/搜索行外,我的所有代码都可以正常工作。我查看了 Nokogiri 的 filtersearch 功能,但似乎无法达到预期的结果。

XML 输入

<xml>
<role xsi:type="director">
<firstName>Thomas</firstName>
<lastName>JONES</lastName>
<company>Jones Enterprises</company>
</role>
<role xsi:type="director">
<firstName>Thomas</firstName>
<lastName>TEST</lastName>
<company>Test Factory</company>
</role>
</xml>

Controller

firstname = 'Thomas'
lastname = 'JONES'

@results = doc.css('role').where((doc.css('firstName').text == @firstname) AND (doc.css('lastName').text == @lastname))

查看

<%= @results.each do |t| %>
<%= t.company %>
<% end %>

要求的输出

Jones Enterprises

最佳答案

您可以使用 XPath 让 libXML2 基础为您完成工作:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<xml>
<role xsi:type="director">
<firstName>Thomas</firstName>
<lastName>JONES</lastName>
<company>Jones Enterprises</company>
</role>
<role xsi:type="director">
<firstName>Thomas</firstName>
<lastName>TEST</lastName>
<company>Test Factory</company>
</role>
</xml>
EOT

FIRSTNAME = 'Thomas'
LASTNAME = 'JONES'

roles = doc.search("//role[child::firstName[text()[contains(., 'Thomas')]] and child::lastName[text()[contains(., 'JONES')]]]")
puts roles.to_xml
# >> <role xsi:type="director">
# >> <firstName>Thomas</firstName>
# >> <lastName>JONES</lastName>
# >> <company>Jones Enterprises</company>
# >> </role>

您可以用 CSS 做同样的事情,只是 CSS 不允许我们使用逻辑在同一个 libXML 调用中测试两个子节点的内容。相反,在那个时候,我们必须进行多次调用,让 Ruby 和 Nokogiri 过滤所需的节点,这变得更加困难和 CPU 密集型。像这样的东西有效:

roles_firstnames = doc.search('role firstName:contains("Thomas")').map(&:parent)
roles_lastnames = doc.search('role lastName:contains("JONES")').map(&:parent)
matching_roles = (roles_firstnames & roles_lastnames)
puts matching_roles.map(&:to_xml)
# >> <role xsi:type="director">
# >> <firstName>Thomas</firstName>
# >> <lastName>JONES</lastName>
# >> <company>Jones Enterprises</company>
# >> </role>

注意事项:

  • Nokogiri 让我们可以使用很多 jQuery 提供的 CSS 扩展,比如 :contains .
  • roles_firstnames & roles_lastnames让 Ruby 在数组上使用集合交集。每个数组都包含一个包含名字或姓氏的节点列表。每个条目都是父节点的标识符。 & 简化测试以查看两个数组中的哪些节点是共同的,并且基本上执行 and其次是 uniq对我们来说。

无论采用哪种方式,一旦您拥有 <role>需要的节点,很容易遍历它们并提取子节点 <company>节点的文本:

roles.map{ |n| n.at('company').text }
# => ["Jones Enterprises"]

关于ruby-on-rails - 如何使用 Nokogiri 过滤数组(搜索、过滤、条件等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27220679/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com