2013-05-30 59 views
6

有没有办法在节点中查找特定值,然后返回其所有兄弟值?使用Nokogiri获取节点的兄弟节点

例如,我想找到找到包含ID 5678 id节点,然后获得的电子邮件地址和ID 5678

Nokogiri::XML.parse(File.open('info.xml')) 

相关联的所有图像下面是一个示例XML文件。

<xmlcontainer> 
    <details> 
    <id>1234</id> 
    <email>[email protected]</email> 
    <image>images/1.jpg</image> 
    <image>images/2.jpg</image> 
    <image>images/3.jpg</image> 
    </details> 
    <details> 
    <id>5678</id> 
    <email>[email protected]</email> 
    <image>images/4.jpg</image> 
    <image>images/5.jpg</image> 
    </details> 
    <details> 
    <id>9011</id> 
    <email>[email protected]</email> 
    <image>images/6.jpg</image> 
    <image>images/7.jpg</image> 
    </details> 
</xmlcontainer> 

回答

3
require 'nokogiri' 
doc = Nokogiri::XML.parse(File.open('info.xml')) 
details = doc.css('details').find{|node| node.css('id').text == "5678"} 
email = details.css('email').text # => "[email protected]" 
images = details.css('image').map(&:text) # => ["images/4.jpg", "images/5.jpg"] 

更新:有短,可以说是更好的,方法来抓住你想要的details节点:

details = doc.at('details:has(id[text()="5678"])') 

details = doc.search('id[text()="5678"] ~ *') 

这些都是双方礼貌pguardiario。

+1

您可以通过用'find {}'替换'select {}。first'来加强它,或者您可以更直接地通过'doc.at('details:has(id [text()= “5678”])')' – pguardiario

+0

@pguardiario搜索文档的很多方法!感谢您的提示! –

+2

不客气!在这种情况下,xpath实际上可能会更简单:'doc.at('// id [text()='5678“]/..')' – pguardiario

6

您可以使用~,这是CSS一般兄弟选择:

doc.search('id[text()="5678"] ~ *').map &:text 
#=> ["[email protected]", "images/4.jpg", "images/5.jpg"] 

这很奇怪使用CSS与XML一点点,但它是如此容易得多看看(比XPath的)。

+0

非常好的语法''id [text()=“5678”]〜*''。第一次,我基本上找到了'XPATH'部分,就像'[text()=“5678”]'。你在哪里见过这样的伎俩? :)如果可能请解释搜索表达式。 –

+0

'[text()=“5678”]不是标准的CSS,但nokogiri允许。其余的只是CSS。 '〜*'表示任何兄弟元素 – pguardiario

+0

+1“在xml中使用css有些奇怪,但它比xpath更容易查看(比xpath)。”我同意,我很高兴Nokogiri给了我们这个选择。 CSS通常更具可读性。 –