2014-01-29 2 views
0

Я пытался установить атрибут для конкретного элемента в файле XML, и у меня был успех, используяУстановка атрибута в Nokogiri :: XML :: NodeSet с CSS

doc.css('Object').attr("Id").value = timestamp 

Это было прекрасно до тех пор, ситуация, когда «Объект» не существует, вызывая исключение в программе и завершая работу. Чтобы избежать этого, я хотел использовать Nodeset, поскольку вместо этого он будет пустым.

doc.css('Object').each do |element| 
    element.attr("Id").value = timestamp 
end 

Однако это возвращает с ошибкой, что значение = является неопределенным методом. Это, наверное, что-то простое, но я новичок в Ruby и CSS, поэтому любая помощь будет отличной.

ответ

1

Эта проблема имеет мало общего с CSS, поскольку Nokogiri использует селекторы CSS в качестве альтернативы использованию селекторов XPath, и оба они используются только для указания пути к узлу или узлам.

Похоже, вы слишком задумываетесь об этом и делаете его сложнее, чем должно быть. Вот что я хотел бы сделать:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<xml> 
    <foo> 
    <Object>bar</Object> 
    </foo> 
</xml> 
EOT 

doc.at('Object')["Id"] = Time.now.to_s 

Глядя на doc в данный момент показывает:

puts doc.to_xml 
# >> <?xml version="1.0"?> 
# >> <xml> 
# >> <foo> 
# >>  <Object Id="2014-01-28 19:13:32 -0700">bar</Object> 
# >> </foo> 
# >> </xml> 

Это очень важно понимать разницу между at, at_css и at_xpath, которые возвращают первый соответствие Node, и search, css и xpath, которые возвращают NodeSets. A NodeSet сродни массиву, содержащему узлы. Когда вы знаете, что ваше заявление:

doc.css('Object').attr("Id").value = timestamp 

не имеет особого смысла, тем более, что это не так, как определяется метод attr:

attr(key, value = nil, &blk) 

Вы должны были бы использовать:

doc.css('Object').attr("Id", value) 

, который присваивает value всем Id атрибутам для каждого <Object> узел в документе.

Но, опять же, это неправильный выбор, вместо этого вы должны использовать at или at_css, чтобы вернуть единственный узел.

Это был прекрасен до ситуации, когда «объект» не существует

Если нет <Object> узла не существует, то он становится более интересным, и вы должны определить, что делать. Вы можете вставить его, или вы можете просто двигаться вперед и ничего не делать.

Чтобы увидеть, если узел существует простое:

object_node = doc.at('Object') 
if object_node 
    object_node['Id'] = Time.now.to_s 
else 
    # ... insert it 
end 

Чтобы вставить узел включает местонахождение место, куда вы хотите, чтобы вставить его, а затем добавить его:

doc.at('foo').add_child("<Object Id='#{ Time.now }'>baz</Object>") 
puts doc.to_xml 
# >> <?xml version="1.0"?> 
# >> <xml> 
# >> <foo> 
# >>  <Object>bar</Object> 
# >> <Object Id="2014-01-28 19:39:38 -0700">baz</Object></foo> 
# >> </xml> 

Я не пробовал чтобы сделать вывод XML довольно, что не важно в XML, он просто должен быть синтаксически правильным.

Также обратите внимание, что можно вставить узел или узлы, указав их как строку XML. Nokogiri проанализирует его в соответствующем XML и пересаживает его там, где вы сказали. Вы также можете пройти длинный маршрут, задав NodeSet или Node, а затем вставив его, но, в общем, это делает более уродливый код и заставляет вас делать гораздо больше работы, что приводит к тому, что менее читаемый код для тех, кто следует по вашим стопам поддерживая источник.

+0

Спасибо за подробный ответ! Это определенно помогло. Я был уверен, что думаю, и заработал мою программу, как я этого хочу! – Jud202

+0

Рад помочь. Я пришел к Ruby и Nokogiri после использования синтаксических анализаторов XML в Perl и очень много сделал. Ruby и Nokogiri, сделать это намного проще. –

Смежные вопросы