Ну, обычно Nokogiri позволяет действительно легко заменять узлы или удалять их и добавлять что-то еще, но для этого нужно немного обойти:
require 'nokogiri'
old_doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE relatos PUBLIC "-//SINCODH/DTD relatos 0.97" "relatos.dtd">
<relatos>
<foo />
<bar />
</relatos>
EOT
Создать новый документ:
new_doc = Nokogiri::XML('<relatos/>')
Что выглядит следующим образом:
new_doc.to_xml # => "<?xml version=\"1.0\"?>\n<relatos/>\n"
Затем добавьте новый DTD:
new_doc.create_internal_subset('relatos', nil, 'test/dummy/public/midtd.dtd')
Затем добавьте узлы из старого документа в новый:
new_doc.at('relatos').children = old_doc.at('relatos').children
В результате:
new_doc.to_xml # => "<?xml version=\"1.0\"?>\n<!DOCTYPE relatos SYSTEM \"test/dummy/public/midtd.dtd\">\n<relatos>\n <foo/>\n <bar/>\n</relatos>\n"
Вот код в одном фрагменте:
require 'nokogiri'
old_doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE relatos PUBLIC "-//SINCODH/DTD relatos 0.97" "relatos.dtd">
<relatos>
<foo />
<bar />
</relatos>
EOT
new_doc = Nokogiri::XML('<relatos/>')
new_doc.create_internal_subset('relatos', nil, 'test/dummy/public/midtd.dtd')
new_doc.at('relatos').children = old_doc.at('relatos').children
Вы можете спросить в списке разговоров Nokogiri или их IR C Канал, как там действительно умные люди.