ixyml 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.gitignore~ +17 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +44 -0
- data/Gemfile~ +13 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/dbg_x2o +8 -0
- data/bin/x2y +8 -0
- data/bin/y2x +17 -0
- data/ixyml.gemspec +23 -0
- data/lib/ixyml.rb +10 -0
- data/lib/ixyml/version.rb +3 -0
- data/lib/ixyml/xyml.rb +821 -0
- data/lib/ixyml/xyml_element.rb +778 -0
- data/test/dirTemp/ktest00.nml.j2j.json +1 -0
- data/test/dirTemp/ktest00.nml.nml.xml +53 -0
- data/test/dirTemp/ktest00.nml.nml.yaml +74 -0
- data/test/dirTemp/ktest00.nml.x2j.json +1 -0
- data/test/dirTemp/ktest00.nml.x2x.xml +53 -0
- data/test/dirTemp/ktest00.nml.xyj.yaml +134 -0
- data/test/dirTemp/ktest00.nml.xyx.xml +53 -0
- data/test/dirTemp/ktest00.nml.xyx.yaml +134 -0
- data/test/dirTemp/ktest00.nml.y2j.json +1 -0
- data/test/dirTemp/ktest00.nml.y2y.yaml +74 -0
- data/test/dirTemp/ktest00.nml.yxy.xml +2 -0
- data/test/dirTemp/ktest00.nml.yxy.yaml +74 -0
- data/test/dirTemp/ktest01.nml.yaml +74 -0
- data/test/dirTemp/ktest01.yxy.xml +2 -0
- data/test/dirTemp/ktest01.yxy.yaml +74 -0
- data/test/dirTemp/test01.nml.nml.xml +21 -0
- data/test/dirTemp/test01.nml.nml.yaml +5 -0
- data/test/dirTemp/test01.nml.x2j.json +1 -0
- data/test/dirTemp/test01.nml.x2x.xml +21 -0
- data/test/dirTemp/test01.nml.xyj.yaml +18 -0
- data/test/dirTemp/test01.nml.xyx.xml +21 -0
- data/test/dirTemp/test01.nml.xyx.yaml +18 -0
- data/test/dirTemp/test01.nml.y2j.json +1 -0
- data/test/dirTemp/test01.nml.y2y.yaml +5 -0
- data/test/dirTemp/test01.nml.yaml +74 -0
- data/test/dirTemp/test01.nml.yxy.xml +3 -0
- data/test/dirTemp/test01.nml.yxy.yaml +5 -0
- data/test/dirTemp/test01.yxy.xml +2 -0
- data/test/dirTemp/test01.yxy.yaml +74 -0
- data/test/dirTemp/testBreak.nml.yaml +7 -0
- data/test/dirTemp/testBreak.yxy.xml +5 -0
- data/test/dirTemp/testBreak.yxy.yaml +7 -0
- data/test/dirTemp/testCDATA.nml.nml.xml +26 -0
- data/test/dirTemp/testCDATA.nml.x2j.json +1 -0
- data/test/dirTemp/testCDATA.nml.x2x.xml +26 -0
- data/test/dirTemp/testCDATA.nml.xyj.yaml +18 -0
- data/test/dirTemp/testCDATA.nml.xyx.xml +26 -0
- data/test/dirTemp/testCDATA.nml.xyx.yaml +18 -0
- data/test/dirTemp/testCDATA.nml.y2j.json +1 -0
- data/test/dirTemp/testEscape.nml.nml.xml +77 -0
- data/test/dirTemp/testEscape.nml.nml.yaml +53 -0
- data/test/dirTemp/testEscape.nml.x2j.json +1 -0
- data/test/dirTemp/testEscape.nml.x2x.xml +77 -0
- data/test/dirTemp/testEscape.nml.xyj.yaml +213 -0
- data/test/dirTemp/testEscape.nml.xyx.xml +77 -0
- data/test/dirTemp/testEscape.nml.xyx.yaml +213 -0
- data/test/dirTemp/testEscape.nml.y2j.json +1 -0
- data/test/dirTemp/testEscape.nml.y2y.yaml +53 -0
- data/test/dirTemp/testEscape.nml.yxy.xml +2 -0
- data/test/dirTemp/testEscape.nml.yxy.yaml +53 -0
- data/test/dirTemp/testNS.nml.nml.xml +21 -0
- data/test/dirTemp/testNS.nml.x2j.json +1 -0
- data/test/dirTemp/testNS.nml.x2x.xml +21 -0
- data/test/dirTemp/testNS.nml.xyj.yaml +19 -0
- data/test/dirTemp/testNS.nml.xyx.xml +21 -0
- data/test/dirTemp/testNS.nml.xyx.yaml +19 -0
- data/test/dirTemp/testNS.nml.y2j.json +1 -0
- data/test/test_xyml.rb +167 -0
- data/test/test_xyml.rb~ +167 -0
- data/test/test_xyml_element.rb +241 -0
- data/test/test_xyml_element.rb~ +111 -0
- data/test/testfiles/ktest00.nml.ori.json +1 -0
- data/test/testfiles/ktest00.nml.ori.xml +53 -0
- data/test/testfiles/ktest00.nml.ori.yaml +74 -0
- data/test/testfiles/ktest00.nml.ori.yaml~ +75 -0
- data/test/testfiles/ktest01.ori.yaml +75 -0
- data/test/testfiles/test01.nml.ori.xml +21 -0
- data/test/testfiles/test01.nml.ori.yaml +5 -0
- data/test/testfiles/test01.ori.yaml +75 -0
- data/test/testfiles/testBreak.ori.yaml +10 -0
- data/test/testfiles/testCDATA.ng.ng.xml +26 -0
- data/test/testfiles/testEscape.nml.ori.xml +77 -0
- data/test/testfiles/testEscape.nml.ori.yaml +105 -0
- data/test/testfiles/testNS.nml.ori.xml +21 -0
- data/test/testfiles/xmlTemp.xml +2 -0
- data/test/testfiles/xymlTemp.xyml +6 -0
- metadata +230 -0
data/.gitignore
ADDED
data/.gitignore~
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ixyml (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (4.0.0)
|
10
|
+
i18n (~> 0.6, >= 0.6.4)
|
11
|
+
minitest (~> 4.2)
|
12
|
+
multi_json (~> 1.3)
|
13
|
+
thread_safe (~> 0.1)
|
14
|
+
tzinfo (~> 0.3.37)
|
15
|
+
ansi (1.4.3)
|
16
|
+
atomic (1.1.13)
|
17
|
+
i18n (0.6.5)
|
18
|
+
json (1.8.0)
|
19
|
+
minitest (4.7.5)
|
20
|
+
multi_json (1.7.9)
|
21
|
+
rubytest (0.7.0)
|
22
|
+
ansi
|
23
|
+
shoulda (3.5.0)
|
24
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
25
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
26
|
+
shoulda-context (1.1.5)
|
27
|
+
shoulda-matchers (2.3.0)
|
28
|
+
activesupport (>= 3.0.0)
|
29
|
+
test (1.0.0)
|
30
|
+
rubytest
|
31
|
+
thread_safe (0.1.2)
|
32
|
+
atomic
|
33
|
+
tzinfo (0.3.37)
|
34
|
+
unit (0.4.1)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
ixyml!
|
41
|
+
json
|
42
|
+
shoulda
|
43
|
+
test
|
44
|
+
unit
|
data/Gemfile~
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Nobuhiko Ido
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Ixyml
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ixyml'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ixyml
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/dbg_x2o
ADDED
data/bin/x2y
ADDED
data/bin/y2x
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
require 'xyml/xyml'
|
3
|
+
|
4
|
+
from=ARGV[0]
|
5
|
+
to=ARGV[1]
|
6
|
+
indent=nil
|
7
|
+
if ARGV[2]
|
8
|
+
indent=ARGV[2]
|
9
|
+
end
|
10
|
+
|
11
|
+
xyml=Xyml::Document.new
|
12
|
+
xyml.load_YAML(File.open(from))
|
13
|
+
if indent then
|
14
|
+
xyml.out_XML(File.open(to,'w'),indent)
|
15
|
+
else
|
16
|
+
xyml.out_XML(File.open(to,'w'))
|
17
|
+
end
|
data/ixyml.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ixyml/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Nobuhiko Ido"]
|
6
|
+
gem.email = ["ido@gifu-keizai.ac.jp"]
|
7
|
+
gem.description = %q{I propose a new file format called "XYML." Xyml module has the following functions:
|
8
|
+
* loads a XYML file as an instance of Xyml::Document, saves an instance of Xyml::Document as a XYML file.
|
9
|
+
* loads an XML subset file as an instance of Xyml::Document, saves an instance of Xyml::Document as an XML file.
|
10
|
+
* saves an instance of Xyml::Document as a JSON file.
|
11
|
+
* converts an instance of Xyml::Document to an instance of REXML::Document and vice versa. The instance of REXML::Document supports a subset of XML specifications.
|
12
|
+
Xyml_element module provides XYML element API methods. These API methods can be used to elements in Xyml::Document.}
|
13
|
+
gem.summary = %q{XYML file accessors and XYML element accessors.}
|
14
|
+
|
15
|
+
gem.homepage = "https://github.com/nobuhiko-ido/Ixyml"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($\)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.name = "ixyml"
|
21
|
+
gem.require_paths = ["lib"]
|
22
|
+
gem.version = Ixyml::VERSION
|
23
|
+
end
|
data/lib/ixyml.rb
ADDED
data/lib/ixyml/xyml.rb
ADDED
@@ -0,0 +1,821 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
require 'pp'
|
5
|
+
require_relative 'xyml_element'
|
6
|
+
# In this manual, "XYML" is explained first. After that, "XYML module" is explained.
|
7
|
+
#
|
8
|
+
# このマニュアルでは、最初にXYMLについて説明し、その後にXYMLモジュールについて説明する。
|
9
|
+
#
|
10
|
+
# == (1)XYML file format
|
11
|
+
# I propose an alternative text file format ”XYML(Xml in YaML format)” for writing XML subset data,
|
12
|
+
# suitable for input by non-engineers. Although some file formats have been proposed for the same purpose,
|
13
|
+
# XYML can be distinguished from them by its significant feature that a XYML format file can be read and
|
14
|
+
# written as a YAML file. Inheriting both the simple tree data structure of XML and the readability of YAML,
|
15
|
+
# a text in the XYML format is easy to understand because it looks like book contents.
|
16
|
+
#
|
17
|
+
# == (1)Xymlファイル形式
|
18
|
+
#
|
19
|
+
# 非技術者にも XML サブセットデータの入力が容易に行えることを目的とした、ファイル形式
|
20
|
+
# ”XYML(Xml in YaML format)”を提案する。このようなファイル形式は既にいくつもの提案があるが、
|
21
|
+
# 提案する XYML はデータ直列化形式である YAML ファイルとして読み書きが出来ることに大きな特徴がある。
|
22
|
+
# XML のツリー構造データの簡明さと YAML の可読性の良さとを活かすことにより、目次風の分かりやすい
|
23
|
+
# ファイル形式を XYML は実現している。
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# == (2)Example of Mapping between XYML and XML
|
27
|
+
# == (2)XYMLとXMLとの対応の例
|
28
|
+
# +--XYML------------+ +--XML---------------+
|
29
|
+
# | - aaa: | | <aaa> |
|
30
|
+
# | - bbb: | | <bbb xxx="1" |
|
31
|
+
# | - xxx: 1 | | yyy="2"> |
|
32
|
+
# | - yyy: 2 | | <ccc zzz="3"> |
|
33
|
+
# | - ccc: | | morning |
|
34
|
+
# | - zzz: 3 | | </ccc> |
|
35
|
+
# | - morning | | <ddd zzz="4"> |
|
36
|
+
# | - ddd: | | noon |
|
37
|
+
# | - zzz: 4 | | </ddd> |
|
38
|
+
# | - noon | | </bbb> |
|
39
|
+
# | - eee: | | <eee xxx="5" |
|
40
|
+
# | - xxx: 5 | | yyy="6"> |
|
41
|
+
# | - yyy: 6 | | <fff zzz="7"> |
|
42
|
+
# | - fff: | | night |
|
43
|
+
# | - zzz: 7 | | </fff> |
|
44
|
+
# | - night | | </eee> |
|
45
|
+
# +------------------+ | </aaa> |
|
46
|
+
# +--------------------+
|
47
|
+
#
|
48
|
+
# == (3)Mapping from XML to XYML
|
49
|
+
#
|
50
|
+
# == (3)XMLからXYMLへの対応付け
|
51
|
+
#
|
52
|
+
# === (3.1)element
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# An element corresponds to a hash which has only one pair of key and value,
|
56
|
+
# where the key stands for the element name and the value is an array of
|
57
|
+
# child elements and texts. Note the key must be a symbol.
|
58
|
+
#
|
59
|
+
#
|
60
|
+
# === (3.1)要素(エレメント)
|
61
|
+
#
|
62
|
+
#
|
63
|
+
# 要素は、キー・バリュー対が一つだけのハッシュに対応する。そのキーが要素名を
|
64
|
+
# 表し、そのバリューは子エレメントとテキストが要素の配列となる。要素名となる
|
65
|
+
# キーはシンボルであることに注意。
|
66
|
+
#
|
67
|
+
# +--XML--------------------+ +--XYML-------+
|
68
|
+
# | <eee a>bc</eee> | | - eee: | '-'(hyphon) before 'eee'
|
69
|
+
# | * a : attribute | | - a | stands for a part of array
|
70
|
+
# | * b,c : child node,text | | - b | that belongs to the parent
|
71
|
+
# +-------------------------+ | - c | element.
|
72
|
+
# +-------------+
|
73
|
+
#
|
74
|
+
#
|
75
|
+
# === (3.2)attribute
|
76
|
+
#
|
77
|
+
# An attribute corresponds to a hash which has only one pair of key and value,
|
78
|
+
# where the key stands for the attribute name and the value is a scalar of attribute
|
79
|
+
# value.
|
80
|
+
# A hash of an attribute can be distinguished from a hash of an element by the fact
|
81
|
+
# that its value is not an array. Note the key must be a symbol.
|
82
|
+
#
|
83
|
+
# === (3.2)属性
|
84
|
+
#
|
85
|
+
# 属性は、キー・バリュー対が一つだけのハッシュに対応する。そのキーが属性名を
|
86
|
+
# 表し、そのバリューが属性値を表す。
|
87
|
+
# バリューが配列では無いことにより、属性のハッシュは、要素のハッシュと見分けがつく。
|
88
|
+
# キーはシンボルであることに注意。
|
89
|
+
#
|
90
|
+
# +--XML--------------------+ +--XYML-------+ '-'(hyphon) before 'aaa'
|
91
|
+
# | aaa="AAA" | | - aaa: AAA | stands for a part of array
|
92
|
+
# | | | | that belongs to the parent
|
93
|
+
# +-------------------------+ +-------------+ element.
|
94
|
+
#
|
95
|
+
# === (3.3) text node
|
96
|
+
#
|
97
|
+
# A text node corresponds to a scalar which is in the array of its parent element.
|
98
|
+
#
|
99
|
+
# If two or more scalars are in the array, they are joined when method 'gt'(get text) is called.
|
100
|
+
# You can get such parted text stored in a array when designating :raw for the argument of method 'gt.'
|
101
|
+
# see Xyml_element module for 'gt' method
|
102
|
+
#
|
103
|
+
# === (3.3) テキストノード
|
104
|
+
#
|
105
|
+
# テキストは、親エレメントの配列に直接格納されるスカラーに対応する。
|
106
|
+
#
|
107
|
+
# 2つ以上のスカラーが配列内にある場合、エレメントの'gt'メソッドが呼び出された際に、それらは結合
|
108
|
+
# される。'gt'メソッドの引数に:rawを指定すると、配列に格納された分かち書きのテキストが得られる。
|
109
|
+
# (メソッド'gt'については、Xyml_elementモジュールを参照のこと)
|
110
|
+
#
|
111
|
+
# +--XML--------------------+ +--XYML-------+ '-'(hyphon) before 'TTT'
|
112
|
+
# | <...>TTT<...> | | - TTT | stands for a part of array
|
113
|
+
# | | | | that belongs to the parent
|
114
|
+
# +-------------------------+ +-------------+ element.
|
115
|
+
#
|
116
|
+
#
|
117
|
+
#
|
118
|
+
# ==(4) XYML module
|
119
|
+
# Xyml module has the following functions:
|
120
|
+
# * loads a XYML file to an instance of Xyml::Document, saves an instance of Xyml::Document to a XYML file.
|
121
|
+
# * loads an XML subset file to an instance of Xyml::Document, saves an instance of Xyml::Document to an XML file.
|
122
|
+
# * saves an instance of Xyml::Document to a JSON file.(You can load a JSON file as XYML file, because JSON is included in YAML as its flow style.)
|
123
|
+
# * converts an instance of Xyml::Document to an instance of REXML::Document and vice versa. Note an instance of REXML::Document in this case supports a subset of XML specifications, not full set.
|
124
|
+
# Instance methods of Xyml::Document class deal with only accesses to instance variables. Concrete procedures are written in Xyml module methods.
|
125
|
+
# In the figure below, Xyml module method names are enclosed in square brackets("[]").
|
126
|
+
#
|
127
|
+
# ==(4) XYMLモジュール
|
128
|
+
# 提案するファイル形式XYMLについて、Xymlモジュールは次の機能を持つ。
|
129
|
+
# * Xyml::Documentクラスのインスタンスとして、XYMLファイルをロード/出力する。
|
130
|
+
# * Xyml::Documentクラスのインスタンスとして、XMLサブセットのファイルをロード/出力する。
|
131
|
+
# * Xyml::Documentクラスのインスタンスとして、JSONファイルを出力する(JSONはYAMLのフロースタイルなので、入力はXYMLファイルとして行える)。
|
132
|
+
# * Xyml::DocumentクラスのインスタンスとREXML::Documentのインスタンスとの相互変換を行う(但し、REXML::Documentは仕様のフルセットでなく、サブセットに対応)。
|
133
|
+
# Xyml::Documentクラスのメソッドは、インスタンス変数に関わる処理のみを行い、具体的な処理はXymlモジュールメソッドに記述している。
|
134
|
+
# 下図中、モジュールメソッド名は"[]"(角型括弧)で囲んで表示している。
|
135
|
+
#
|
136
|
+
# +-------------------------+ load_XYML +------------------+
|
137
|
+
# | |[rawobj2element]| |
|
138
|
+
# | |<---------------| |
|
139
|
+
# | Xyml::Document | out_XYML | XYML file |
|
140
|
+
# | instance | [doc2file] |(YAML subset file)|
|
141
|
+
# | |--------------->| |
|
142
|
+
# | +-------------+ | +------------------+
|
143
|
+
# | | Raw Object | |
|
144
|
+
# | +-------------+ | out_JSON +------------------+
|
145
|
+
# | |--------------->| JSON subset file |
|
146
|
+
# +-------------------------+ +------------------+
|
147
|
+
# | | ^
|
148
|
+
# | to_domobj | |
|
149
|
+
# V [rawobj2domobj] | |[domboj2element]
|
150
|
+
# +-------------------|--|--+
|
151
|
+
# | | | | load_XML +------------------+
|
152
|
+
# | | +---<---------------| |
|
153
|
+
# | REXML::Document | | out_XML | XML subset file |
|
154
|
+
# | instance +--------------------->| |
|
155
|
+
# | | +------------------+
|
156
|
+
# +-------------------------+
|
157
|
+
#
|
158
|
+
#
|
159
|
+
# see also "Xyml_element module."
|
160
|
+
#
|
161
|
+
# 参考:Xyml_elementモジュール
|
162
|
+
#
|
163
|
+
module Xyml
|
164
|
+
|
165
|
+
# convert a tree composed of alternate hashes and arrays into a XYML element tree.
|
166
|
+
#
|
167
|
+
# ハッシュと配列とを交互に組み合わせたツリーを、XYMLエレメントのツリーに変換する。
|
168
|
+
# ==== Args
|
169
|
+
# _rawobj_ :: the root of a tree composed of alternate hashes and arrays
|
170
|
+
# ==== Return
|
171
|
+
# the root element of a created XYML element tree.
|
172
|
+
def self.rawobj2element rawobj
|
173
|
+
temp_root=Xyml::Element.new :tempRoot
|
174
|
+
Xyml.rawobj2element_rcsv rawobj,temp_root
|
175
|
+
temp_root[:tempRoot][0]._sp(:_iamroot)
|
176
|
+
temp_root[:tempRoot][0]
|
177
|
+
end
|
178
|
+
|
179
|
+
# convert a tree composed of alternate hashes and arrays into XML strings.
|
180
|
+
# note that a XYML element tree is such a tree to be converted by this method.
|
181
|
+
#
|
182
|
+
# ハッシュと配列とを交互に組み合わせたツリーを、XMLの文字列に変換する。
|
183
|
+
# XYMLエレメントのツリーも、このメソッドにより変換されるツリーとなっていることに注意。
|
184
|
+
# ==== Args
|
185
|
+
# _rawobj_ :: the root of a tree composed of alternate hashes and arrays.
|
186
|
+
# ==== Return
|
187
|
+
# strings in XML.
|
188
|
+
def self.rawobj2xmlString rawobj
|
189
|
+
sio=StringIO.new
|
190
|
+
Xyml.rawobj2domobj(rawobj).write(sio)
|
191
|
+
sio.rewind
|
192
|
+
sio.read
|
193
|
+
end
|
194
|
+
|
195
|
+
# convert a tree composed of alternate hashes and arrays into a DOM object tree.
|
196
|
+
# note that a XYML element tree is such a tree that can be converted by this method.
|
197
|
+
#
|
198
|
+
# ハッシュと配列とを交互に組み合わせたツリーを、DOMオブジェクトのツリーに変換する。
|
199
|
+
# XYMLエレメントのツリーも、このメソッドにより変換されるツリーとなっていることに注意。
|
200
|
+
# ==== Args
|
201
|
+
# _rawobj_ :: the root of a tree composed of alternate hashes and arrays.
|
202
|
+
#
|
203
|
+
# ==== Return
|
204
|
+
# an instance of REXML::Document.
|
205
|
+
def self.rawobj2domobj rawobj
|
206
|
+
dom = REXML::Document.new <<EOS
|
207
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
208
|
+
EOS
|
209
|
+
Xyml.rawobj2domobj_rcsv rawobj,dom
|
210
|
+
end
|
211
|
+
|
212
|
+
# extend each hash in a tree composed of alternate hashes and arrays to a XYML element, and
|
213
|
+
# obtain a XYML element tree. This method is similar to _rawobj2element_ method except that _extend_element_
|
214
|
+
# does not create new hashes and arrays. In order to apply this method to a tree,
|
215
|
+
# all hashes in that tree must use symbols as hash keys.
|
216
|
+
#
|
217
|
+
# ハッシュと配列とを交互に組み合わせたツリー中のハッシュをXYMLエレメントに拡張し、
|
218
|
+
# XYMLエレメントツリーを得る。このメソッドは、 _rawobj2element_と似ているが、新たにハッシュと配列を
|
219
|
+
# 生成しない点が異なっている。このメソッドを適用するツリーでは、ハッシュのキーはすべてシンボルで
|
220
|
+
# なければならない。
|
221
|
+
# ==== Args
|
222
|
+
# _rawobj_ :: the root of a tree composed of alternate hashes and arrays
|
223
|
+
# ==== Return
|
224
|
+
# the root element of a created XYML element tree, which is identical to _rawobj_ in the input argument.
|
225
|
+
def self.extend_element rawobj
|
226
|
+
Xyml.extend_element_rcsv rawobj,nil
|
227
|
+
end
|
228
|
+
|
229
|
+
# convert a DOM object tree into a XYML element tree.
|
230
|
+
#
|
231
|
+
# DOMオブジェクトのツリーをXYMLエレメントのツリーに変換する。
|
232
|
+
# ==== Args
|
233
|
+
# _domobj_ :: an instance of REXML::Document.
|
234
|
+
# ==== Return
|
235
|
+
# the root element of a created XYML element tree.
|
236
|
+
#
|
237
|
+
# 生成されたXYMLエレメントツリーのルートエレメント
|
238
|
+
def self.domobj2element domobj
|
239
|
+
temproot=Hash.new
|
240
|
+
temproot.extend Xyml_element
|
241
|
+
Xyml.domobj2element_rcsv domobj,temproot,nil
|
242
|
+
end
|
243
|
+
|
244
|
+
# print out a XYML element tree to a XYML file.
|
245
|
+
#
|
246
|
+
# XYMLエレメントのツリーをXYMLファイルとしてプリントアウトする。
|
247
|
+
# ==== Args
|
248
|
+
# _doc_ :: an instance of Xyml::Document.
|
249
|
+
# _io_ :: output IO.
|
250
|
+
def self.doc2file doc,io
|
251
|
+
io.print "---\n"
|
252
|
+
Xyml.doc2file_rcsv(doc,0,io)
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
# Indent used in a YAML file. Two spaces.
|
257
|
+
#
|
258
|
+
# YAMLファイルとしてのインデント。スペース2個。
|
259
|
+
Indent=' '
|
260
|
+
|
261
|
+
# '- ' : String for sequence(Array) entry in a YAML file.
|
262
|
+
#
|
263
|
+
# '- ' : YAMLファイルのシーケンス(配列)要素を表す文字列
|
264
|
+
SequenceEntry='- '
|
265
|
+
|
266
|
+
# ': ' : String for mapping(hash) value in a YAML file.
|
267
|
+
#
|
268
|
+
# ': ' : YAMLファイルのマッピング(ハッシュ)の値を表す文字列
|
269
|
+
MappingValue=': '
|
270
|
+
|
271
|
+
# '| ' : String for literal block in a YAML file.
|
272
|
+
#
|
273
|
+
# '| ' : YAMLファイルのリテラルブロックを表す文字列
|
274
|
+
LiteralBlock='| '
|
275
|
+
|
276
|
+
# Xyml::Element class implement the element object in XYML tree data. See Xyml_element module
|
277
|
+
# for more detaled specifications.
|
278
|
+
#
|
279
|
+
# Xyml::Elementクラスは、XYMLツリーデータ中のエレメントを実装するクラスである。
|
280
|
+
# 詳細については、Xyml_elementモジュール参照。
|
281
|
+
class Element < Hash
|
282
|
+
include Xyml_element
|
283
|
+
# create an instance of Xyml::Element class.
|
284
|
+
#
|
285
|
+
# Xyml::Elementクラスのインスタンスを生成する。
|
286
|
+
# ==== Args
|
287
|
+
# _name_ :: Element name.
|
288
|
+
#
|
289
|
+
# _name_ :: エレメント名
|
290
|
+
def initialize name
|
291
|
+
name=name.intern unless name.is_a?(Symbol)
|
292
|
+
self[name]=Array.new
|
293
|
+
self
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# Xyml::Document class implements the online data loaded from a XYML file.
|
298
|
+
# Because XYML is a subset of XML from the viewpoint of data structure, the data in this class
|
299
|
+
# is a tree composed of elements, attributes and texts. I call this tree "XYML element tree."
|
300
|
+
# The tree data in this class is composed of alternate hashes and arrays, in the same way of
|
301
|
+
# XYML files. See "Xyml module" for the mapping between XYML and XML.
|
302
|
+
#
|
303
|
+
# Xyml::Documentクラスは、XYMLファイルを読みだしたオンライン上のデータを実装するクラスである。
|
304
|
+
# XYMLファイルはデータ構造としてはXMLのサブセットであるため、Xyml::Documentクラスの保持する
|
305
|
+
# データは、エレメント・属性・テキストからなるツリーである。これを、XYMLエレメントツリーと呼ぶこととする。
|
306
|
+
# XYMLファイルフォーマットと同様に、このクラスによるツリーも、ハッシュと配列との交互の組み合わせ
|
307
|
+
# で実現されている。XYMLとXMLとの対応付けについては、"XYMLモジュール"を参照のこと。
|
308
|
+
# +-------------------------+ load_XYML +------------------+
|
309
|
+
# | |<-----------| |
|
310
|
+
# | Xyml::Document | out_XYML | XYML file |
|
311
|
+
# | instance |----------->|(YAML subset file)|
|
312
|
+
# | +-------------+ | +------------------+
|
313
|
+
# | | Raw Object | |
|
314
|
+
# | +-------------+ | out_JSON +------------------+
|
315
|
+
# | |----------->| JSON subset file |
|
316
|
+
# +-------------------------+ +------------------+
|
317
|
+
# | | ^
|
318
|
+
# | to_domobj | |
|
319
|
+
# V | |
|
320
|
+
# +-------------------|--|--+
|
321
|
+
# | | | | load_XML +------------------+
|
322
|
+
# | | +---<----------| |
|
323
|
+
# | REXML::Document | | out_XML | XML subset file |
|
324
|
+
# | instance +---------------->| |
|
325
|
+
# | | +------------------+
|
326
|
+
# +-------------------------+
|
327
|
+
class Document < Array
|
328
|
+
|
329
|
+
# the root of the XYML element tree. This root element is a hash extended by "Xyml_element module,"
|
330
|
+
# as all other XYML elements in the tree are also such hashes. The idential element to "@root" is stored
|
331
|
+
# in the begining of the array that this class inherites. Threrefore "@root" and "self.at(0)" stand
|
332
|
+
# for the same object. @root is provided for accessibility.
|
333
|
+
#
|
334
|
+
# XYMLエレメントツリーのルート。ツリー中の他のエレメントと同じく、このルートエレメントは
|
335
|
+
# "xyml_elementモジュール"により拡張されたハッシュである。@rootと同一のエレメントは、このクラスが
|
336
|
+
# 継承する配列の先頭にも格納されている。つまり、"@root"と"self.at(0)"とは同じオブジェクトを指す。
|
337
|
+
# "@root"は、アクセスしやすいように設けたものである。
|
338
|
+
attr_reader :root
|
339
|
+
|
340
|
+
# create an instance of Xyml::Document.
|
341
|
+
#
|
342
|
+
# Xyml::Documentのインスタンスを生成する。
|
343
|
+
# ==== Args
|
344
|
+
# if first argument in *_argv_ is designated:
|
345
|
+
#
|
346
|
+
# *_argv_の第一要素が指定されている場合:
|
347
|
+
# - case of a symbol
|
348
|
+
# - シンボルの場合
|
349
|
+
# - create an instance composed of only a root element such that the name of the root elemnemt is the first argument
|
350
|
+
# - ルート要素のみからなるインスタンスを生成。ルート要素の名前が、argvの第一要素となる。
|
351
|
+
#
|
352
|
+
# xyml_tree=Xyml::Document.new(:a)
|
353
|
+
# #-> [{a:[]}]
|
354
|
+
#
|
355
|
+
# - case of an IO instance
|
356
|
+
# - IOインスタンスの場合
|
357
|
+
# - create an instance corresponding to the XYML file loaded through the IO. note that only XYML file can be loaded, not XML.(use load_XML method to load an XML file.)
|
358
|
+
# - IOを通してロードしたXYMLファイルに対応したインスタンスを生成する。XYMLファイルのみが指定可能であり、XMLは不可であることに注意。(XMLファイルをロードする場合は、load_XMLメソッドを使用)
|
359
|
+
# # aaa.xyml
|
360
|
+
# # - a:
|
361
|
+
# # -b: ccc
|
362
|
+
# # -d:
|
363
|
+
# # - eee
|
364
|
+
# xyml_tree=Xyml::Document.new(File.open("aaa.xyml"))
|
365
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
366
|
+
#
|
367
|
+
# - case of a tree composed of alternate hashes and arrays.
|
368
|
+
# - 交互になったハッシュと配列とにより構成したツリーの場合
|
369
|
+
# - create an instance reflecting a input tree.
|
370
|
+
# - 入力引数のツリーを反映したインスタンスを生成。
|
371
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee"]}]})
|
372
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
373
|
+
# xyml_tree.out_XYML(File.open("aaa.xyml","w"))
|
374
|
+
# #-> aaa.xyml
|
375
|
+
# # - a:
|
376
|
+
# # -b: ccc
|
377
|
+
# # -d:
|
378
|
+
# # - eee
|
379
|
+
def initialize *argv
|
380
|
+
if argv.size==1
|
381
|
+
if argv[0].is_a?(Symbol)
|
382
|
+
@root=Xyml::Element.new argv[0]
|
383
|
+
self.push @root
|
384
|
+
@root._sp(:_iamroot)
|
385
|
+
elsif argv[0].is_a?(IO)
|
386
|
+
raw_yaml=YAML.load(argv[0])
|
387
|
+
@root=Xyml.rawobj2element raw_yaml[0]
|
388
|
+
self.clear.push @root
|
389
|
+
@root._sp(:_iamroot)
|
390
|
+
elsif argv[0].is_a?(Hash)
|
391
|
+
@root=Xyml.rawobj2element argv[0]
|
392
|
+
self.clear.push @root
|
393
|
+
@root._sp(:_iamroot)
|
394
|
+
end
|
395
|
+
elsif argv.size>1
|
396
|
+
raise "tried to create Xyml::Document with more than one parameters."
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# load an XML file through the designated IO and set the tree data in the file to the self.
|
401
|
+
#
|
402
|
+
# XMLファイルをIOよりロードして、そのツリーデータを自身に設定する。
|
403
|
+
# # aaa.xml
|
404
|
+
# # <a b="ccc">
|
405
|
+
# # <d>eee</d>
|
406
|
+
# # </a>
|
407
|
+
# xyml_tree=Xyml::Document.new
|
408
|
+
# xyml_tree.load_XML(File.open("aaa.xml"))
|
409
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
410
|
+
def load_XML io
|
411
|
+
xml=REXML::Document.new(io)
|
412
|
+
@root=Xyml.domobj2element xml.root
|
413
|
+
self.clear.push @root
|
414
|
+
@root._sp(:_iamroot)
|
415
|
+
io.close
|
416
|
+
end
|
417
|
+
|
418
|
+
# save an XML file corresponding to the tree data in the self through the designated IO.
|
419
|
+
#
|
420
|
+
# 自身のツリーデータを、指定されたIOを通して、XMLファイルに保存する。
|
421
|
+
# ==== Args
|
422
|
+
# _indent_(if not nil) :: a saved XML file is formatted with the designaged indent.
|
423
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee"]}]})
|
424
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
425
|
+
# xyml_tree.out_XML(File.open("aaa.xml","w"))
|
426
|
+
# #-> aaa.xml
|
427
|
+
# # <a b="ccc">
|
428
|
+
# # <d>eee</d>
|
429
|
+
# # </a>
|
430
|
+
def out_XML io,indent=nil
|
431
|
+
|
432
|
+
if indent
|
433
|
+
Xyml.rawobj2domobj(@root).write(io,indent.to_i)
|
434
|
+
else
|
435
|
+
sio=StringIO.new
|
436
|
+
Xyml.rawobj2domobj(@root).write(sio)
|
437
|
+
sio.rewind
|
438
|
+
io.print sio.read,"\n"
|
439
|
+
end
|
440
|
+
io.close
|
441
|
+
end
|
442
|
+
|
443
|
+
|
444
|
+
# save a XYML file corresponding to the tree data in the self through the designated IO.
|
445
|
+
#
|
446
|
+
# 自身のツリーデータを、指定されたIOを通して、XYMLファイルに保存する。
|
447
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee","fff"]}]})
|
448
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee","fff"]}]}]
|
449
|
+
# xyml_tree.out_XYML(File.open("aaa.xyml","w"))
|
450
|
+
# #-> aaa.xyml
|
451
|
+
# # - a:
|
452
|
+
# # -b: ccc
|
453
|
+
# # -d:
|
454
|
+
# # - eee
|
455
|
+
# # - fff
|
456
|
+
def out_XYML io
|
457
|
+
Xyml.doc2file(self,io)
|
458
|
+
io.close
|
459
|
+
end
|
460
|
+
|
461
|
+
# save a XYML file corresponding to the tree data in the self through the designated IO,
|
462
|
+
# in the way that a saved XYML file is in the "standard syle."
|
463
|
+
# For example, a XYML file has no redandant partitions in texts in the "standard style."
|
464
|
+
# Two XYML files can be compared presicely if they are in the standard style.
|
465
|
+
#
|
466
|
+
# 自身のツリーデータを、指定されたIOを通して、"標準スタイル"で、XYMLファイルに保存する。
|
467
|
+
# 例えば、"標準スタイル"ではXYMLファイル内で冗長なテキストの分かち書きを行わない。
|
468
|
+
# 標準スタイルであれば、2つのファイルを正確に比較することが可能となる。
|
469
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee","fff"]}]})
|
470
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee","fff"]}]}]
|
471
|
+
# xyml_tree.out_XYML(File.open("aaa.xyml","w"))
|
472
|
+
# #-> aaa.xyml
|
473
|
+
# # - a:
|
474
|
+
# # -b: ccc
|
475
|
+
# # -d:
|
476
|
+
# # - eeefff
|
477
|
+
def out_XYML_standard io
|
478
|
+
io.print "---\n"
|
479
|
+
Xyml.out_xyml_rcsv_std(self,0,io)
|
480
|
+
io.close
|
481
|
+
end
|
482
|
+
|
483
|
+
|
484
|
+
# load an XYML file through the designated IO and set the tree data in the file to the self.
|
485
|
+
#
|
486
|
+
# XYMLファイルをIOよりロードして、そのツリーデータを自身に設定する。
|
487
|
+
# # aaa.xyml
|
488
|
+
# # - a:
|
489
|
+
# # -b: ccc
|
490
|
+
# # -d:
|
491
|
+
# # - eee
|
492
|
+
# xyml_tree=Xyml::Document.new
|
493
|
+
# xyml_tree.load_XYML(File.open("aaa.xyml"))
|
494
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
495
|
+
def load_XYML io
|
496
|
+
raw_yaml=YAML.load(io)
|
497
|
+
@root=Xyml.rawobj2element raw_yaml[0]
|
498
|
+
self.clear.push @root
|
499
|
+
io.close
|
500
|
+
end
|
501
|
+
|
502
|
+
# save a JSON file corresponding to the tree data in the self through the designated IO.
|
503
|
+
# Note that a JSON file can be loaded by load_XYML method because JSON is a part of YAML.
|
504
|
+
#
|
505
|
+
# 自身のツリーデータを、指定されたIOを通して、JSONファイルに保存する。JSONファイルのロードは、
|
506
|
+
# _load_XYML_メソッドで実施できることに注意(JSONはYAML仕様の一部分となっているため)。
|
507
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee"]}]})
|
508
|
+
# #-> [{a: [{b: "ccc"},{d: ["eee"]}]}]
|
509
|
+
# xyml_tree.out_JSON(File.open("aaa.json","w"))
|
510
|
+
# #-> aaa.jdon
|
511
|
+
# # [{"a":[{"b":"ccc"},{"d":["eee"]}]}]
|
512
|
+
def out_JSON io
|
513
|
+
serialized=JSON.generate(Xyml.remove_parent_rcsv(self))
|
514
|
+
io.print serialized
|
515
|
+
io.close
|
516
|
+
end
|
517
|
+
|
518
|
+
# convert the tree data in the self into a REXML::Document instance.
|
519
|
+
#
|
520
|
+
# 自身のツリーデータを、REXML::Documentインスタンスに変換する。
|
521
|
+
# ==== Return
|
522
|
+
# a REXML::Document instance.
|
523
|
+
# xyml_tree=Xyml::Document.new({a: [{b: "ccc"},{d: ["eee"]}]})
|
524
|
+
# REXML::Document rexml_tree=xyml_tree.to_domobj
|
525
|
+
def to_domobj
|
526
|
+
Xyml.rawobj2domobj(@root)
|
527
|
+
end
|
528
|
+
|
529
|
+
end # end of Xyml::Document
|
530
|
+
|
531
|
+
private
|
532
|
+
|
533
|
+
def self.rawobj2domobj_rcsv obj,dom
|
534
|
+
if obj.is_a?(Hash)
|
535
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with no pairs)." if obj.length==0
|
536
|
+
raise "loaded XYML document is illegal(ruby object contains a hash where second key is not ':_parent' or ':__parent'). second key=#{obj.keys[1]}" if obj.length>1 && (obj.keys[1]!=:_parent && obj.keys[1]!=:__parent)
|
537
|
+
key=obj.keys[0]
|
538
|
+
value=obj[key]
|
539
|
+
if value.is_a?(Array)
|
540
|
+
elm=REXML::Element::new("#{key}")
|
541
|
+
dom.add_element(elm)
|
542
|
+
if value.length==0
|
543
|
+
return
|
544
|
+
end
|
545
|
+
step=:s0_attribute
|
546
|
+
value.each do |tobj|
|
547
|
+
case step
|
548
|
+
|
549
|
+
when :s0_attribute
|
550
|
+
if tobj.is_a?(Hash)
|
551
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with no pairs) parent=#{key}." if tobj.length==0
|
552
|
+
raise "loaded XYML document is illegal(ruby object contains a hash where second key is not 'parent'). second key=#{tobj.keys[1]}" if tobj.length>1 && (tobj.keys[1]!=:_parent && tobj.keys[1]!=:__parent)
|
553
|
+
#puts "class=#{tobj.values[0].class}, to_s=#{tobj.values[0].to_s}"
|
554
|
+
if !tobj.values[0].is_a?(Array) && !tobj.values[0].is_a?(Hash)
|
555
|
+
elm.attributes["#{tobj.keys[0].to_s}"]="#{tobj.values[0].to_s}"
|
556
|
+
else
|
557
|
+
step=:s1_others
|
558
|
+
redo
|
559
|
+
end
|
560
|
+
else
|
561
|
+
step=:s1_others
|
562
|
+
redo
|
563
|
+
end
|
564
|
+
|
565
|
+
when :s1_others
|
566
|
+
if tobj.is_a?(Hash)
|
567
|
+
rawobj2domobj_rcsv tobj,elm
|
568
|
+
elsif tobj.is_a?(Array)
|
569
|
+
else
|
570
|
+
elm.add_text(tobj.to_s)
|
571
|
+
end
|
572
|
+
|
573
|
+
else
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|
577
|
+
elsif obj.is_a?(Array)
|
578
|
+
raise "loaded XYML document is illegal(Array apear on the top)."
|
579
|
+
end
|
580
|
+
dom
|
581
|
+
end
|
582
|
+
|
583
|
+
|
584
|
+
def self.rawobj2element_rcsv(raw_obj,node)
|
585
|
+
if raw_obj.is_a?(Hash)
|
586
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with no pairs)." if raw_obj.length==0
|
587
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with more than one pair). first key=#{obj.keys[0]}" if raw_obj.length>1
|
588
|
+
key=raw_obj.keys[0]
|
589
|
+
value=raw_obj[key]
|
590
|
+
if value.is_a?(Array)
|
591
|
+
elm=Xyml::Element.new("#{key}")
|
592
|
+
node.ac elm
|
593
|
+
if value.length==0
|
594
|
+
return
|
595
|
+
end
|
596
|
+
step=:s0_attribute
|
597
|
+
value.each do |tobj|
|
598
|
+
case step
|
599
|
+
when :s0_attribute
|
600
|
+
if tobj.is_a?(Hash)
|
601
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with no pairs) parent=#{key}." if tobj.length==0
|
602
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with more than one pair). first key=#{tobj.keys[0]}" if tobj.length>1
|
603
|
+
if !tobj.values[0].is_a?(Array) && !tobj.values[0].is_a?(Hash)
|
604
|
+
elm.sa tobj.keys[0].to_s.intern,tobj.values[0].to_s
|
605
|
+
else
|
606
|
+
step=:s1_others
|
607
|
+
redo
|
608
|
+
end
|
609
|
+
else
|
610
|
+
step=:s1_others
|
611
|
+
redo
|
612
|
+
end
|
613
|
+
|
614
|
+
when :s1_others
|
615
|
+
if tobj.is_a?(Hash)
|
616
|
+
rawobj2element_rcsv tobj,elm
|
617
|
+
elsif tobj.is_a?(Array)
|
618
|
+
else
|
619
|
+
elm.at tobj.to_s unless tobj.to_s.empty?
|
620
|
+
end
|
621
|
+
|
622
|
+
else
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
elsif raw_obj.is_a?(Array)
|
627
|
+
raise "loaded XYML document is illegal(Array apear on the top)."
|
628
|
+
end
|
629
|
+
node
|
630
|
+
end
|
631
|
+
|
632
|
+
def self.extend_element_rcsv obj,parent
|
633
|
+
if obj.is_a?(Hash)
|
634
|
+
raise "ruby object is illegal(ruby object contains a hash with no pairs)." if obj.length==0
|
635
|
+
raise "ruby object is illegal(ruby object contains a hash with more than one pair). first key=#{obj.keys[0]}" if obj.length>1
|
636
|
+
raise "ruby hash has a key that is not a symbol. keys[0]=#{obj.keys[0]}" unless obj.keys[0].is_a?(Symbol)
|
637
|
+
value=obj[obj.keys[0]]
|
638
|
+
if value.is_a?(Array)
|
639
|
+
value.delete(nil)
|
640
|
+
obj.extend Xyml_element
|
641
|
+
obj._sp(parent)
|
642
|
+
if value.length==0
|
643
|
+
return
|
644
|
+
end
|
645
|
+
step=:s0_attribute
|
646
|
+
value.each do |tobj|
|
647
|
+
case step
|
648
|
+
when :s0_attribute
|
649
|
+
if tobj.is_a?(Hash)
|
650
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with no pairs) parent=#{key}." if tobj.length==0
|
651
|
+
raise "loaded XYML document is illegal(ruby object contains a hash with more than one pair). first key=#{tobj.keys[0]}" if tobj.length>1
|
652
|
+
if !tobj.values[0].is_a?(Array) && !tobj.values[0].is_a?(Hash)
|
653
|
+
raise "ruby hash has a key that is not a symbol. keys[0]=#{tobj.keys[0]}" unless tobj.keys[0].is_a?(Symbol)
|
654
|
+
else
|
655
|
+
step=:s1_others
|
656
|
+
redo
|
657
|
+
end
|
658
|
+
else
|
659
|
+
step=:s1_others
|
660
|
+
redo
|
661
|
+
end
|
662
|
+
|
663
|
+
when :s1_others
|
664
|
+
if tobj.is_a?(Hash)
|
665
|
+
extend_element_rcsv tobj,obj
|
666
|
+
elsif tobj.is_a?(Array)
|
667
|
+
else
|
668
|
+
end
|
669
|
+
|
670
|
+
else
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end
|
674
|
+
elsif obj.is_a?(Array)
|
675
|
+
raise "ruby object is illegal(Array apear on the top)."
|
676
|
+
end
|
677
|
+
obj
|
678
|
+
end
|
679
|
+
|
680
|
+
def self.domobj2element_rcsv elm,robj,parent
|
681
|
+
if elm.is_a?(REXML::Element)
|
682
|
+
elmArray=Array.new
|
683
|
+
robj[elm.expanded_name.to_sym]=elmArray
|
684
|
+
robj._sp(parent)
|
685
|
+
#p "#D#xyml.rb:domobj2element_rcsv:robj:";pp robj
|
686
|
+
if elm.has_attributes?
|
687
|
+
elm.attributes.each do |key,value|
|
688
|
+
attrHash=Hash.new
|
689
|
+
attrHash[key.to_sym]=value
|
690
|
+
elmArray.push(attrHash)
|
691
|
+
end
|
692
|
+
end
|
693
|
+
elm.each do |node|
|
694
|
+
if node.is_a?(REXML::Element)
|
695
|
+
elmHash=Hash.new
|
696
|
+
elmHash.extend Xyml_element
|
697
|
+
domobj2element_rcsv(node,elmHash,robj)
|
698
|
+
elmArray.push(elmHash)
|
699
|
+
elsif node.is_a?(REXML::Text)
|
700
|
+
text=node.to_s.gsub('<','<').gsub('>','>').gsub(''','\'').gsub('"','"').gsub('&','&')
|
701
|
+
elmArray.push(text) if text.length!=0
|
702
|
+
else
|
703
|
+
end
|
704
|
+
end
|
705
|
+
end
|
706
|
+
robj
|
707
|
+
end
|
708
|
+
|
709
|
+
def self.doc2file_rcsv obj, nest, io
|
710
|
+
if obj.is_a?(Hash)
|
711
|
+
key=obj.keys[0]
|
712
|
+
value=obj.values[0]
|
713
|
+
if value.is_a?(Array)
|
714
|
+
io.print(Indent*nest,SequenceEntry,key.to_s.strip,":\n")
|
715
|
+
Xyml.doc2file_rcsv(value,nest+1,io)
|
716
|
+
else
|
717
|
+
io.print(Indent*nest,SequenceEntry, key.to_s.strip,MappingValue,Xyml.escaped_line(value.to_s),"\n")
|
718
|
+
end
|
719
|
+
elsif obj.is_a?(Array)
|
720
|
+
obj.each do |value|
|
721
|
+
if value.is_a?(Hash)
|
722
|
+
doc2file_rcsv(value,nest,io,)
|
723
|
+
elsif value.is_a?(Array)
|
724
|
+
else
|
725
|
+
io.print(Indent*nest, SequenceEntry, escaped_line(value.to_s),"\n")
|
726
|
+
end
|
727
|
+
end
|
728
|
+
if obj.length==0
|
729
|
+
io.print(Indent*nest,SequenceEntry, "\n")
|
730
|
+
end
|
731
|
+
else
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
def self.escaped_line(str)
|
736
|
+
escape_needed=false
|
737
|
+
if str.match(/\"|[:]\s|\s[#]|\A[,\[\]\{\}#&\*\!\|\>\<\%\s\@:'`]|\A[\?:-]\z|[:]\z|\n/)
|
738
|
+
"\""+str.gsub(/\\/,"\\\\\\\\").gsub(/\n/,"\\n").gsub(/\f/,"\\f").gsub(/\"/,'\"')+"\""
|
739
|
+
else
|
740
|
+
str
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
def self.out_xyml_rcsv_std obj, nest, io
|
745
|
+
if obj.is_a?(Hash)
|
746
|
+
key=obj.keys[0]
|
747
|
+
value=obj[key]
|
748
|
+
if value.is_a?(Array)
|
749
|
+
io.print(Indent*nest,SequenceEntry,key.to_s.strip,":\n")
|
750
|
+
out_xyml_rcsv_std(value,nest+1,io)
|
751
|
+
else
|
752
|
+
io.print(Indent*nest,SequenceEntry, key.to_s.strip,MappingValue,value.to_s.strip,"\n")
|
753
|
+
end
|
754
|
+
elsif obj.is_a?(Array)
|
755
|
+
unseparatedString=""
|
756
|
+
obj.each do |value|
|
757
|
+
if value.is_a?(Hash)
|
758
|
+
if unseparatedString.length!=00
|
759
|
+
io.print(Indent*nest, SequenceEntry, Xyml.escaped_line(unseparatedString), "\n")
|
760
|
+
unseparatedString="";
|
761
|
+
end
|
762
|
+
Xyml.out_xyml_rcsv_std(value,nest,io,)
|
763
|
+
elsif value.is_a?(Array)
|
764
|
+
else
|
765
|
+
unseparatedString+=value.to_s
|
766
|
+
end
|
767
|
+
end
|
768
|
+
if unseparatedString.length!=0
|
769
|
+
io.print(Indent*nest, SequenceEntry, escaped_line(unseparatedString),"\n")
|
770
|
+
unseparatedString="";
|
771
|
+
end
|
772
|
+
if obj.length==0
|
773
|
+
io.print(Indent*nest,SequenceEntry, "\n")
|
774
|
+
end
|
775
|
+
else
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
|
780
|
+
def self.remove_parent_rcsv elmArray
|
781
|
+
raise "something wrong when removing parent information from objects. elmArray=#{elmArray.inspect}" unless elmArray.is_a?(Array)
|
782
|
+
elmArray.each do |obj|
|
783
|
+
if(obj.is_a?(Hash))
|
784
|
+
if(obj.values[0].is_a?(Array))
|
785
|
+
obj._dp
|
786
|
+
remove_parent_rcsv obj.values[0]
|
787
|
+
end
|
788
|
+
end
|
789
|
+
end
|
790
|
+
elmArray
|
791
|
+
end
|
792
|
+
|
793
|
+
def self.dbg_dom_print_rcsv elem,nest
|
794
|
+
indent="||"
|
795
|
+
print "================================\n"
|
796
|
+
print indent*nest + "name : #{elem.name}\n"
|
797
|
+
attrs = elem.attributes
|
798
|
+
attrs.each{|a,e|
|
799
|
+
print indent*nest + "attr :#{a}=#{e}\n"
|
800
|
+
}
|
801
|
+
print indent*nest + "text : \n-->#{elem.text.to_s.gsub("\s",'_').gsub("\t",'\t')}<--\n"
|
802
|
+
|
803
|
+
elem.each do |node|
|
804
|
+
if node.is_a?(REXML::Element)
|
805
|
+
dbg_dom_print_rcsv node,nest+1
|
806
|
+
elsif node.is_a?(REXML::Text)
|
807
|
+
text=node.to_s.strip
|
808
|
+
print indent*nest + "textnode : \n-->#{text.gsub("\s",'_').gsub("\t",'\t')}<--\n"
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
|
813
|
+
if elem.has_elements? then
|
814
|
+
elem.each_element{|e|
|
815
|
+
dbg_dom_print_rcsv e,nest+1
|
816
|
+
}
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
|
821
|
+
end
|