XML::XUpdate::LibXMLでxupdateを使う
xmldiff xupdate XMLDB xindice の続き。
前に検索してたときにどうもxmlupdateで検索してたっぽく、今日xupdateで検索したらふつうに XML::XUpdate::LibXML – Simple implementation of XUpdate format – search.cpan.org が出てきて脱力。
<?xml version="1.0"?>
<me
><name>KUMAGAI Kentaro</name>
<mail>ku*ido.nu</mail>
<related_url>
<url>http://ido.nu/</url>
<url>http://twitter.com/ku</url>
<url>http://ku.tumblr.com/</url>
</related_url>
</me>
っていうのと
<?xml version="1.0"?>
<me>
<name>熊谷健太郎</name>
<mail>ku0522a*gmail.com</mail>
<related_url>
<url>http://ido.nu/</url>
<url>http://twitter.com/ku</url>
<url>http://ku.tumblr.com/</url>
<url>http://ku.tumblr.com/</url>
<url>http://bluedot.us/users/ku0522</url>
</related_url>
</me>
っていうのの差分をxmldiffで作る。
xmldiff -x profile.xml profile_altered.xml
出てくるxupdateは
<?xml version="1.0"?>
<xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate">
<xupdate:append select="/me[1]" child="first()" > <xupdate:element name="name">熊谷健太郎
</xupdate:element>
</xupdate:append>
<xupdate:insert-after select="/me[1]/name[1]" > <xupdate:element name="mail">ku0522a*gmail.com
</xupdate:element>
</xupdate:insert-after>
<xupdate:insert-after select="/me[1]/related_url[1]/url[3]" > <xupdate:element name="url">http://ku.tumblr.com/
</xupdate:element>
</xupdate:insert-after>
<xupdate:insert-after select="/me[1]/related_url[1]/url[4]" > <xupdate:element name="url">http://bluedot.us/users/ku0522
</xupdate:element>
</xupdate:insert-after>
<xupdate:remove select="/me[1]/name[2]" />
<xupdate:remove select="/me[1]/mail[2]" />
</xupdate:modifications>
こう。これを
#!/usr/bin/perl
use XML::LibXML;
use XML::XUpdate::LibXML;
$parser = XML::LibXML->new();
$dom = $parser->parse_file(shift);
$diff = $parser->parse_file(shift);
$xupdate = XML::XUpdate::LibXML->new();
$xupdate->process($dom->getDocumentElement(), $diff);
print $dom->toString();
こういうコードで実行するだけでいい。
でもどうもxmldiffが生成するxupdateの中の child="first()" っていうのはNGらしく、実行すると
xmlXPathCompOpEval: function first not found
Unregistered function at /usr/perl5/site_perl/5.8.4/XML/XUpdate/LibXML.pm line 164
といわれるので XML/XUpdate/LibXML.pm をみてみると
# XUpdate WD is weird:
# child=1 should mean make the new node 1st child
# child=last() should mean make new node last child
なーんて書いてあるので、child="first()"部分をあらかじめ child="1" に置き換えておいてあげると解決。たしかにXPathにlast()はあるけどfirst()はない。
そうするとインデントが違うけどXML的には同じものに仕上がります。
<me> <name>熊谷健太郎
</name> <mail>ku0522a*gmail.com
</mail>
<related_url>
<url>http://ido.nu/</url>
<url>http://twitter.com/ku</url>
<url>http://ku.tumblr.com/</url> <url>http://ku.tumblr.com/
</url> <url>http://bluedot.us/users/ku0522
</url>
</related_url>
</me>
ブラボー!
どうもxmldiffのつくるxupdateとXML::XUpdate::LibXMLと相性が良くないようで、あらかじめxupdateのXMLから不要なホワイトスペースを取っておかないと出てくる結果がおかしかったり、インデントが変になったりします。なのでこの組み合わせで使うときはかならずとりましょう。

No comments
Jump to comment form | comments rss [?] | trackback uri [?]