ixyml 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|