Nokogiri :: XML解析值基于另一个XML属性的值

时间:2017-04-24 23:42:10

标签: ruby-on-rails ruby nokogiri

使用Nokogiri :: XML如何根据其他属性检索属性的值?

XML文件:

  <RateReplyDetails>
    <ServiceType>INT</ServiceType>
    <Price>1.0</Price>
  </RateReplyDetails>
  <RateReplyDetails>
    <ServiceType>LOCAL</ServiceType>
    <Price>2.0</Price>
  </RateReplyDetails>

我想检索LOCAL ServiceType的价格是2.0

我可以在没有任何条件的情况下获取该值:

rated_shipment.at('RateReplyDetails/Price').text

也许我可以做类似的事情:

if rated_shipment.at('RateReplyDetails/ServiceType').text == "LOCAL"
  rated_shipment.at('RateReplyDetails/Price').text

但有没有优雅和干净的方式呢?

3 个答案:

答案 0 :(得分:1)

尝试,content是xml内容字符串。

doc = Nokogiri::HTML(content)
doc.at('servicetype:contains("INT")').next_element.content

[16] pry(main)> 
doc.at('servicetype:contains("INT")').next_element.content
=> "1.0"
[17] pry(main)> 
doc.at('servicetype:contains("LOCAL")').next_element.content
=> "2.0"

我测试了它,它正在工作。

答案 1 :(得分:1)

我做的事情如下:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<xml>
 <RateReplyDetails>
    <ServiceType>INT</ServiceType>
    <Price>1.0</Price>
  </RateReplyDetails>
  <RateReplyDetails>
    <ServiceType>LOCAL</ServiceType>
    <Price>2.0</Price>
  </RateReplyDetails>
</xml>
EOT

service_type = doc.at('//RateReplyDetails/*[text() = "LOCAL"]')
service_type.name # => "ServiceType"

'//RateReplyDetails/*[text() = "LOCAL"]'是一个XPath选择器,用于查找包含等于< RateReplyDetails>的文本节点的"LOCAL"节点,并返回包含文本的节点,即<ServiceType>节点

service_type.next_element.text # => "2.0"

一旦我们发现可以轻松查看下一个元素并获取其文字。

答案 2 :(得分:0)

完全在XPath中:

rated_shipment.at('//RateReplyDetails[ServiceType="LOCAL"]/Price/text()').to_s
# => "2.0"

修改

  

它对我不起作用

完整代码作为证据确实有效:

#!/usr/bin/env ruby
require 'nokogiri'
rated_shipment = Nokogiri::XML(DATA)
puts rated_shipment.at('//RateReplyDetails[ServiceType="LOCAL"]/Price/text()').to_s
__END__
<xml>
 <RateReplyDetails>
    <ServiceType>INT</ServiceType>
    <Price>1.0</Price>
  </RateReplyDetails>
  <RateReplyDetails>
    <ServiceType>LOCAL</ServiceType>
    <Price>2.0</Price>
  </RateReplyDetails>
</xml>

(输出2.0。)如果它不起作用,那是因为你的文件内容与你的OP不匹配。