2017-04-24 88 views
0

使用Nokogiri :: XML如何基于另一个属性检索属性的值?Nokogiri ::基于另一个XML属性值的XML解析值

XML文件:

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

而且我想检索本地服务类型是2.0

我可以采取的值,而不任何与此条件的价格:

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

而且可能我可以这样做:

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

但是,有没有这样做的优雅和干净的方式?

回答

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选择,以查找包含相同文本节点"LOCAL",并返回包含文本,这是<ServiceType>节点的节点的节点< RateReplyDetails>

service_type.next_element.text # => "2.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" 

我已测试它,它的工作。

+0

在选择器中使用CSS'contains'要小心,因为它是子字符串匹配,这意味着它将在字符串中的任何位置匹配“INT”或“LOCAL”,可能会导致错误匹配。 –

+0

这应该也适用于我,因为我的文本在那里非常独特。我选择了第一个回答正确的答案作为答案,但这也应该起作用。谢谢各位 – user664859

+0

@theTinMan感谢您的提醒,其实我知道这个问题,在我粘贴这个答案之前,我尝试了你之前做过的方式,但是失败了,现在我知道现在使用'text'的正确方法。谢谢。 –

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不匹配。

+0

它没有为我工作 - 必须在搜索后去父母 – user664859