Как правильно вставить XML-документ в другой, используя rexml? - PullRequest
2 голосов
/ 04 марта 2010

Мне удалось выяснить основную часть моего вопроса: «Как вставить один XML-документ в другой?» Полученный результат будет работать, но в напечатанном XML отсутствует перевод строки.

s = <<EOF
<application>
  <email>
    <host>mail.test.com</host>
    <port>25</port>
  </email>
</application>
EOF

p = <<EOF
<auth>
  <user>godber</user>
  <pass>foo</pass>
</auth>
EOF

subdoc = REXML::Document.new(p)
doc = REXML::Document.new(s)
doc.root.insert_after( '//email', subdoc.root )
doc.write

это выводит следующее, которое, как вы можете видеть, имеет тег auth, начинающийся сразу после тега закрытия электронного письма без новой строки

<application>
  <email>
    <host>mail.test.com</host>
    <port>25</port>
  </email><auth>
  <user>godber</user>
  <pass>foo</pass>
</auth>
</application>

На самом деле, как только я закончил, я понял, что могу изменить свою последнюю строку на

doc.write( $stdout, 2 )

Это было ясно написано в учебнике по rexml, я просто упустил из виду, что что-то не так. Я предполагаю, что подам это на случай, если кто-то еще будет озадачен этим. Если у кого-то есть советы по этим вопросам, я буду рад их услышать.

1 Ответ

2 голосов
/ 27 сентября 2011

REXML делает точно то, что вы просите: doc.root.insert_after('//email', subdoc.root) означает поставить subdoc.root сразу после последнего элемента email. И последний элемент email заканчивается точно после > in </email>.

Узлы пробелов, хотя мы, люди-читатели, часто упускаем из виду, не могут игнорироваться анализаторами XML. Ключевым моментом здесь является этот документ XML

<doc>
  <email>
  </email>
</doc>

не состоит из элемента email внутри элемента doc. На самом деле он сделан из порядка 1014 *

  • root doc element,
  • один текстовый узел с текстом "[новая строка] [пробел] [пробел]",
  • элемент email, содержащий текстовый узел "[newline] [пробел] [пробел]",
  • другой текстовый узел с текстом «[newline]».

Это означает, что REXML не может произвольно добавить пробелы, необходимые для отступа auth так, как мы ожидаем.

Чтобы обойти эту проблему, нужно попросить REXML вызвать повторную сериализацию XML-документа. Это то, что вы сделали, используя метод #write с положительным уровнем отступа. Но вы можете сделать это только в том случае, если пробелы не важны в вашем документе: позволите ли REXML переформатировать фрагмент кода с тщательно выделенным кодом Ruby?

...