Node.jsでXMLをまともに読み書きできる唯一と言えそうなxml2jsパッケージがv0.4.5に更新され、待望のCDATAセクションの書き込みに対応した。今までも読み込みは普通に行えていたが、書き込みには対応していなかったため全て文字参照で書かれていたが、これできれいに(小さなRSSが)吐ける。

使い方はビルダーのオプションでcdata: trueするだけだ。これで要素の値が文字列で、かつ[&<>]のいずれかを含む場合のみCDATAセクションとして書かれるようになる。

var xml2js = require('xml2js');

var builder = new xml2js.Builder({
  cdata: true
});
var obj = {
  foo: 'Foo',
  bar: 'Bar'
};
var xml = builder.buildObject(obj);

このようにグローバルでの設定しかないため、CDATAで書くか書かないかの二択になる。この要素ではCDATAを、この要素では文字参照で、などとはできないのが少し残念だ。


まだサポートは完璧ではないようで、パーサー側でexplicitArray: falseで配列を強制せずに読み込んだ場合にうまくいかない事がある。そう設定した場合に得られるJavaScriptオブジェクトやそれと同じ構造を持つJavaScriptオブジェクトを、CDATAで書くように設定したビルダーに渡しても、配列でないプロパティーの値はCDATAで書いてくれない。最小再現コードは以下の通りだ。

var xml2js = require('xml2js');

console.log(new xml2js.Builder({
  cdata: true
}).buildObject({
  'foo': {
    'bar': 'baz & qux'
  }
}));

これでbar要素の内容がCDATAセクションになってくれれば良いが、なってくれない。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
  <bar>baz &amp; qux</bar>
</foo>

イシューは立てておいたので早めに直って欲しい。手元ではパッチを(しかもJavaScriptファイルの方に)当ててなんとなく対応してみたが、ちゃんと全部コード読んでないので間違ってそうだ。