Как получить доступ к атрибутам с помощью Nokogiri - PullRequest
53 голосов
/ 25 мая 2010

У меня есть простая задача доступа к значениям некоторых атрибутов. Это простой скрипт, который использует 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 может вызвать эту ошибку.

Ответы [ 2 ]

64 голосов
/ 26 мая 2010

Использование Nokogiri :: XML :: Reader подходит для вашего примера, но, вероятно, не является полным ответом, который вы ищете (Обратите внимание, что для Builder * нет attributes метода 1005 *).

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

Обратите внимание, что если вы ввели reader.read снова, а затем попытались reader.attribute("messageId"), результатом будет nil, так как текущий узел не будет иметь этого атрибута.

Что вы, вероятно, хотите сделать, это использовать 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 
46 голосов
/ 29 августа 2012

Вот несколько более краткий способ доступа к атрибутам с использованием Nokogiri (при условии, что ваш xml уже хранится в переменной с именем xml, как указано в ответе @atomicules):

xml.xpath("//Placement").attr("messageId")
...