2011年3月2日水曜日

RhinoでXMLを使うときデフォルト名前空間を設定...できたけど何か変?

前回の投稿で名前空間の扱いがよく分からず、力技で処理してました。 その後ちょっと勉強してデフォルト名前空間を設定するコードを発見。 次のようにすればいいようです。

var ns = xmlobj.namespace();
default xml namespace = ns;

これでxmlの各要素にアクセスできるようになりました。 例えば次のようなxmlファイル「test.xml」を用意して、

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.dummy.jp">
    <msg attr="属性">テキスト</msg>
</root>

msg要素にアクセスするには次のようにします。

var xml_text = readFile('test.xml', 'utf-8');
xml_text = xml_text.replace(/^<\?xml.*\?>\s*/, "");

var x = new XML(xml_text);
var ns = x.namespace();
default xml namespace = ns;

print(x.msg);

結果は次のようになりました。

D:\~\rhino1_7R2>java -jar js.jar -w -strict -encoding utf-8 test2.js
テキスト

デフォルト名前空間を使わずに、別個に名前空間を書く場合は次のようになります。

var xml_text = readFile('test.xml', 'utf-8');
xml_text = xml_text.replace(/^<\?xml.*\?>\s*/, "");

var x = new XML(xml_text);
var ns = x.namespace();

print(x.ns::msg);

結果は同じです。

これでXMLの編集ができるようになった...と思ったらちょっと変なところもありました。 ノードへのアクセスの仕方を確かめようと次のようなコードを組んだら...

var xml_text = readFile('test.xml', 'utf-8');
xml_text = xml_text.replace(/^<\?xml.*\?>\s*/, "");

var x = new XML(xml_text);
var ns = x.namespace();
default xml namespace = ns;

print('名前空間 : ' + ns + '\n');

print('<' + x.name() + '>');
attrs = x.attributes();
for(i in attrs)
{
    var attr = attrs[i];
    print('  @' + attr.localName() + ' / @' + attr.name() );
}
print('');

// ルート要素の子孫の全要素名と属性の表示
var elems = x..*;
for(var i in elems)
{
    var elem = elems[i];
    if(elem.nodeKind() == 'element')
    {
        print('<' + elem.name() + '>');
        //print('<' + elem.localName() + '>');
    }
    else if(elem.nodeKind() == 'text')
    {
        print('#text : "' + elem + '"');
    }
    
    var attrs = elem.attributes();
    for(var j in attrs)
    {
        print('  @' + attrs[j].name() );
    }
}

結果はこれ。

D:\~\rhino1_7R2>java -jar js.jar -w -strict -encoding utf-8 test2.js
名前空間 : http://www.dummy.jp

<http://www.dummy.jp::root>
  @xmlns / @http://www.w3.org/2000/xmlns/::xmlns

<http://www.dummy.jp::msg>
  @attr
#text : "テキスト"

一言も書いていないsvgの名前空間が出てきたのです。 なぜ?

なんか嫌な感じの結果ですよね。 これがsvgを読んだときの正しい解析結果だったとしても、

  1. xmlの読み込み。
  2. javascriptで編集。
  3. 編集結果をファイルに出力。

で出力するときには「http://www.w3.org/2000/xmlns/::xmlns」という文字列から元の名前空間を復元しなくてはなりません。 やっぱり前回の投稿のやり方の方が面倒が無くていいかも?