Эта проблема имеет мало общего с 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, а затем вставив его, но, в общем, это делает более уродливый код и заставляет вас делать гораздо больше работы, что приводит к тому, что менее читаемый код для тех, кто следует по вашим стопам поддерживая источник.
Спасибо за подробный ответ! Это определенно помогло. Я был уверен, что думаю, и заработал мою программу, как я этого хочу! – Jud202
Рад помочь. Я пришел к Ruby и Nokogiri после использования синтаксических анализаторов XML в Perl и очень много сделал. Ruby и Nokogiri, сделать это намного проще. –