Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access attributes using Nokogiri

I have a simple task of accessing the values of some attributes. This is a simple script that uses Nokogiri::XML::Builder to create a simple XML doc.

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"] 

The results are:

<?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 

The XML that is generated looks fine. However, my attempts to access attributes cause an error to be generated:

Document already has a root node 

I don't understand why puts would cause this error.

like image 767
Liz Avatar asked May 25 '10 00:05

Liz


People also ask

How does Nokogiri work?

Nokogiri makes an attempt to determine whether a CSS or XPath selector is being passed in. It's possible to create a selector that fools at or search so occasionally it will misunderstand, which is why we have the more specific versions of the methods.

What does Rails use Nokogiri for?

One of the best gems for Ruby on Rails is Nokogiri which is a library to deal with XML and HTML documents. The most common use for a parser like Nokogiri is to extract data from structured documents.


2 Answers

Using Nokogiri::XML::Reader works for your example, but probably isn't the full answer you are looking for (Note that there is no attributes method for Builder).

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

Note that if you issued reader.read again and then tried reader.attribute("messageId") the result will be nil since the current node will not have this attribute.

What you probably want to do is use Nokogiri::XML::Document if you want to search an XML document by attribute.

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  
like image 196
atomicules Avatar answered Sep 23 '22 11:09

atomicules


Here is a slightly more succinct way to access attributes using Nokogiri (assuming you already have your xml stored in a variable called xml, as covered by @atomicules' answer):

xml.xpath("//Placement").attr("messageId") 
like image 42
ben.snape Avatar answered Sep 19 '22 11:09

ben.snape