如何使用rexml将XML文档正确插入另一个文档?

时间:2010-03-04 00:08:18

标签: xml ruby rexml

我已经设法找出问题的主要部分,“如何将一个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 个答案:

答案 0 :(得分:2)

REXML正在按照您的要求执行:doc.root.insert_after('//email', subdoc.root)表示将subdoc.root放在最后一个email元素之后。最后一个email元素恰好在>中的</email>之后结束。

空格节点虽然经常被人类读者忽视,但是XML解析器不能忽略它们。 这里的关键是这个XML文档

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

不是由email元素中的doc元素组成的。实际上它是按顺序制成的

  • root doc元素,
  • 一个文本节点,文本为“[newline] [space] [space]”,
  • 包含文本节点“[newline] [space] [space]”的email元素,
  • 另一个文本节点,文本为“[newline]”。

这意味着REXML不能以我们预期的方式任意添加缩进auth所需的空格。

解决此问题的一种方法是要求REXML强制重新序列化XML文档,这是使用具有正缩进级别的#write方法所做的。但是,只有当文档中的空格不重要时,才能这样做:您是否会让REXML重新格式化一段精心缩进的Ruby代码?