image

  • フォト Amazonギフト券
    ※この時計の時刻は、閲覧しているパソコンのものであり、必ずしも正確な時間とは限りません

検索

最近のトラックバック

無料ブログはココログ

« ピックアップ: 連想検索エンジンreflexaのAPI, UISpec4J:Java GUI Testing, etc... | トップページ | wirble で irb が使いやすくなる »

2007-05-19

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_yaml

doc = 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-18

require '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)
  end

  def buffer
    return @buffer
  end

  def 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
  end

  def 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
  end

  def 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
  end

  def gentag tagname   
    return tagname if @prefix == ''
    return @prefix + ":" + tagname
  end

end

yaml = YAML::load(File.open(ARGV[0]))
# puts "---- YAML ----"
# pp yaml
# puts yaml.to_yaml

puts "---- 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 が使いやすくなる »

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: yaml <-> xml の相互変換 (名前空間に対応):

« ピックアップ: 連想検索エンジンreflexaのAPI, UISpec4J:Java GUI Testing, etc... | トップページ | wirble で irb が使いやすくなる »

mokuji

2013年12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

google

  • twitter
  • __
  • _
    Googleボットチェッカー

合わせて読む

  • 合わせて読む
    フィードメーター - katoy: cocolog あわせて読みたい

リンク