2

「あるXMLドキュメントを別の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

これにより、次のように出力されます。これは、改行なしで電子メールの終了タグの直後に認証タグが開始されていることがわかります。

<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チュートリアルで明確に書かれていましたが、他の何かが間違っていると思い込んで見落としていました。他の誰かがこれに戸惑う場合に備えて、私はこれを提出すると思います。誰かがこれらの線に沿ってヒントを持っているなら、私はそれらを聞いてうれしいです。

4

1 に答える 1

2

REXML はあなたが求めていることを正確に実行しています: 最後の要素の直後にdoc.root.insert_after('//email', subdoc.root)配置することを意味します。そして、最後の要素は in の直後で終わります。subdoc.rootemailemail></email>

空白ノードは、人間の読者には見過ごされがちですが、XML パーサーは無視できません。ここで重要なのは、この XML ドキュメントです。

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

email要素内の要素によって構成されていませんdoc。実際には、順番に、

  • ルートdoc要素、
  • テキスト「[改行][スペース][スペース]」を持つ1つのテキストノード、
  • emailテキストノード「[改行][スペース][スペース]」を含む要素、
  • テキスト「[改行]」を持つ別のテキストノード。

これは、REXML がauth期待どおりにインデントするために必要なスペースを任意に追加できないことを意味します。

これを回避する方法は、REXML に XML ドキュメントの再シリアル化を強制することです。これは#write、正のインデント レベルのメソッドを使用して行ったことです。しかし、それができるのは、文書内で空白が重要でない場合だけです。慎重にインデントされた Ruby コードのスニペットを REXML で再フォーマットできますか?

于 2011-09-27T13:28:48.620 に答える