eimxml 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/README ADDED
@@ -0,0 +1,58 @@
1
+ = Easy IMplemented XML
2
+ :lang:ja
3
+ Easy IMplemented XML(EimXML)は、RubyスクリプトからXMLを作成するためのライブラリです。
4
+ 動作が軽くなるように、単純さを心がけて実装しています。
5
+
6
+ :lang:en
7
+ Easy IMplemented XML(EimXML) is library to construct XML on Ruby.
8
+ For light weight performance, this library is implemented simply.
9
+
10
+ :lang:
11
+ = URLs
12
+ * Document(Japanese)[http://eimxml.rubyforge.org/ja/]
13
+ * Document(English)[http://eimxml.rubyforge.org/en/]
14
+ * MercurialRepository[https://hg.hinet.mydns.jp/eim_xml/]
15
+
16
+ = Sample
17
+ :lang:ja
18
+ 例えば、次のようなHTMLを作成する場合は
19
+
20
+ :lang:en
21
+ For example, to construct html like bellow
22
+
23
+ :lang:
24
+ <html>
25
+ <head>
26
+ <title>TITLE</title>
27
+ </head>
28
+ <body>
29
+ <p>Texts...</p>
30
+ </body>
31
+ </html>
32
+
33
+ :lang:ja
34
+ スクリプトは以下のように記述します。
35
+
36
+ :lang:en
37
+ write script like bellow.
38
+
39
+ :lang:
40
+ #!/usr/bin/ruby
41
+ # require "rubygems"
42
+ require "eim_xml/xhtml"
43
+
44
+ include EimXML::XHTML
45
+ html = HTML.new do |html|
46
+ html << Head.new do |head|
47
+ head << Title.new do |title|
48
+ title << "TITLE"
49
+ end
50
+ end
51
+ html << Body.new do |body|
52
+ body << P.new do |par|
53
+ par << "Text..."
54
+ end
55
+ end
56
+ end
57
+
58
+ html.write($stdout, false)
data/Rakefile ADDED
@@ -0,0 +1,94 @@
1
+ require "rake/clean"
2
+ require "rake/testtask"
3
+ require "rake/rdoctask"
4
+ require "rake/gempackagetask"
5
+
6
+ FILES = FileList["**/*"].exclude("pkg", "html")
7
+
8
+ task :default => :test
9
+
10
+ ### Document ###
11
+ RDOC_DIR = "./html/"
12
+ RDOC_OPTS = ["-S", "-w", "3", "-c", "UTF-8", "-m", "README"]
13
+ RDOC_OPTS << "-d" if ENV["DOT"]
14
+ RDOC_FILES = FileList["lib/**/*.rb"]
15
+ RDOC_EXTRAS = FileList["README"]
16
+ ["", "ja", "en"].each do |l|
17
+ dir = RDOC_DIR.dup
18
+ dir << "#{l}/" unless l.empty?
19
+ Rake::RDocTask.new("rdoc#{":"+l unless l.empty?}") do |rdoc|
20
+ rdoc.title = "Easy IMplemented XML"
21
+ rdoc.options = RDOC_OPTS.dup
22
+ rdoc.options << "-l" << l unless l.empty?
23
+ rdoc.rdoc_dir = dir
24
+ rdoc.rdoc_files.include(RDOC_FILES, RDOC_EXTRAS)
25
+ end
26
+ end
27
+ task "rdoc:all" => ["rdoc", "rdoc:ja", "rdoc:en"]
28
+ task "rerdoc:all" => ["rerdoc", "rerdoc:ja", "rerdoc:en"]
29
+
30
+
31
+ ### Publish document ###
32
+ task :publish => [:clobber_rdoc, "rdoc:ja", "rdoc:en"] do
33
+ require "rake/contrib/rubyforgepublisher"
34
+ cp "index.html", "html/index.html"
35
+ Rake::RubyForgePublisher.new("eimxml", "hiraku").upload
36
+ end
37
+
38
+ ### Test ###
39
+ task :test => "test:apart"
40
+ namespace :test do
41
+ FileList["test/*_test.rb"].sort{|a,b| File.mtime(a)<=>File.mtime(b)}.reverse.each do |i|
42
+ Rake::TestTask.new(:apart) do |t|
43
+ t.test_files = i
44
+ end
45
+ end
46
+ task(:apart).comment = "Run tests separately"
47
+
48
+ Rake::TestTask.new(:lump) do |t|
49
+ t.test_files = FileList["test/*_test.rb"]
50
+ end
51
+ task(:lump).comment = "Run all tests in a lump"
52
+ end
53
+
54
+ ### Build GEM ###
55
+ GEM_DIR = "./pkg"
56
+ directory GEM_DIR
57
+ def build_gem(unstable=false)
58
+ spec = Gem::Specification.new do |spec|
59
+ spec.name = "eimxml"
60
+ spec.rubyforge_project = "eimxml"
61
+ spec.version = "0.0.1"
62
+ spec.summary = "Easy IMplemented XML"
63
+ spec.author = "KURODA Hiraku"
64
+ spec.email = "hiraku@hinet.mydns.jp"
65
+ spec.homepage = "http://eimxml.rubyforge.org/"
66
+ spec.files = FILES
67
+ spec.test_files = Dir.glob("test/*.rb")
68
+ spec.has_rdoc = true
69
+ spec.rdoc_options = RDOC_OPTS.dup
70
+ spec.extra_rdoc_files = RDOC_EXTRAS
71
+ end
72
+
73
+ spec.version = spec.version.to_s << Time.now.strftime(".%Y.%m%d.%H%M") if unstable
74
+ b = Gem::Builder.new(spec)
75
+ gname = b.build
76
+ mv gname, "#{GEM_DIR}/"
77
+ end
78
+
79
+ desc "Build gem package"
80
+ task :gem => GEM_DIR do
81
+ build_gem
82
+ end
83
+
84
+ desc "Build unstable version gem package"
85
+ task "gem:unstable" do
86
+ build_gem(true)
87
+ end
88
+
89
+
90
+ ### Build package ###
91
+ package_task = Rake::PackageTask.new("eim_xml",ENV["VER"] || :noversion) do |t|
92
+ t.package_files.include(FILES)
93
+ t.need_tar_gz = true
94
+ end
@@ -0,0 +1,16 @@
1
+ require "eim_xml"
2
+
3
+ module EimXML::Assertions
4
+ def assert_has(expect, element, message="")
5
+ message << "\n" unless message.size==0
6
+ message << "<#{element}> doesn't have\n<#{expect.inspect}>"
7
+ assert_block(message) do
8
+ element.has?(expect)
9
+ end
10
+ rescue Test::Unit::AssertionFailedError=>e
11
+ bt = e.backtrace.find_all do |b|
12
+ b !~ /#{Regexp.escape(__FILE__)}/
13
+ end
14
+ raise Test::Unit::AssertionFailedError, e.message, bt
15
+ end
16
+ end
@@ -0,0 +1,99 @@
1
+ # XML parser for EimXML
2
+ #
3
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+ #
6
+
7
+ require "eim_xml"
8
+ require "strscan"
9
+
10
+ module EimXML
11
+ class ParseError < StandardError
12
+ end
13
+
14
+ class Parser
15
+ attr_reader :scanner
16
+ module RE
17
+ EMPTY_ELEMENT = /<([^>]*?)\/>/
18
+ START_TAG = /<([^>]*?([^\/>]\s*))>/
19
+ END_TAG = /<\/(\S+)\s*>/
20
+ ATTRIBUTE = /\s+([^=\s]+)\s*=\s*('(.*?)'|"(.*?)")/m
21
+ STRING = /[^<]+/
22
+ end
23
+
24
+ def initialize(src, *space_holders)
25
+ @scanner = StringScanner.new(src)
26
+ @space_holders = []
27
+ @space_holder_res = []
28
+ space_holders.each do |i|
29
+ if i.is_a?(Regexp)
30
+ @space_holder_res << i
31
+ else
32
+ @space_holders << i.to_sym
33
+ end
34
+ end
35
+ end
36
+
37
+ def parse(hold_space = false)
38
+ @scanner.scan(/\s+/) unless hold_space
39
+ if @scanner.scan(RE::EMPTY_ELEMENT)
40
+ parse_empty_element(hold_space)
41
+ elsif @scanner.scan(RE::START_TAG)
42
+ parse_start_tag(hold_space)
43
+ elsif @scanner.scan(RE::STRING)
44
+ parse_string(hold_space)
45
+ else
46
+ nil
47
+ end
48
+ end
49
+
50
+ def parse_tag
51
+ s = StringScanner.new(@scanner[1])
52
+ e = Element.new(s.scan(/\S+/))
53
+ e[s[1]] = s[3] ? s[3] : s[4] while s.scan(RE::ATTRIBUTE)
54
+ e
55
+ end
56
+ protected :parse_tag
57
+
58
+ def space_holder?(ename)
59
+ return true if @space_holders.include?(ename)
60
+ s = ename.to_s
61
+ @space_holder_res.each do |re|
62
+ return true if re=~s
63
+ end
64
+ false
65
+ end
66
+
67
+ def parse_empty_element(hold_space)
68
+ e = parse_tag
69
+ hold_space = space_holder?(e.name) unless hold_space
70
+ e.hold_space if hold_space
71
+ e
72
+ end
73
+ protected :parse_empty_element
74
+
75
+ def parse_start_tag(hold_space)
76
+ e = parse_tag
77
+ hold_space = space_holder?(e.name) unless hold_space
78
+
79
+ e.hold_space if hold_space
80
+ @scanner.scan(/\s*/) unless hold_space
81
+ until @scanner.scan(RE::END_TAG)
82
+ c = parse(hold_space)
83
+ raise ParseError.new("Syntax error.") unless c
84
+ e << c
85
+ @scanner.scan(/\s*/) unless hold_space
86
+ end
87
+ raise ParseError.new("End tag mismatched.") unless @scanner[1].to_sym==e.name
88
+ e
89
+ end
90
+ protected :parse_start_tag
91
+
92
+ def parse_string(hold_space)
93
+ s = @scanner[0]
94
+ s.strip! unless hold_space
95
+ PCString.new(s)
96
+ end
97
+ protected :parse_string
98
+ end
99
+ end
data/lib/eim_xml.rb ADDED
@@ -0,0 +1,235 @@
1
+ # Easy IMplementation of XML
2
+ #
3
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+ #
6
+
7
+ module EimXML
8
+ XML_DECLARATION = %[<?xml version="1.0"?>]
9
+
10
+ class PCString
11
+ attr_reader :encoded_string
12
+ alias to_s encoded_string
13
+
14
+ def self.encode(s)
15
+ s.gsub(/&\#?\w+;|[&\"\'<>]/) do |m|
16
+ case m
17
+ when /&\#?\w+;/
18
+ m
19
+ when "&"
20
+ "&amp;"
21
+ when '"'
22
+ "&quot;"
23
+ when "'"
24
+ "&apos;"
25
+ when "<"
26
+ "&lt;"
27
+ when ">"
28
+ "&gt;"
29
+ end
30
+ end
31
+ end
32
+
33
+ def initialize(s, encoded=false)
34
+ @encoded_string = encoded ? s : PCString.encode(s)
35
+ end
36
+
37
+ def ==(other)
38
+ @encoded_string==other.encoded_string
39
+ end
40
+ end
41
+
42
+ class SymbolKeyHash < Hash
43
+ def initialize(src=nil)
44
+ case src
45
+ when self.class
46
+ super(src)
47
+ when Hash
48
+ src.each_key do |k|
49
+ store(k, src[k])
50
+ end
51
+ end
52
+ end
53
+
54
+ def update(src)
55
+ src = self.class.new(src) unless src.is_a?(self.class)
56
+ super(src)
57
+ end
58
+ alias :merge! :update
59
+
60
+ def merge(src)
61
+ super(self.class.new(src))
62
+ end
63
+
64
+ def store(k, v)
65
+ super(k.to_sym, v)
66
+ end
67
+
68
+ alias :[]= :store
69
+ end
70
+
71
+ class Element
72
+ attr_reader :name, :attributes, :contents
73
+
74
+ NEST = " "
75
+
76
+ def initialize(name, attributes=nil)
77
+ @name = name.to_sym
78
+ @attributes = SymbolKeyHash.new
79
+ @contents = Array.new
80
+ @hold_space = false
81
+
82
+ @attributes.update(attributes) if attributes
83
+
84
+ yield(self) if block_given?
85
+ end
86
+
87
+ def name=(new_name)
88
+ @name = new_name.to_sym
89
+ end
90
+ protected :name=
91
+
92
+ def hold_space
93
+ @hold_space = true
94
+ self
95
+ end
96
+
97
+ def unhold_space
98
+ @hold_space = false
99
+ self
100
+ end
101
+
102
+ def hold_space?
103
+ @hold_space
104
+ end
105
+
106
+ def add(v)
107
+ case v
108
+ when nil
109
+ when Element, PCString
110
+ @contents << v
111
+ when Array
112
+ v.each{|i| self.add(i)}
113
+ else
114
+ @contents << v.to_s
115
+ end
116
+ self
117
+ end
118
+ alias << add
119
+
120
+ def write(dst=String.new, level=0, is_head=true)
121
+ nest = NEST*level
122
+ head = is_head ? nest : ""
123
+ lf = @hold_space ? "" : "\n"
124
+
125
+ attributes = ""
126
+ @attributes.each do |k, v|
127
+ v = k.to_s unless v
128
+ attributes << " #{k}='#{PCString===v ? v : PCString.encode(v)}'"
129
+ end
130
+
131
+ case @contents.size
132
+ when 0
133
+ dst << "#{head}<#{@name}#{attributes} />"
134
+ when 1
135
+ dst << "#{head}<#{@name}#{attributes}>"
136
+ write_content_to(dst, @contents[0], level, false)
137
+ dst << "</#{@name}>"
138
+ else
139
+ dst << "#{head}<#{@name}#{attributes}>#{lf}"
140
+ @contents.each {|i| write_content_to(dst, i, level+1, !@hold_space) << lf}
141
+ dst << "#{@hold_space ? "" : nest}</#{@name}>"
142
+ end
143
+ end
144
+ def to_s(*args)
145
+ args.unshift("")
146
+ write(*args)
147
+ end
148
+ alias :inspect :to_s
149
+
150
+ def write_content_to(dst, c, level, is_head)
151
+ return c.write(dst, level, is_head) if c.is_a?(Element)
152
+ dst << (is_head ? NEST*level : "") + (c.is_a?(PCString) ? c.to_s : PCString.encode(c))
153
+ end
154
+ private :write_content_to
155
+
156
+ def ==(xml)
157
+ return false unless xml.is_a?(Element)
158
+ (@name==xml.name && @attributes==xml.attributes && @contents==xml.contents && @hold_space==xml.hold_space?)
159
+ end
160
+
161
+ def add_attribute(key, value)
162
+ @attributes[key.to_sym] = value
163
+ end
164
+ alias []= add_attribute
165
+
166
+ def [](key)
167
+ if key.is_a?(Fixnum)
168
+ @contents[key]
169
+ else
170
+ @attributes[key.to_sym]
171
+ end
172
+ end
173
+
174
+ def del_attribute(key)
175
+ @attributes.delete(key.to_sym)
176
+ end
177
+
178
+ def match?(name, attrs=nil)
179
+ case name
180
+ when Module
181
+ return is_a?(name)
182
+ when Element
183
+ return match?(name.name, name.attributes)
184
+ when Array
185
+ return match?(name[0], name[1])
186
+ end
187
+
188
+ if name.is_a?(Regexp)
189
+ return false unless name=~@name.to_s
190
+ else
191
+ return false unless @name==name
192
+ end
193
+
194
+ (attrs||[]).all? do |k, v|
195
+ if k.is_a?(Regexp)
196
+ @attributes.any? do |sk, sv|
197
+ next false unless k===sk.to_s
198
+ v===sv
199
+ end
200
+ else
201
+ v===@attributes[k]
202
+ end
203
+ end
204
+ end
205
+ alias :=~ :match?
206
+
207
+ def has?(name, attrs=nil, find_deep=true)
208
+ return true if match?(name, attrs)
209
+ @contents.any? do |i|
210
+ if i.is_a?(Element)
211
+ if find_deep
212
+ i=~[name, attrs] || i.has?(name, attrs, find_deep)
213
+ else
214
+ i=~[name, attrs]
215
+ end
216
+ else
217
+ name.is_a?(Module) && i.is_a?(name)
218
+ end
219
+ end
220
+ end
221
+
222
+ def find(name, attrs=nil)
223
+ r = []
224
+ r << self if match?(name, attrs)
225
+ @contents.each do |i|
226
+ if i.is_a?(Element)
227
+ r.concat(i.find(name, attrs))
228
+ else
229
+ r << i if name.is_a?(Module) && i.is_a?(name)
230
+ end
231
+ end
232
+ r
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,29 @@
1
+ # Test for eim_xml/assertions.rb
2
+ #
3
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+
6
+ require "test/unit"
7
+ require "eim_xml/assertions"
8
+
9
+ class TC_EimXML_Assertions < Test::Unit::TestCase
10
+ include EimXML
11
+ include EimXML::Assertions
12
+
13
+ def test_assert_has
14
+ e = Element.new(:tag) do |e|
15
+ e <<= Element.new(:sub)
16
+ end
17
+
18
+ assert_nothing_raised do
19
+ assert_has(:sub, e)
20
+ end
21
+
22
+ a = assert_raises(Test::Unit::AssertionFailedError) do
23
+ assert_has(:no, e)
24
+ end
25
+ assert(!a.backtrace.any?{ |i|
26
+ i=~/eim_xml\/assertions\.rb/
27
+ })
28
+ end
29
+ end
@@ -0,0 +1,428 @@
1
+ # Test for eim_xml.rb
2
+ #
3
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+
6
+ require "test/unit"
7
+ require "eim_xml"
8
+
9
+ class TC_PCString < Test::Unit::TestCase
10
+ include EimXML
11
+
12
+ def test_encode
13
+ assert_equal("&lt;&gt;&quot;&apos;&amp;", PCString.encode("<>\"'&"))
14
+ assert_equal("&test;", PCString.encode("&test;"))
15
+ assert_equal("&\#0ax;", PCString.encode("&#0ax;"))
16
+ assert_equal("&amp;test", PCString.encode("&test"))
17
+ assert_equal("&amp;\#0ax", PCString.encode("&#0ax"))
18
+ end
19
+
20
+ def test_new
21
+ assert_equal("&amp;", PCString.new("&").encoded_string)
22
+ assert_equal("&", PCString.new("&", true).encoded_string)
23
+ end
24
+
25
+ def test_equal
26
+ p1 = PCString.new("str")
27
+ p2 = PCString.new("str")
28
+ assert_equal(p1, p2)
29
+ end
30
+ end
31
+
32
+ class TC_Element < Test::Unit::TestCase
33
+ include EimXML
34
+
35
+ class Dummy < Element
36
+ def chgname(name)
37
+ self.name = name
38
+ end
39
+ end
40
+
41
+ def test_name
42
+ e = Element.new("el")
43
+ assert_equal(:el, e.name)
44
+ assert_raises(NoMethodError){e.name="changed"}
45
+
46
+ d = Dummy.new("el1")
47
+ assert_equal(:el1, d.name)
48
+ d.chgname(:el2)
49
+ assert_equal(:el2, d.name)
50
+ d.chgname("el3")
51
+ assert_equal(:el3, d.name)
52
+ end
53
+
54
+ def test_attributes
55
+ e = Element.new("el", {"a1"=>"v1", "a2"=>"v2", "a3"=>nil})
56
+ assert_equal(:el, e.name)
57
+ assert_equal({:a1=>"v1", :a2=>"v2", :a3=>nil}, e.attributes)
58
+ end
59
+
60
+ def test_bracket
61
+ e = Element.new(:el, :attr=>"value")
62
+ e << "test"
63
+ assert_equal("value", e[:attr])
64
+ assert_equal("test", e[0])
65
+ end
66
+
67
+ def test_add_attribute
68
+ e = Element.new("el")
69
+ e.add_attribute("key_str", "value1")
70
+ e.add_attribute(:key_sym, "value2")
71
+ assert_equal({:key_str=>"value1", :key_sym=>"value2"}, e.attributes)
72
+ e.add_attribute(:nil, nil)
73
+ assert_equal({:key_str=>"value1", :key_sym=>"value2", :nil=>nil}, e.attributes)
74
+ end
75
+
76
+ def test_del_attribute
77
+ e = Element.new("el", {:a1=>"v1", :a2=>"v2"})
78
+ e.del_attribute("a1")
79
+ assert_equal({:a2=>"v2"}, e.attributes)
80
+ e.del_attribute(:a2)
81
+ assert_equal({}, e.attributes)
82
+ end
83
+
84
+ def test_contents
85
+ sub = Element.new("sub")
86
+ e = Element.new("el") << "String1" << "String2" << sub
87
+ assert_equal(["String1", "String2", sub], e.contents)
88
+ end
89
+
90
+ def test_add
91
+ e = Element.new("el").add(Element.new("sub"))
92
+ assert_instance_of(Element, e, "add Element")
93
+ assert_equal(:el, e.name)
94
+
95
+ e = Element.new("el")
96
+ e.add(Element.new("sub1"))
97
+ e.add([Element.new("sub2").add("text"), "string"])
98
+ assert_equal([Element.new("sub1"), Element.new("sub2").add("text"), "string"], e.contents, "add Array")
99
+
100
+ e = Element.new("el")
101
+ e.add(nil)
102
+ assert_equal(0, e.contents.size, "add nil")
103
+
104
+ e = Element.new("el").add(:symbol)
105
+ assert_equal(["symbol"], e.contents, "add anything(which has to_s)")
106
+
107
+ e = Element.new("super") << Element.new("sub")
108
+ assert_equal(:super, e.name)
109
+ assert_equal([Element.new("sub")], e.contents)
110
+ end
111
+
112
+ def test_write
113
+ e = Element.new("el")
114
+ s = String.new
115
+ assert_equal(s.object_id, e.write(s).object_id)
116
+ assert_equal("<el />", s)
117
+
118
+ e = Element.new("super")
119
+ e << Element.new("sub")
120
+ assert_equal("<super><sub /></super>", e.write)
121
+ e << Element.new("sub2")
122
+ assert_equal("<super>\n <sub />\n <sub2 />\n</super>", e.write)
123
+ assert_equal(" <super>\n <sub />\n <sub2 />\n </super>", e.write("", 1))
124
+ assert_equal("<super>\n <sub />\n <sub2 />\n </super>", e.write("", 1, false))
125
+
126
+ s = Element.new("supersuper")
127
+ s << e
128
+ assert_equal("<supersuper><super>\n <sub />\n <sub2 />\n</super></supersuper>", s.write)
129
+
130
+ e = Element.new("el") << "str"
131
+ s = Element.new("sub")
132
+ s << "inside"
133
+ e << s
134
+ assert_equal("<el>\n str\n <sub>inside</sub>\n</el>", e.write)
135
+
136
+ e = Element.new("el")
137
+ e.attributes["a1"] = "v1"
138
+ e.attributes["a2"] = "'\"<>&"
139
+ s = e.write
140
+ assert_match(/\A<el ([^>]*) \/>\z/, s)
141
+ assert_match(/a1='v1'/, s)
142
+ assert_match(/a2='&apos;&quot;&lt;&gt;&amp;'/, s)
143
+
144
+ e = Element.new("el", {"a1"=>nil})
145
+ assert_equal("<el a1='a1' />", e.write)
146
+ end
147
+
148
+ def test_spcial_string
149
+ e = Element.new("el") << "&\"'<>"
150
+ e << PCString.new("&\"'<>", true)
151
+ e.attributes["key"] = PCString.new("&\"'<>", true)
152
+ assert_equal(%[<el key='&\"'<>'>\n &amp;&quot;&apos;&lt;&gt;\n &\"'<>\n</el>], e.to_s)
153
+ end
154
+
155
+ def test_dup
156
+ e = Element.new("el")
157
+ e.attributes["key"] = "value"
158
+ e << "String"
159
+ e << "Freeze".freeze
160
+ s = Element.new("sub")
161
+ s.attributes["subkey"] = "subvalue"
162
+ e << s
163
+ f = e.dup
164
+
165
+ assert_equal(e.attributes.object_id, f.attributes.object_id)
166
+ assert_equal(e.contents.object_id, f.contents.object_id)
167
+
168
+ assert_equal(e.to_s, f.to_s)
169
+
170
+ e = Element.new("el")
171
+ e.hold_space
172
+ f = e.dup
173
+ assert(f.hold_space?)
174
+ end
175
+
176
+ def test_clone
177
+ e = Element.new("el")
178
+ e.attributes["key"] = "value"
179
+ e << "String"
180
+ e << "Freeze".freeze
181
+ s = Element.new("sub")
182
+ s.attributes["subkey"] = "subvalue"
183
+ e << s
184
+ f = e.clone
185
+
186
+ assert_equal(e.attributes.object_id, f.attributes.object_id)
187
+ assert_equal(e.contents.object_id, f.contents.object_id)
188
+
189
+ assert_equal(e.to_s, f.to_s)
190
+
191
+ e = Element.new("el")
192
+ e.hold_space
193
+ f = e.clone
194
+ assert(f.hold_space?)
195
+ end
196
+
197
+ def test_hold_space
198
+ e = Element.new("el") << "Line1" << "Line2"
199
+ s = Element.new("sub") << "Sub1" << "Sub2"
200
+ e << s
201
+ e.hold_space
202
+ assert_equal("<el>Line1Line2<sub>\n Sub1\n Sub2\n </sub></el>", e.to_s)
203
+
204
+ e.unhold_space
205
+ assert_equal("<el>\n Line1\n Line2\n <sub>\n Sub1\n Sub2\n </sub>\n</el>", e.to_s)
206
+
207
+ e = Element.new("e")
208
+ assert_equal(e.object_id, e.hold_space.object_id)
209
+ assert_equal(e.object_id, e.unhold_space.object_id)
210
+ end
211
+
212
+ def test_equal
213
+ e1 = Element.new("el")
214
+ e1.attributes["key"] = "value"
215
+ s = Element.new("sub")
216
+ s << "String"
217
+ e1 << s
218
+ e2 = e1.dup
219
+ assert_equal(e1, e2)
220
+
221
+ e3 = Element.new("e")
222
+ e3.attributes["key"] = "value"
223
+ s = Element.new("sub")
224
+ s << "String"
225
+ e3 << s
226
+ assert_not_equal(e1, e3)
227
+
228
+ e3 = Element.new("e")
229
+ e3.attributes["k"] = "value"
230
+ s = Element.new("sub")
231
+ s << "String"
232
+ e3 << s
233
+ assert_not_equal(e1, e3)
234
+
235
+ e3 = Element.new("e")
236
+ e3.attributes["key"] = "v"
237
+ s = Element.new("sub")
238
+ s << "String"
239
+ e3 << s
240
+ assert_not_equal(e1, e3)
241
+
242
+ e3 = Element.new("e")
243
+ e3.attributes["key"] = "value"
244
+ s = Element.new("sub")
245
+ s << "S"
246
+ e3 << s
247
+ assert_not_equal(e1, e3)
248
+
249
+ e3 = Element.new("e")
250
+ e3.attributes["key"] = "value"
251
+ s = Element.new("s")
252
+ s << "String"
253
+ e3 << s
254
+ assert_not_equal(e1, e3)
255
+
256
+ assert_not_equal(e1, "string")
257
+ end
258
+
259
+ def test_new_with_block
260
+ b = nil
261
+ e = Element.new("base") do |b|
262
+ b["attr"]="value"
263
+ b << Element.new("sub")
264
+ end
265
+ assert_same(e, b)
266
+ e2 = Element.new("base", "attr"=>"value")
267
+ e2 << Element.new("sub")
268
+ assert_equal(e, e2)
269
+
270
+ e = Element.new("base") do |e|
271
+ e <<= Element.new("sub1") do |e|
272
+ e <<= Element.new("sub12")
273
+ end
274
+ e <<= Element.new("sub2")
275
+ end
276
+ base = Element.new("base")
277
+ sub1 = Element.new("sub1")
278
+ sub1 << Element.new("sub12")
279
+ sub2 = Element.new("sub2")
280
+ base << sub1 << sub2
281
+ assert_equal(base, e)
282
+ end
283
+
284
+ def test_symbol_string_compatible
285
+ sym = Element.new(:tag, :attr=>"value")
286
+ str = Element.new("tag", "attr"=>"value")
287
+
288
+ assert_equal(sym.to_s, str.to_s)
289
+ assert_equal(sym, str)
290
+ end
291
+
292
+ def test_match
293
+ e = Element.new(:tag, :attr=>"value")
294
+ assert(e.match?(:tag))
295
+ assert(e.match?(:tag, :attr=>"value"))
296
+ assert(! e.match?(:t))
297
+ assert(! e.match?(:tag, :attr2=>"value"))
298
+ assert(! e.match?(:tag, :attr=>"value2"))
299
+
300
+ assert(e.match?(Element.new(:tag)))
301
+ assert(e.match?(Element.new(:tag, :attr=>"value")))
302
+ assert(! e.match?(Element.new(:t)))
303
+ assert(! e.match?(Element.new(:tag, :attr2=>"value")))
304
+ assert(! e.match?(Element.new(:tag, :attr=>"value2")))
305
+
306
+ assert(e.match?(/ag/))
307
+ assert(e.match?(/ag/, /tt/=>/al/))
308
+ assert(! e.match?(/elem/))
309
+ assert(! e.match?(/tag/, /attr2/=>/val/))
310
+ assert(! e.match?(/tag/, /attr/=>/v2/))
311
+
312
+ assert(e.match?(:tag, :attr=>/val/))
313
+ assert(e.match?(/t/, /at/=>"value"))
314
+
315
+ e = Element.new(:tag, :attr1=>"value", :attr2=>"test")
316
+ assert(e.match?(:tag, /attr/=>"value"))
317
+ assert(e.match?(:tag, /attr/=>/t/))
318
+
319
+ assert(e.match?(Element))
320
+ assert(!e.match?(Dummy))
321
+ assert(!e.match?(String))
322
+ end
323
+
324
+ def test_match_by_array
325
+ e = Element.new(:tag, :attr=>"value", :a2=>"v2")
326
+ assert(e.match?([:tag]))
327
+ assert(e.match?([:tag, {:attr=>"value"}]))
328
+ assert(e.match?([:tag, {:attr=>"value", :a2=>"v2"}]))
329
+ assert(e.match?([/tag/, {/a/=>/v/}]))
330
+ end
331
+
332
+ def test_match_operator
333
+ e = Element.new(:tag, :attr=>"value", :a2=>"v2")
334
+ assert_match(:tag, e)
335
+ assert_match(Element.new(:tag), e)
336
+ assert_match([:tag], e)
337
+ assert_match([:tag, {:attr=>"value"}], e)
338
+ assert_match(Element.new(:tag, :a2=>"v2"), e)
339
+ assert_match([/t/, {/a/=>/v/}], e)
340
+
341
+ assert(e !~ :t)
342
+ assert(e !~ Element.new(:t))
343
+ assert(e !~ [:t])
344
+ assert(e !~ [:tag, {:a=>"v"}])
345
+ assert(e !~ Element.new(:tag, :a=>"v"))
346
+ end
347
+
348
+ def test_has
349
+ e = Element.new(:base) do |b|
350
+ b <<= Element.new(:sub) do |s|
351
+ s <<= Element.new(:deep) do |d|
352
+ d << "text"
353
+ end
354
+ end
355
+ b <<= Element.new(:sub, :attr=>"value")
356
+ end
357
+
358
+ assert(e.has?(:base))
359
+ assert(e.has?(:sub))
360
+ assert(e.has?(:sub, :attr=>"value"))
361
+ assert(!e.has?(:sub, :attr=>"value", :attr2=>""))
362
+ assert(e.has?(:deep))
363
+ assert(! e.has?(:deep, {}, false))
364
+
365
+ assert(e.has?(String))
366
+ end
367
+
368
+ def test_find
369
+ s1 = Element.new(:sub)
370
+ d = Element.new(:deep)
371
+ d << "3rd"
372
+ s1 << "2nd" << d
373
+ s2 = Element.new(:sub, :attr=>"value")
374
+ e = Element.new(:base)
375
+ e << "1st" << s1 << s2
376
+
377
+ assert_equal([d], e.find(:deep))
378
+ assert_equal([s1, s2], e.find(:sub))
379
+ assert_equal([e, s1, d, s2], e.find(//))
380
+
381
+ assert_equal(["1st", "2nd", "3rd"], e.find(String))
382
+ end
383
+ end
384
+
385
+ class TC_SymbolKeyHash < Test::Unit::TestCase
386
+ SKH = EimXML::SymbolKeyHash
387
+
388
+ def test_new
389
+ s = SKH.new({"key1"=>"value1", :key2=>"value2"})
390
+ assert_equal({:key1=>"value1", :key2=>"value2"}, s)
391
+ end
392
+
393
+ def test_update
394
+ h = {"key"=>"value"}
395
+ s = SKH.new
396
+ s.update(h)
397
+ assert_equal({:key=>"value"}, s)
398
+
399
+ s2 = SKH.new
400
+ s2.update(s)
401
+ assert_equal(s, s2)
402
+ end
403
+
404
+ def test_merge
405
+ s = SKH.new
406
+ s2 = s.merge({"key"=>"value"})
407
+ assert_equal({}, s)
408
+ assert_equal({:key=>"value"}, s2)
409
+ end
410
+
411
+ def test_merge!
412
+ s = SKH.new
413
+ s2 = s.merge!({"key"=>"value"})
414
+ h = {:key=>"value"}
415
+ assert_equal(h, s)
416
+ assert_equal(h, s2)
417
+ end
418
+
419
+ def test_store
420
+ s = SKH.new
421
+ s.store(:sym1, "value1")
422
+ s.store("str1", "value2")
423
+ s[:sym2] = "value3"
424
+ s["str2"] = "value4"
425
+
426
+ assert_equal({:sym1=>"value1", :str1=>"value2", :sym2=>"value3", :str2=>"value4"}, s)
427
+ end
428
+ end
@@ -0,0 +1,102 @@
1
+ # Test for eim_xml/parser.rb
2
+ #
3
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+
6
+ require "test/unit"
7
+ require "eim_xml/parser"
8
+
9
+ class TC_Parser < Test::Unit::TestCase
10
+ include EimXML
11
+
12
+ def parse(src)
13
+ Parser.new(src).parse
14
+ end
15
+
16
+ def test_parse
17
+ s = " <e /> "
18
+ assert_equal(Parser.new(s).parse, parse(s))
19
+ end
20
+
21
+ def test_parse_empty_element
22
+ assert_equal(Element.new("e"), parse("<e />"))
23
+ assert_equal(Element.new("e"), parse("<e/>"))
24
+
25
+ assert_equal(Element.new("e", "key"=>"value"), parse(%[<e key="value"/>]))
26
+ assert_equal(Element.new("e", "key"=>"value"), parse(%[<e key='value'/>]))
27
+ assert_equal(Element.new("e", "key"=>"value"), parse(%[<e key="value" />]))
28
+ assert_equal(Element.new("e", "key"=>"value"), parse(%[<e key='value' />]))
29
+
30
+ assert_equal(Element.new("e", "key"=>"value", "key2"=>"value2"), parse(%[<e key="value" key2="value2"/>]))
31
+ assert_equal(Element.new("e", "key"=>"value", "key2"=>"value2"), parse(%[<e key="value" key2="value2" />]))
32
+
33
+ s = " <e1 /> <e2 /> "
34
+ p = Parser.new(s)
35
+ assert_equal(Element.new("e1"), p.parse)
36
+ assert_equal(Element.new("e2"), p.parse)
37
+ end
38
+
39
+ def test_parse_nonempty_element
40
+ assert_equal(Element.new("super") << Element.new("sub"), parse("<super><sub /></super>"))
41
+ e = assert_raises(ParseError){parse("<el></e>")}
42
+ assert_equal("End tag mismatched.", e.message)
43
+ e = assert_raises(ParseError){parse("<el><></el>")}
44
+ assert_equal("Syntax error.", e.message)
45
+ end
46
+
47
+ def test_parse_string
48
+ e = parse("string&amp;")
49
+ assert_instance_of(PCString, e)
50
+ assert_equal("string&amp;", e.to_s)
51
+ e = parse(" string &amp; ")
52
+ assert_instance_of(PCString, e)
53
+ assert_equal("string &amp;", e.to_s)
54
+
55
+ e = Element.new("e")
56
+ e << PCString.new("string")
57
+ assert_equal(e, parse("<e> string </e>"))
58
+ assert_equal(e, parse("<e>string</e>"))
59
+ end
60
+
61
+ def test_hold_space
62
+ s = "<e> string with space\n</e>"
63
+ e = Element.new("e")
64
+ e << PCString.new("string with space", true)
65
+ assert_equal(e, parse(s))
66
+
67
+ e = Element.new("e").hold_space
68
+ e << PCString.new(" string with space\n", true)
69
+ assert_not_equal(e, Parser.new(s).parse)
70
+ assert_equal(e, Parser.new(s).parse(true))
71
+ assert_equal(e, Parser.new(s, "dummy", "e").parse)
72
+ assert_equal(e, Parser.new(s, /dummy/, /e/).parse)
73
+ assert_equal(e, Parser.new(s, :dummy, :e).parse)
74
+ assert_equal(e, Parser.new(s, :dummy, /^(.*:)?e$/).parse)
75
+
76
+ s = "<ns:e> string with space\n</ns:e>"
77
+ e = Element.new("ns:e")
78
+ e << PCString.new("string with space")
79
+ assert_equal(e, Parser.new(s).parse)
80
+
81
+ e = Element.new("ns:e").hold_space
82
+ e << PCString.new(" string with space\n")
83
+ assert_equal(e, Parser.new(s, /^(.*:)?e$/).parse)
84
+
85
+ s = "<a> string without space <b> string with space <a> string with space 2 </a> </b> </a>"
86
+ oa = Element.new("a") << PCString.new("string without space")
87
+ b = Element.new("b").hold_space
88
+ b << PCString.new(" string with space ")
89
+ ia = Element.new("a").hold_space
90
+ ia << PCString.new(" string with space 2 ")
91
+ b << ia
92
+ b << PCString.new(" ")
93
+ oa << b
94
+ assert_equal(oa, Parser.new(s, "b").parse)
95
+
96
+ s = "<a><b/></a>"
97
+ a = Element.new("a").hold_space
98
+ b = Element.new("b").hold_space
99
+ a << b
100
+ assert_equal(a, Parser.new(s, "a").parse)
101
+ end
102
+ end
@@ -0,0 +1,138 @@
1
+ # Test for eim_xml/xhtml.rb
2
+ #
3
+ # Copyright (C) 2007, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+
6
+ require "eim_xml/xhtml"
7
+ require "test/unit"
8
+
9
+ class TC_XHTML < Test::Unit::TestCase
10
+ include EimXML::XHTML
11
+ Element = EimXML::Element
12
+
13
+ def test_html
14
+ h = HTML.new(:attr=>"value")
15
+ assert_equal(Element.new(:html, :attr=>"value"), h)
16
+
17
+ h = HTML.new do |e|
18
+ e <<= Element.new(:sub)
19
+ end
20
+ h2 = HTML.new
21
+ h2 << Element.new(:sub)
22
+ assert_equal(h, h2)
23
+ end
24
+
25
+ def test_html_with_declarations
26
+ decs = EimXML::XML_DECLARATION + "\n" + DocType::XHTML_MATHML + "\n"
27
+ h = HTML.new
28
+ assert_equal(decs + "<html />", h.to_s)
29
+
30
+ h = HTML.new
31
+ assert_equal("<html />", h.to_s(false))
32
+
33
+ h = HTML.new do |h|
34
+ h << Body.new do |b|
35
+ b << "test"
36
+ end
37
+ end
38
+
39
+ assert_equal(decs+h.to_s(false), h.to_s)
40
+
41
+ s1 = ""
42
+ s2 = ""
43
+ assert_equal(decs+h.write(s1, false), h.write(s2))
44
+ end
45
+
46
+ def test_head
47
+ assert_equal(:head, Head.new.name)
48
+ end
49
+
50
+ def test_title
51
+ assert_equal(:title, Title.new.name)
52
+ end
53
+
54
+ def test_body
55
+ assert_equal(:body, Body.new.name)
56
+ end
57
+
58
+ def test_pre
59
+ assert_equal(:pre, Pre.new.name)
60
+ end
61
+
62
+ def test_form
63
+ assert_equal(:form, Form.new.name)
64
+ end
65
+
66
+ def test_hn
67
+ assert_equal(:h1, Hn.new(1).name)
68
+ assert_equal(:h6, Hn.new(6).name)
69
+ assert_raises(ArgumentError){Hn.new(7)}
70
+ assert_raises(ArgumentError){Hn.new(0)}
71
+ end
72
+
73
+ def test_p
74
+ assert_equal(:p, P.new.name)
75
+ end
76
+
77
+ def test_a
78
+ assert_equal(:a, A.new.name)
79
+ end
80
+
81
+ def test_em
82
+ assert_equal(:em, Em.new.name)
83
+ end
84
+
85
+ def test_strong
86
+ assert_equal(:strong, Strong.new.name)
87
+ end
88
+
89
+ def test_div
90
+ assert_equal(:div, Div.new.name)
91
+ end
92
+
93
+ def test_ul
94
+ assert_equal(:ul, Ul.new.name)
95
+ end
96
+
97
+ def test_ol
98
+ assert_equal(:ol, Ol.new.name)
99
+ end
100
+
101
+ def test_li
102
+ assert_equal(:li, Li.new.name)
103
+ end
104
+
105
+ def test_text_area
106
+ assert_equal(Element.new(:textarea, :name=>"item"), TextArea.new("item"))
107
+ assert_equal(Element.new(:textarea, :name=>"item"), TextArea.new(:item))
108
+ assert_equal(Element.new(:textarea, :name=>"item", :class=>"cv"), TextArea.new("item", :class=>"cv"))
109
+ end
110
+
111
+ def test_input
112
+ assert_equal(Element.new(:input, :type=>"test", :name=>"item", :value=>"v"), Input.new(:test, :item, "v"))
113
+ assert_equal(Element.new(:input, :type=>"test", :name=>"item", :value=>"v"), Input.new("test", "item", "v"))
114
+ assert_equal(Element.new(:input, :type=>"test", :name=>"item", :value=>"v", :class=>"c"), Input.new(:test, :item, "v", :class=>"c"))
115
+
116
+ assert_equal(Element.new(:input, :type=>"submit", :value=>"v"), Input.new(:submit, nil, "v"))
117
+ assert_equal(Element.new(:input, :type=>"submit", :name=>"item"), Input.new(:submit, "item", nil))
118
+ end
119
+
120
+ def test_hidden
121
+ assert_equal(Element.new(:input, :type=>"hidden", :name=>"item", :value=>"v"), Hidden.new("item", "v"))
122
+ assert_equal(Element.new(:input, :type=>"hidden", :name=>"item", :value=>"v"), Hidden.new(:item, "v"))
123
+ assert_equal(Element.new(:input, :type=>"hidden", :name=>"item", :value=>"v", :class=>"c"), Hidden.new(:item, "v", :class=>"c"))
124
+ end
125
+
126
+ def test_submit
127
+ assert_equal(Element.new(:input, :type=>"submit"), Submit.new)
128
+ assert_equal(Element.new(:input, :type=>"submit", :value=>"OK"), Submit.new("OK"))
129
+ assert_equal(Element.new(:input, :type=>"submit", :value=>"OK", :class=>"c"), Submit.new("OK", :class=>"c"))
130
+ end
131
+
132
+ def test_text
133
+ assert_equal(Element.new(:input, :type=>"text", :name=>"item"), Text.new(:item))
134
+ assert_equal(Element.new(:input, :type=>"text", :name=>"item"), Text.new("item"))
135
+ assert_equal(Element.new(:input, :type=>"text", :name=>"item", :value=>"txt"), Text.new(:item, "txt"))
136
+ assert_equal(Element.new(:input, :type=>"text", :name=>"item", :value=>"txt", :class=>"c"), Text.new(:item, "txt", :class=>"c"))
137
+ end
138
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: eimxml
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-10-23 00:00:00 +09:00
8
+ summary: Easy IMplemented XML
9
+ require_paths:
10
+ - lib
11
+ email: hiraku@hinet.mydns.jp
12
+ homepage: http://eimxml.rubyforge.org/
13
+ rubyforge_project: eimxml
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - KURODA Hiraku
31
+ files:
32
+ - lib
33
+ - test
34
+ - Rakefile
35
+ - README
36
+ - lib/eim_xml.rb
37
+ - lib/eim_xml
38
+ - lib/eim_xml/parser.rb
39
+ - lib/eim_xml/assertions.rb
40
+ - test/assertions_test.rb
41
+ - test/eim_xml_test.rb
42
+ - test/parser_test.rb
43
+ test_files:
44
+ - test/assertions_test.rb
45
+ - test/xhtml_test.rb
46
+ - test/eim_xml_test.rb
47
+ - test/parser_test.rb
48
+ rdoc_options:
49
+ - -S
50
+ - -w
51
+ - "3"
52
+ - -c
53
+ - UTF-8
54
+ - -m
55
+ - README
56
+ extra_rdoc_files:
57
+ - README
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ requirements: []
63
+
64
+ dependencies: []
65
+