web-dev-qa-db-fra.com

Comment accéder aux attributs à l'aide de Nokogiri

J'ai une tâche simple d'accéder aux valeurs de certains attributs. Ceci est un script simple qui utilise Nokogiri::XML::Builder pour créer un simple document XML.

require 'nokogiri'

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
  xml.Placement(:messageId => "392847-039820-938777", :system => "MOD", :version => "2.0") {
    xml.objects {
        xml.object(:myattribute => "99", :anotherattrib => "333")
        xml.nextobject_ '9387toot'
        xml.Entertainment "Last Man Standing"
    }
  }
end

puts builder.to_xml
puts builder.root.attributes["messageId"]

Les résultats sont:

<?xml version="1.0" encoding="UTF-8"?>
<Placement messageId="392847-039820-938777" version="2.0" system="MOD">
  <objects>
    <object anotherattrib="333" myattribute="99"/>
    <nextobject>9387toot</nextobject>
    <Entertainment>Last Man Standing</Entertainment>
  </objects>
</Placement>
C:/Ruby/lib/Ruby/gems/1.8/gems/nokogiri-1.4.2-x86-mingw32/lib/nokogiri/xml/document.rb:178:in `add_child': Document already has a root node (RuntimeError)
    from C:/Ruby/lib/Ruby/gems/1.8/gems/nokogiri-1.4.2-x86-mingw32/lib/nokogiri/xml/node.rb:455:in `parent='
    from C:/Ruby/lib/Ruby/gems/1.8/gems/nokogiri-1.4.2-x86-mingw32/lib/nokogiri/xml/builder.rb:358:in `insert'
    from C:/Ruby/lib/Ruby/gems/1.8/gems/nokogiri-1.4.2-x86-mingw32/lib/nokogiri/xml/builder.rb:350:in `method_missing'
    from C:/Documents and Settings/etrojan/workspace/Lads/tryXPATH2.rb:15

Le XML généré semble correct. Cependant, mes tentatives d'accès aux attributs provoquent la génération d'une erreur:

Document already has a root node

Je ne comprends pas pourquoi puts provoquerait cette erreur.

53
Liz

L'utilisation de Nokogiri :: XML :: Reader fonctionne pour votre exemple, mais ce n'est probablement pas la réponse complète que vous recherchez (Notez qu'il n'y a pas de méthode attributes pour Builder ).

reader = Nokogiri::XML::Reader(builder.to_xml)
reader.read #Moves to next node in document
reader.attribute("messageId")

Notez que si vous avez de nouveau émis reader.read Puis essayé reader.attribute("messageId") le résultat sera nil car le nœud actuel n'aura pas cet attribut.

Ce que vous voulez probablement faire est d'utiliser Nokogiri :: XML :: Document si vous souhaitez rechercher un document XML par attribut.

doc = Nokogiri::XML(builder.to_xml)
elems = doc.xpath("//*[@messageId]") #get all elements with an attribute of 'messageId'
elems[0].attr('messageId') #gets value of attribute of first elem 
64
atomicules

Voici une façon un peu plus succincte d'accéder aux attributs en utilisant Nokogiri (en supposant que votre xml est déjà stocké dans une variable appelée xml, comme couvert par la réponse de @atomicules):

xml.xpath("//Placement").attr("messageId")
46
ben.snape