ruby で freemind <-> text 相互変換の実験
ruby で text から freemind ファイルを生成したり、逆に freemind ファイルからテキストを生成したりさせてみた。
# freemind 自体には、 text 出力や text の張りつけ機能があるが、ruby での扱い方ができるようにしておけば、別のプログラムと組み合わせて使う事に利用できるだろう。
テキストの形式としては、TAB でのインデント付けでの node 菜(UTF8) とした。
test.txt として、入力データを用意した。
プログラムは2つを用意した。
text2mm.rb : text -> freemind 変換
mm2text.rb: frremind. -> text 変換
ソースコードは後で示すとして、実行例を先に示そう。
$ cat test.txt
新規ノード
B
B1
B2
B3-<&>"|'
C
C1
C1-1
D
$ ruby text2mm.rb test.txt
out.mm に結果が出力される。
$ cat out.mm
<map version='0.9.0'>
<node MODIFIED='1228559840186' TEXT='新規ノード' ID='IDX_1' CREATED='1228559840186'>
<node MODIFIED='1228559840186' TEXT='' ID='IDX_2' CREATED='1228559840186'>
<node MODIFIED='1228559840186' TEXT='B' ID='IDX_3' CREATED='1228559840186'>
<node MODIFIED='1228559840187' TEXT='B1' ID='IDX_4' CREATED='1228559840187'/>
<node MODIFIED='1228559840187' TEXT='B2' ID='IDX_5' CREATED='1228559840187'/>
<node MODIFIED='1228559840187' TEXT='B3-<&>"|'' ID='IDX_6' CREATED='1228559840187'/>
</node>
</node>
<node MODIFIED='1228559840187' TEXT='C' ID='IDX_7' CREATED='1228559840187'>
<node MODIFIED='1228559840188' TEXT='C1' ID='IDX_8' CREATED='1228559840188'>
<node MODIFIED='1228559840188' TEXT='C1-1' ID='IDX_9' CREATED='1228559840188'/>
</node>
</node>
<node MODIFIED='1228559840188' TEXT='D' ID='IDX_10' CREATED='1228559840188'/>
</node>
</map>
freemind で out.mm を読み込んだときのスクリーンショット
$ ruby mm2text.rb out.mm
新規ノード
B
B1
B2
B3-<&>"|'
C
C1
C1-1
D
コードを示す。
$ cat text2mm.rb
# TAB でインデント付けした Text ファイルから Freemind ファイルを作成する。
# 2008-12-05 katoy
require 'rubygems'
require 'rexml/document'
require 'cgi'
require 'pp'
$KCODE="UTF-8"
class Mindmap
attr_reader :current
def initialize
@id_prefix = 'IDX'
@nextId = 1
@doc = REXML::Document.new
map = REXML::Element.new('map')
map.add_attribute 'version', '0.9.0'
@doc.add_element map
@current = map
end
def open(text = "")
node = REXML::Element.new('node')
id = "#{@id_prefix}_#{@nextId}"
@nextId += 1
s = CGI.escapeHTML(text)
s = s.gsub('&', '&')
s = s.gsub('<', '<')
s = s.gsub('>', '>')
s = s.gsub('"', '"')
s = s.gsub(''', '\'')
time = (Time.new.to_f * 1000).to_i.to_s
node.add_attributes( { 'ID' => id, 'TEXT' => s,
'CREATED' => time, 'MODIFIED' => time } )
@current.add_element node unless @current.nil?
@current = node
end
def close
@current = @current.parent
end
def write_to(xml_path)
out = File.new(xml_path, File::CREAT|File::TRUNC|File::RDWR)
begin
@doc.write(out, 2)
ensure
out.close
end
end
end
file = ARGV.shift
map = Mindmap.new()
prev_indent = -1
open(file) { |f|
while line = f.gets
next if line.chomp.size == 0 # 空行はスキップ
/(\t*)(.*)(\r*\n*)/ =~ line
indent = $1.size # 先頭のタブ数
(prev_indent - indent + 1).times { map.close }
(indent - prev_indent - 1).times { map.open }
map.open($2)
prev_indent = indent
end
}
(prev_indent + 1).times { map.close }
raise "assert" unless prev_indent != 0
raise "assert" unless map.current.name == "map"
map.write_to "out.mm"
$ cat mm2text.rb
# See http://www.bytemycode.com/snippets/snippet/504/
# Freemind データのノード名を TAB で indent して出力する。
# 2008-12-05 katoy
require 'rubygems'
require 'rexml/document'
require 'cgi'
require 'pp'
$KCODE="UTF-8"
def out_nodes(elem, indent = 0)
type = elem.node_type
if type != :text and type != :comment
text = elem.attributes.get_attribute 'TEXT'
if text != nil
puts "\t" * (indent - 1) + CGI.unescapeHTML(text.to_s)
end
elem.each do |c|
out_nodes(c, indent + 1)
end
end
end
f = ARGV.shift
doc = REXML::Document.new File.open(f)
out_nodes doc.root
これらは 特別な ライブラリーは使っていないので jruby でも動作する。
« ピックアップ:押井守が「鉄人28号」を演出!, XMLを越える万能なRESTful API, etc... | トップページ | ピックアップ:ジンバブエが1位で日本が2位のもの、古いJREを一掃する「JavaRa」, etc... »
この記事へのコメントは終了しました。
« ピックアップ:押井守が「鉄人28号」を演出!, XMLを越える万能なRESTful API, etc... | トップページ | ピックアップ:ジンバブエが1位で日本が2位のもの、古いJREを一掃する「JavaRa」, etc... »
コメント