yaml <-> xml の相互変換 (名前空間に対応)
yaml <-> xml の相互変換。
完全な変換はできないが、そこそこの動作をするものが出来た。
(jruby でも動作する。
gem で builder, xml-simple を install することが必要。
$ jruby $JRUBY_HOME/bin/gem install buildre
$ jruby $JRUBY_BOME/bin/gem install xml-simple
)
以下に xml->yaml のソース、yaml->xml のソースを示し、変換結果例を示そう。
xml->yaml は次のようにする。
xml -> Hash -> yaml
---- yaml2xml.rb ----
# See http://www.namikilab.tuat.ac.jp/%7Esasada/prog/yaml.html#i-2# gem install xml-simple
require 'yaml'
require 'rexml/document'
require 'rubygems'
require 'xmlsimple'
require 'pp'good_xml = %{
<groceries>
<bread>Wheat</bread>
<bread>Quadrotriticale</bread>
</groceries>}# puts "----------------"
# doc = XmlSimple.xml_in good_xml
# pp doc
# puts doc.to_yamldoc = XmlSimple.xml_in File.open(ARGV[0])
puts "----------------"
puts doc.to_yaml
puts "----------------"
pp doc
yaml->xml は、http://www.unfitforprint.com/articles/2005/09/23/yaml2xml-in-33-lines-or-your-money-back
にあったコードを元に、xml 宣言を出力する/namespace, prefix 指定を可能にするようにしてみた。
---- yaml2xml.rb ----
# See http://www.xml.com/lpt/a/1637
# http://www.unfitforprint.com/articles/2005/09/23/yaml2xml-in-33-lines-or-your-money-back
#
# Modifyed by katoy 2007-05-18require 'yaml'
require 'rubygems'
require 'builder'
require 'pp'class Yaml2Xml
def initialize roottagname, prefix="", uri=""
@roottagname = roottagname
@prefix, @url = prefix
@url = uri# @builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
@buffer=""
@builder = Builder::XmlMarkup.new(:target=>@buffer, :indent=>2)
enddef buffer
return @buffer
enddef to_xml src
@builder.instruct!
if @prefix == ""
@builder.method_missing(gentag(@roottagname)) {
process_source src
}
else
@builder.method_missing(gentag(@roottagname), "xmlns:" + @prefix => @url) {
process_source src
}
end
enddef yaml2xmlChild src, tagname
if src.is_a?(Hash)
@builder.method_missing(gentag(tagname)) {
process_source src, tagname
}
elsif src.is_a?(Array)
process_source src, tagname
else
@builder.method_missing(gentag(tagname), src)
end
enddef process_source src, tagname=""
if src.is_a?(Hash)
src.each do |name, value|
unless value.kind_of?(Hash) or value.kind_of?(Array)
@builder.method_missing(gentag(tagname), value)
else
yaml2xmlChild value, name
end
end
elsif src.is_a?(Array)
src.each do |value|
unless value.kind_of?(Hash) or value.kind_of?(Array)
yaml2xmlChild value, tagname
else
if value.empty?
yaml2xmlChild "", tagname
else
yaml2xmlChild value, tagname
end
end
end
else
@builder.method_missing(gentag(tagname), value)
end
enddef gentag tagname
return tagname if @prefix == ''
return @prefix + ":" + tagname
endend
yaml = YAML::load(File.open(ARGV[0]))
# puts "---- YAML ----"
# pp yaml
# puts yaml.to_yamlputs "---- XML ----"
x = Yaml2Xml.new 'root', 'ab', 'http://xxx.com'
x.to_xml yaml
puts x.buffer
これを利用して、xml -> yaml -> xml 変換した結果を示そう。
最初のxml:
========
xfy のチュートリアル中の住所録 xml の形式をまねたものだ。
<?xml version="1.0" encoding="UTF-8"?>
<ab:root xmlns:ab="http://xxx.com">
<ab:entry>
<ab:address>Rochester, NY USA</ab:address>
<ab:person>George Adams</ab:person>
</ab:entry>
<ab:entry>
<ab:address>Denver, Colorado USA</ab:address>
<ab:person>Betty Jackson</ab:person>
</ab:entry>
<ab:entry>
<ab:address></ab:address>
<ab:person></ab:person>
</ab:entry>
<ab:entry></ab:entry>
</ab:root>
xml->yaml 結果
=============
実際のコンソール出力から yaml 部分を抜粋したもののみを示す。
$ ruby xml2yaml rb 1.xml
entry:
- address:
- Rochester, NY USA
person:
- George Adams
- address:
- Denver, Colorado USA
person:
- Betty Jackson
- address:
- {}person:
- {}- {}
xmlns:ab: http://xxx.com
yaml->xml 結果
=============
上の結果の最後の行の xmlns:ab: http://xxx.com を削除したものについて実行する。(実際のコンソール出力から xml 部分を抜粋したもののみを示す)
$ ruby yaml2xml.rb 2.yaml
<?xml version="1.0" encoding="UTF-8"?>
<ab:root xmlns:ab="http://xxx.com">
<ab:entry>
<ab:address>Rochester, NY USA</ab:address>
<ab:person>George Adams</ab:person>
</ab:entry>
<ab:entry>
<ab:address>Denver, Colorado USA</ab:address>
<ab:person>Betty Jackson</ab:person>
</ab:entry>
<ab:entry>
<ab:address></ab:address>
<ab:person></ab:person>
</ab:entry>
<ab:entry></ab:entry>
</ab:root>
これで、ruby で生成したデータを xml 化して、xfy/xvcd に送り込むことが出来そうだ。
ruby で RDB などにアクセスして得たデータや、druby や rinda 上で取得したデータなども xml に加工して xfy/xvcd に送り込める。
逆に xfy/xvcd から 渡される xml を ruby 側で hash/yaml にして、それ以降の処理を行うこともできる。
« ピックアップ: 連想検索エンジンreflexaのAPI, UISpec4J:Java GUI Testing, etc... | トップページ | wirble で irb が使いやすくなる »
この記事へのコメントは終了しました。
« ピックアップ: 連想検索エンジンreflexaのAPI, UISpec4J:Java GUI Testing, etc... | トップページ | wirble で irb が使いやすくなる »
コメント