Как получить доступ к атрибутам с помощью Nokogiri
У меня есть простая задача доступа к значениям некоторых атрибутов. Это простой скрипт, который использует Nokogiri::XML::Builder
для создания простого 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"]
Результаты:
<?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
Сгенерированный XML выглядит нормально. Тем не менее, мои попытки получить доступ к атрибутам вызывают ошибку:
Document already has a root node
Я не понимаю, почему puts
вызывают эту ошибку.
Ответы
Ответ 1
Использование Nokogiri:: XML:: Reader работает для вашего примера, но, вероятно, это не полный ответ, который вы ищете (обратите внимание, что существует no attributes
метод для Builder).
reader = Nokogiri::XML::Reader(builder.to_xml)
reader.read #Moves to next node in document
reader.attribute("messageId")
Обратите внимание, что если вы снова выпустили reader.read
, а затем попробовали reader.attribute("messageId")
, результат будет nil
, так как текущий node не будет иметь этот атрибут.
Что вы, вероятно, захотите сделать, это использовать Nokogiri:: XML:: Document, если вы хотите искать XML-документ по атрибуту.
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
Ответ 2
Вот несколько более краткий способ доступа к атрибутам с помощью Nokogiri
(если вы уже имеете свой xml, хранящийся в переменной с именем xml
, как описано в ответе @atomicules):
xml.xpath("//Placement").attr("messageId")