magic-xml 0.2013.04.14 → 0.2016.05.07

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.
Files changed (5) hide show
  1. checksums.yaml +7 -7
  2. data/lib/magic_xml.rb +1218 -1228
  3. metadata +50 -33
  4. data/test.xml +0 -1
  5. data/tests.rb +0 -836
metadata CHANGED
@@ -1,56 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: magic-xml
3
- version: !ruby/object:Gem::Version
4
- version: 0.2013.04.14
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2016.05.07
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Tomasz Wegrzanowski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2013-04-14 00:00:00 Z
13
- dependencies: []
14
-
11
+ date: 2016-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
15
41
  description: The best Ruby library for handling XML
16
- email:
42
+ email:
17
43
  - Tomasz.Wegrzanowski@gmail.com
18
44
  executables: []
19
-
20
45
  extensions: []
21
-
22
46
  extra_rdoc_files: []
23
-
24
- files:
47
+ files:
25
48
  - lib/magic_xml.rb
26
- - tests.rb
27
- - test.xml
28
49
  homepage: https://github.com/taw/magic-xml
29
50
  licenses: []
30
-
31
51
  metadata: {}
32
-
33
52
  post_install_message:
34
53
  rdoc_options: []
35
-
36
- require_paths:
54
+ require_paths:
37
55
  - lib
38
- required_ruby_version: !ruby/object:Gem::Requirement
39
- requirements:
40
- - &id001
41
- - ">="
42
- - !ruby/object:Gem::Version
43
- version: "0"
44
- required_rubygems_version: !ruby/object:Gem::Requirement
45
- requirements:
46
- - *id001
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
47
66
  requirements: []
48
-
49
67
  rubyforge_project:
50
- rubygems_version: 2.0.3
68
+ rubygems_version: 2.4.5
51
69
  signing_key:
52
70
  specification_version: 4
53
71
  summary: The best Ruby library for handling XML
54
- test_files:
55
- - tests.rb
56
- - test.xml
72
+ test_files: []
73
+ has_rdoc:
data/test.xml DELETED
@@ -1 +0,0 @@
1
- <foo><bar></bar></foo>
data/tests.rb DELETED
@@ -1,836 +0,0 @@
1
- #!/usr/bin/env ruby -Ilib
2
- require 'test/unit'
3
- require 'magic_xml'
4
-
5
- # For tests
6
- require 'stringio'
7
-
8
- class XML_Tests < Test::Unit::TestCase
9
- # Test whether XML.new constructors work (without monadic case)
10
- def test_constructors
11
- br = XML.new(:br)
12
- h3 = XML.new(:h3, "Hello")
13
- a = XML.new(:a, {:href => "http://www.google.com/"}, "Google")
14
- ul = XML.new(:ul, XML.new(:li, "Hello"), XML.new(:li, "world"))
15
-
16
- assert_equal("<br/>", br.to_s, "Constructors should work")
17
- assert_equal("<h3>Hello</h3>", h3.to_s, "Constructors should work")
18
- assert_equal("<a href='http://www.google.com/'>Google</a>", a.to_s, "Constructors should work")
19
- assert_equal("<ul><li>Hello</li><li>world</li></ul>", ul.to_s, "Constructors should work")
20
- end
21
-
22
- # Test character escaping on output, in text and in attribute values
23
- def test_escapes
24
- p = XML.new(:p, "< > &")
25
- foo = XML.new(:foo, {:bar=>"< > ' \" &"})
26
-
27
- assert_equal("<p>&lt; &gt; &amp;</p>", p.to_s, "Character escaping should work")
28
- assert_equal("<foo bar='&lt; &gt; &apos; &quot; &amp;'/>", foo.to_s, "Character escaping in attributes should work")
29
- end
30
-
31
- # Test #sort_by and #children_sort_by
32
- def test_sort_by
33
- doc = XML.parse("<foo><bar id='5'/>a<bar id='3'/>c<bar id='4'/>b<bar id='1'/></foo>")
34
-
35
- doc_by_id = doc.sort_by{|c| c[:id]}
36
- assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/></foo>", doc_by_id.to_s)
37
-
38
- doc_all_by_id = doc.children_sort_by{|c| if c.is_a? XML then [0, c[:id]] else [1, c] end}
39
- assert_equal("<foo><bar id='1'/><bar id='3'/><bar id='4'/><bar id='5'/>abc</foo>", doc_all_by_id.to_s)
40
- end
41
-
42
- # Test XML#[] and XML#[]= for attribute access
43
- def test_attr
44
- foo = XML.new(:foo, {:x => "1"})
45
- assert_equal("1", foo[:x], "Attribute reading should work")
46
- foo[:x] = "2"
47
- foo[:y] = "3"
48
- assert_equal("2", foo[:x], "Attribute writing should work")
49
- assert_equal("3", foo[:y], "Attribute writing should work")
50
- end
51
-
52
- # Test XML#<< method for adding children
53
- def test_add
54
- a = XML.new(:p, "Hello")
55
- a << ", "
56
- a << "world!"
57
- assert_equal("<p>Hello, world!</p>", a.to_s, "XML#<< should work")
58
-
59
- b = XML.new(:foo)
60
- b << XML.new(:bar)
61
- assert_equal("<foo><bar/></foo>", b.to_s, "XML#<< should work")
62
- end
63
-
64
- # Test XML#each method for iterating over children
65
- def test_each
66
- a = XML.new(:p, "Hello", ", ", "world", XML.new(:br))
67
- b = ""
68
- a.each{|c| b += c.to_s}
69
- assert_equal("Hello, world<br/>", b, "XML#each should work")
70
- end
71
-
72
- # Test XML#map method
73
- def test_map
74
- a = XML.new(:body, XML.new(:h3, "One"), "Hello", XML.new(:h3, "Two"))
75
- b = a.map{|c|
76
- if c.is_a? XML and c.name == :h3
77
- XML.new(:h2, c.attrs, *c.contents)
78
- else
79
- c
80
- end
81
- }
82
- assert_equal("<body><h3>One</h3>Hello<h3>Two</h3></body>", a.to_s, "XML#map should not modify the argument")
83
- assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", b.to_s, "XML#map should work")
84
-
85
- d = a.map(:h3) {|c|
86
- XML.new(:h2, c.attrs, *c.contents)
87
- }
88
- assert_equal("<body><h2>One</h2>Hello<h2>Two</h2></body>", d.to_s, "XML#map should accept selectors")
89
- end
90
-
91
- # Test XML#==
92
- def test_eqeq
93
- a = XML.new(:foo)
94
- b = XML.new(:foo)
95
- c = XML.new(:bar)
96
- assert(a==a, "XML#== should work")
97
- assert(a==b, "XML#== should work")
98
- assert(a!=c, "XML#== should work")
99
-
100
- d = XML.new(:foo, {:bar => "1"})
101
- e = XML.new(:foo, {:bar => "1"})
102
- f = XML.new(:foo, {:bar => "2"})
103
- assert(d==d, "XML#== should work")
104
- assert(d==e, "XML#== should work")
105
- assert(d!=f, "XML#== should work")
106
-
107
- a = XML.new(:foo, "Hello, world!")
108
- b = XML.new(:foo, "Hello, world!")
109
- c = XML.new(:foo, "Hello", ", world!")
110
- d = XML.new(:foo, "Hello")
111
- e = XML.new(:foo, "Hello", "")
112
- assert(a==a, "XML#== should work")
113
- assert(a==b, "XML#== should work")
114
- assert(a==c, "XML#== should work")
115
- assert(a!=d, "XML#== should work")
116
- assert(d==e, "Empty children should not affect XML#==")
117
-
118
- # Highly pathological case
119
- a = XML.new(:foo, "ab", "cde", "", "fg", "hijk", "", "")
120
- b = XML.new(:foo, "", "abc", "d", "efg", "h", "ijk")
121
- assert(a==b, "XML#== should work with differently split Strings too")
122
-
123
- # String vs XML
124
- a = XML.new(:foo, "Hello")
125
- b = XML.new(:foo) {foo!}
126
- c = XML.new(:foo) {bar!}
127
- assert(a!=b, "XML#== should work with children of different types")
128
- assert(b!=c, "XML#== should work recursively")
129
-
130
- a = XML.new(:foo) {foo!; bar!}
131
- b = XML.new(:foo) {foo!; foo!}
132
- assert(a!=b, "XML#== should work recursively")
133
- end
134
-
135
- # Test dup-with-block method
136
- def test_dup
137
- a = XML.new(:foo, {:a => "1"}, "Hello")
138
- b = a.dup{ @name = :bar }
139
- c = a.dup{ self[:a] = "2" }
140
- d = a.dup{ self << ", world!" }
141
-
142
- assert_equal("<foo a='1'>Hello</foo>", a.to_s, "XML#dup{} should not modify its argument")
143
- assert_equal("<bar a='1'>Hello</bar>", b.to_s, "XML#dup{} should work")
144
- assert_equal("<foo a='2'>Hello</foo>", c.to_s, "XML#dup{} should work")
145
- assert_equal("<foo a='1'>Hello, world!</foo>", d.to_s, "XML#dup{} should work")
146
-
147
- # Deep copy test
148
- a = XML.new(:h3, "Hello")
149
- b = XML.new(:foo, XML.new(:bar, a))
150
- c = b.dup
151
- a << ", world!"
152
-
153
- assert_equal("<foo><bar><h3>Hello, world!</h3></bar></foo>", b.to_s, "XML#dup should make a deep copy")
154
- assert_equal("<foo><bar><h3>Hello</h3></bar></foo>", c.to_s, "XML#dup should make a deep copy")
155
- end
156
-
157
- # Test XML#normalize! method
158
- def test_normalize
159
- a = XML.new(:foo, "He", "", "llo")
160
- b = XML.new(:foo, "")
161
- c = XML.new(:foo, "", XML.new(:bar, "1"), "", XML.new(:bar, "2", ""), "X", XML.new(:bar, "", "3"), "")
162
-
163
- a.normalize!
164
- b.normalize!
165
- c.normalize!
166
-
167
- assert_equal(["Hello"], a.contents, "XML#normalize! should work")
168
- assert_equal([], b.contents, "XML#normalize! should work")
169
- assert_equal([XML.new(:bar, "1"), XML.new(:bar, "2"), "X", XML.new(:bar, "3")], c.contents, "XML#normalize! should work")
170
- end
171
-
172
- # Test the "monadic" interface, that is constructors
173
- # with instance_eval'd blocks passed to them:
174
- # XML.new(:foo) { bar! } # -> <foo><bar/></foo>
175
- def test_monadic
176
- a = XML.new(:foo) { bar!; xml!(:xxx) }
177
- b = xml(:div) {
178
- ul! {
179
- li!(XML.a("Hello"))
180
- }
181
- }
182
- assert_equal("<foo><bar/><xxx/></foo>", a.to_s, "Monadic interface should work")
183
- assert_equal("<div><ul><li><a>Hello</a></li></ul></div>", b.to_s, "Monadic interface should work")
184
- end
185
-
186
- # Test if parsing and printing gives the right results
187
- # We test mostly round-trip
188
- def test_parse
189
- a = "<foo/>"
190
- b = "<foo a='1'/>"
191
- c = "<foo>Hello</foo>"
192
- d = "<foo a='1'><bar b='2'>Hello</bar><bar b='3'>world</bar></foo>"
193
- e = "<foo>&gt; &lt; &amp;</foo>"
194
- f = "<foo a='b&amp;c'/>"
195
-
196
- assert_equal(a, XML.parse(a).to_s, "XML.parse(x).to_s should equal x for normalized x")
197
- assert_equal(b, XML.parse(b).to_s, "XML.parse(x).to_s should equal x for normalized x")
198
- assert_equal(c, XML.parse(c).to_s, "XML.parse(x).to_s should equal x for normalized x")
199
- assert_equal(d, XML.parse(d).to_s, "XML.parse(x).to_s should equal x for normalized x")
200
- assert_equal(e, XML.parse(e).to_s, "XML.parse(x).to_s should equal x for normalized x")
201
- assert_equal(f, XML.parse(f).to_s, "XML.parse(x).to_s should equal x for normalized x")
202
- end
203
-
204
- # Test parsing &-entities
205
- def test_parse_extra_escapes
206
- a = "<foo>&quot; &apos;</foo>"
207
- a_out = "<foo>\" '</foo>"
208
-
209
- assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should normalize entities in x")
210
- end
211
-
212
- # Test handling extra cruft
213
- # Some things are best ignored or normalized
214
- def test_parse_extra_cdata
215
- a = "<foo><![CDATA[<greeting>Hello, world!</greeting>]]></foo>"
216
- a_out = "<foo>&lt;greeting&gt;Hello, world!&lt;/greeting&gt;</foo>"
217
- assert_equal(a_out, XML.parse(a).to_s, "XML.parse(x).to_s should equal normalized x")
218
- end
219
-
220
- # Test handling (=ignoring) XML declarations
221
- def test_parse_extra_qxml
222
- b = "<?xml version=\"1.0\"?><greeting>Hello, world!</greeting>"
223
- b_out = "<greeting>Hello, world!</greeting>"
224
- assert_equal(b_out, XML.parse(b).to_s, "XML.parse(x).to_s should equal normalized x")
225
- end
226
-
227
- # Test handling (=ignoring) DTDs
228
- def test_parse_extra_dtd
229
- c = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]><greeting>Hello, world!</greeting>"
230
- c_out = "<greeting>Hello, world!</greeting>"
231
- assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
232
- end
233
-
234
- # Test handling (=ignoring) DTDs
235
- def test_parse_extra_comment
236
- c = "<!-- this is a comment --><greeting>Hello,<!-- another comment --> world!</greeting>"
237
- c_out = "<greeting>Hello, world!</greeting>"
238
- assert_equal(c_out, XML.parse(c).to_s, "XML.parse(x).to_s should equal normalized x")
239
- end
240
-
241
- # Test reading from a file
242
- def test_parse_file
243
- a = File.open("test.xml").xml_parse
244
- b = XML.from_file("test.xml")
245
- c = XML.from_url("file:test.xml")
246
- d = XML.from_url("string:<foo><bar></bar></foo>")
247
- e = XML.parse("<foo><bar></bar></foo>")
248
- f = "<foo><bar></bar></foo>".xml_parse
249
- g = XML.foo { bar! }
250
-
251
- assert_equal(g.to_s, a.to_s, "File#xml_parse should work")
252
- assert_equal(g.to_s, b.to_s, "XML.from_file should work")
253
- assert_equal(g.to_s, c.to_s, "XML.from_url(\"file:...\") should work")
254
- assert_equal(g.to_s, d.to_s, "XML.from_url(\"string:...\") should work")
255
- assert_equal(g.to_s, e.to_s, "XML.parse should work")
256
- assert_equal(g.to_s, f.to_s, "String#xml_parse should work")
257
- end
258
-
259
- # Test XML#children and Array#children
260
- def test_chilrden
261
- a = XML.bar({:x=>"1"})
262
- b = XML.bar({:x=>"3"})
263
- c = XML.bar({:x=>"2"}, b)
264
- d = XML.foo(a,c)
265
- e = d.children(:bar)
266
- f = e.children(:bar)
267
- assert_equal([a,c], e, "XML#children(tag) should return tag-tagged children")
268
- assert_equal([b], f, "Array#children(tag) should return tag-tagged children of its elements")
269
- end
270
-
271
- # Test XML#descendants and Array#descendants
272
- def test_descendants
273
- a = XML.bar({:x=>"1"})
274
- b = XML.bar({:x=>"3"})
275
- c = XML.bar({:x=>"2"}, b)
276
- d = XML.foo(a,c)
277
- e = d.descendants(:bar)
278
- f = e.descendants(:bar)
279
- assert_equal([a,c,b], e, "XML#descendants(tag) should return tag-tagged descendants")
280
- assert_equal([b], f, "Array#descendants(tag) should return tag-tagged descendants of its elements")
281
- end
282
-
283
- # Test XML#exec! monadic interface
284
- def test_exec
285
- a = XML.foo
286
- a.exec! {
287
- bar! { text! "Hello" }
288
- text! "world"
289
- }
290
- assert_equal("<foo><bar>Hello</bar>world</foo>", a.to_s, "XML#exec! should work")
291
- end
292
-
293
- # Test XML#child
294
- def test_child
295
- a = XML.parse("<foo></foo>")
296
- b = XML.parse("<foo><bar a='1'/></foo>")
297
- c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
298
-
299
- assert_equal(nil, a.child(:bar), "XML#child should return nil if there are no matching children")
300
- assert_equal("<bar a='1'/>", b.child(:bar).to_s, "XML#child should work")
301
- assert_equal("<bar a='1'/>", c.child(:bar).to_s, "XML#child should return first child if there are many")
302
- assert_equal("<bar a='2'/>", c.child({:a => '2'}).to_s, "XML#child should support patterns")
303
- end
304
-
305
- # Test XML#descendant
306
- def test_descendant
307
- a = XML.parse("<foo></foo>")
308
- b = XML.parse("<foo><bar a='1'/></foo>")
309
- c = XML.parse("<foo><bar a='1'/><bar a='2'/></foo>")
310
- d = XML.parse("<foo><bar a='1'><bar a='2'/></bar><bar a='3'/></foo>")
311
- e = XML.parse("<foo><foo><bar a='1'/></foo><bar a='2'/></foo>")
312
-
313
- assert_equal(nil, a.descendant(:bar), "XML#descendant should return nil if there are no matching descendants")
314
- assert_equal("<bar a='1'/>", b.descendant(:bar).to_s, "XML#descendant should work")
315
- assert_equal("<bar a='1'/>", c.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
316
- assert_equal("<bar a='1'><bar a='2'/></bar>", d.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
317
- assert_equal("<bar a='1'/>", e.descendant(:bar).to_s, "XML#descendant should return first descendant if there are many")
318
- assert_equal("<bar a='2'/>", c.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
319
- assert_equal("<bar a='2'/>", d.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
320
- assert_equal("<bar a='2'/>", e.descendant({:a => '2'}).to_s, "XML#descendant should support patterns")
321
- end
322
-
323
- # Test XML#text
324
- def test_text
325
- a = XML.parse("<foo>Hello</foo>")
326
- b = XML.parse("<foo></foo>")
327
- c = XML.parse("<foo><bar>Hello</bar></foo>")
328
- d = XML.parse("<foo>He<bar>llo</bar></foo>")
329
-
330
- assert_equal("Hello", a.text, "XML#text should work")
331
- assert_equal("", b.text, "XML#text should work")
332
- assert_equal("Hello", c.text, "XML#text should work")
333
- assert_equal("Hello", d.text, "XML#text should work")
334
- end
335
-
336
- # Test XML#renormalize and XML#renormalize_sequence
337
- def test_renormalize
338
- a = "<foo></foo>"
339
- b = "<foo></foo><bar></bar>"
340
-
341
- assert_equal("<foo/>", XML.renormalize(a), "XML#renormalize should work")
342
- assert_equal("<foo/>", XML.renormalize_sequence(a), "XML#renormalize_sequence should work")
343
- assert_equal("<foo/><bar/>", XML.renormalize_sequence(b), "XML#renormalize_sequence should work")
344
- end
345
-
346
- # Test XML#range
347
- def test_range
348
- a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
349
- b = a.children(:bar)
350
-
351
- # Non-recursive case
352
- ar_n_n = a.range(nil, nil)
353
- ar_0_n = a.range(b[0], nil)
354
- ar_1_n = a.range(b[1], nil)
355
- ar_4_n = a.range(b[4], nil)
356
- ar_n_4 = a.range(nil, b[4])
357
- ar_n_3 = a.range(nil, b[3])
358
- ar_n_0 = a.range(nil, b[0])
359
-
360
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.to_s, "XML#range should work")
361
- assert_equal("<foo><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_0_n.to_s, "XML#range should work")
362
- assert_equal("<foo><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_1_n.to_s, "XML#range should work")
363
- assert_equal("<foo/>", ar_4_n.to_s, "XML#range should work")
364
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.to_s, "XML#range should work")
365
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.to_s, "XML#range should work")
366
- assert_equal("<foo/>", ar_n_0.to_s, "XML#range should work")
367
-
368
- a = XML.parse "<a>
369
- <b i='0'><c i='0'/><c i='1'/><c i='2'/></b>
370
- <b i='1'><c i='3'/><c i='4'/><c i='5'/></b>
371
- <b i='2'><c i='6'/><c i='7'/><c i='8'/></b>
372
- </a>"
373
- c = a.descendants(:c)
374
-
375
- c.each_with_index{|ci,i|
376
- c.each_with_index{|cj,j|
377
- next unless i < j
378
- ar = a.range(ci,cj)
379
- cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
380
- assert_equal(((i+1)...j).to_a, cs_present, "XML#range(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar}")
381
- }
382
- ar = a.range(ci,nil)
383
- cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
384
- assert_equal(((i+1)..8).to_a, cs_present, "XML#range(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar}")
385
-
386
- ar = a.range(nil,ci)
387
- cs_present = ar.descendants(:c).map{|n|n[:i].to_i}
388
- assert_equal((0...i).to_a, cs_present, "XML#range(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar}")
389
- }
390
- end
391
-
392
- # Test XML#subsequence
393
- def test_subsequence
394
- a = XML.parse "<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>"
395
- b = a.children(:bar)
396
-
397
- # Non-recursive case
398
- ar_n_n = a.subsequence(nil, nil)
399
- ar_0_n = a.subsequence(b[0], nil)
400
- ar_1_n = a.subsequence(b[1], nil)
401
- ar_4_n = a.subsequence(b[4], nil)
402
- ar_n_4 = a.subsequence(nil, b[4])
403
- ar_n_3 = a.subsequence(nil, b[3])
404
- ar_n_0 = a.subsequence(nil, b[0])
405
-
406
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/></foo>", ar_n_n.join, "XML#subsequence should work")
407
- assert_equal("<bar i='1'/><bar i='2'/><bar i='3'/><bar i='4'/>", ar_0_n.join, "XML#subsequence should work")
408
- assert_equal("<bar i='2'/><bar i='3'/><bar i='4'/>", ar_1_n.join, "XML#subsequence should work")
409
- assert_equal("", ar_4_n.join, "XML#subsequence should work")
410
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/><bar i='3'/></foo>", ar_n_4.join, "XML#subsequence should work")
411
- assert_equal("<foo><bar i='0'/><bar i='1'/><bar i='2'/></foo>", ar_n_3.join, "XML#subsequence should work")
412
- assert_equal("<foo/>", ar_n_0.join, "XML#subsequence should work")
413
-
414
- a = XML.parse "<a>
415
- <b j='0'><c i='0'/><c i='1'/><c i='2'/></b>
416
- <b j='1'><c i='3'/><c i='4'/><c i='5'/></b>
417
- <b j='2'><c i='6'/><c i='7'/><c i='8'/></b>
418
- </a>"
419
- c = a.descendants(:c)
420
-
421
- # (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}
422
- # instead of ar.descendants(:c) because
423
- # we might have returned [<c i='?'/>] as a result,
424
- # and then it's not a descendant of the result then.
425
- # This is ugly, and it should be fixed somewhere in magic/xml
426
- c.each_with_index{|ci,i|
427
- c.each_with_index{|cj,j|
428
- next unless i < j
429
- ar = a.subsequence(ci,cj)
430
- cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
431
- assert_equal(((i+1)...j).to_a, cs_present, "XML#subsequence(c#{i}, c#{j}) should contain cs between #{i} and #{j}, exclusive, instead got: #{ar.join}")
432
- }
433
- ar = a.subsequence(ci,nil)
434
- cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
435
- assert_equal(((i+1)..8).to_a, cs_present, "XML#subsequence(c#{i}, nil) should contain cs from #{i+1} to 8, instead got: #{ar.join}")
436
-
437
- ar = a.subsequence(nil,ci)
438
- cs_present = (ar + ar.descendants).find_all{|x| x.is_a? XML and x.name == :c}.map{|n| n[:i].to_i}
439
- assert_equal((0...i).to_a, cs_present, "XML#subsequence(nil, c#{i}) should contain cs from 0 to #{i-1}, instead got: #{ar.join}")
440
- }
441
- end
442
-
443
- # Test xml! at top level
444
- def test_xml_bang
445
- real_stdout = $stdout
446
- $stdout = StringIO.new
447
- xml!(:foo)
448
- assert_equal("<foo/>", $stdout.string, "xml! should work")
449
-
450
- $stdout = StringIO.new
451
- XML.bar!
452
- assert_equal("<bar/>", $stdout.string, "XML#foo! should work")
453
- $stdout = real_stdout
454
- end
455
-
456
- # Methods XML#foo! are all catched,
457
- # but how about other methods ?
458
- def test_real_method_missing
459
- foo = XML.new(:foo)
460
- exception_raised = false
461
- begin
462
- foo.bar()
463
- rescue NoMethodError
464
- exception_raised = true
465
- end
466
- # FIXME: There are other assertions than assert_equal ;-)
467
- assert_equal(true, exception_raised, "XML#bar should raise NoMethodError")
468
- end
469
-
470
- # Test XML#parse_as_twigs interface
471
- def test_parse_as_twigs
472
- stream = "<foo><p><ul><li>1</li><li>2</li><li>3</li></ul></p><p><br/></p><p/><p><bar/></p></foo>"
473
- i = 0
474
- results = []
475
- XML.parse_as_twigs(stream) {|n|
476
- n.complete! if i == 1 or i == 3
477
- results << n
478
- i += 1
479
- }
480
- assert_equal("<foo/>", results[0].to_s, "XML.parse_as_twigs should work")
481
- assert_equal("<p><ul><li>1</li><li>2</li><li>3</li></ul></p>", results[1].to_s, "XML.parse_as_twigs should work")
482
- assert_equal("<p/>", results[2].to_s, "XML.parse_as_twigs should work")
483
- assert_equal("<br/>", results[3].to_s, "XML.parse_as_twigs should work")
484
- assert_equal("<p/>", results[4].to_s, "XML.parse_as_twigs should work")
485
- assert_equal("<p/>", results[5].to_s, "XML.parse_as_twigs should work")
486
- assert_equal("<bar/>", results[6].to_s, "XML.parse_as_twigs should work")
487
- assert_equal(7, results.size, "XML.parse_as_twigs should work")
488
- end
489
-
490
- # Test XML#inspect
491
- def test_inpsect
492
- a = xml(:a, xml(:b, xml(:c)))
493
- d = xml(:d)
494
-
495
- assert_equal("<a>...</a>", a.inspect, "XML#inspect should work")
496
- assert_equal("<a>...</a>", a.inspect(0), "XML#inspect(levels) should work")
497
- assert_equal("<a><b>...</b></a>", a.inspect(1), "XML#inspect(levels) should work")
498
- assert_equal("<a><b><c/></b></a>", a.inspect(2), "XML#inspect(levels) should work")
499
- assert_equal("<a><b><c/></b></a>", a.inspect(3), "XML#inspect(levels) should work")
500
- assert_equal("<d/>", d.inspect, "XML#inspect should work")
501
- assert_equal("<d/>", d.inspect(0), "XML#inspect should work")
502
- assert_equal("<d/>", d.inspect(1), "XML#inspect should work")
503
- end
504
-
505
- # Test XML#[:@foo] pseudoattributes
506
- def test_pseudoattributes_read
507
- # Ignore the second <x>...</x>
508
- a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
509
-
510
- assert_equal("10", a[:x], "XML#[] real attributes should work")
511
- assert_nil(a[:y], "XML#[] real attributes should work")
512
- assert_nil(a[:z], "XML#[] real attributes should work")
513
- assert_equal("20", a[:@x], "XML#[] pseudoattributes should work")
514
- assert_equal("30", a[:@y], "XML#[] pseudoattributes should work")
515
- assert_nil(a[:@z], "XML#[] pseudoattributes should work")
516
- end
517
-
518
- # Test XML#[:@foo] pseudoattributes
519
- def test_pseudoattributes_write
520
- # Ignore the second <x>...</x>
521
- a = XML.parse("<foo x='10'><x>20</x><y>30</y><x>40</x></foo>")
522
-
523
- a[:x] = 100
524
- a[:y] = 200
525
- a[:z] = 300
526
- a[:@x] = 1000
527
- a[:@y] = 2000
528
- a[:@z] = 3000
529
-
530
- assert_equal("<foo x='100' y='200' z='300'><x>1000</x><y>2000</y><x>40</x><z>3000</z></foo>", a.to_s, "XML#[]= pseudoattributes should work")
531
- end
532
-
533
- # Test entity unescaping
534
- def test_entities
535
- a = XML.parse("<foo>&#xA5;&#xFC;&#x2020;</foo>")
536
- b = XML.parse("<foo>&#165;&#252;&#8224;</foo>")
537
- c = XML.parse("<foo>&yen;&uuml;&dagger;</foo>")
538
- d = ""
539
-
540
- assert_equal(b.text, a.text, "Entity unescaping on XML#Parse should work")
541
- assert_equal(c.text, a.text, "Entity unescaping on XML#Parse should work")
542
-
543
- assert_equal(b.to_s, a.to_s, "Entity escaping on XML#to_s should work")
544
- assert_equal(c.to_s, a.to_s, "Entity escaping on XML#to_s should work")
545
-
546
- # The escapes assume \XXX are byte escapes and the encoding is UTF-8
547
- assert_equal("\302\245\303\274\342\200\240", a.text, "Entity unescaping on XML#Parse should work")
548
- assert_equal("<foo>\302\245\303\274\342\200\240</foo>", a.to_s, "Entity escaping on XML#to_s should work")
549
- end
550
-
551
- # Test patterns support
552
- def test_patterns
553
- a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
554
- a.normalize!
555
-
556
- blue = []
557
- nocolor = []
558
- bar = []
559
- #hello = []
560
-
561
- a.descendants {|d|
562
- case d
563
- when :bar
564
- bar << d
565
- end
566
-
567
- case d
568
- when {:color => 'blue'}
569
- blue << d
570
- end
571
-
572
- case d
573
- when {:color => nil}
574
- nocolor << d
575
- end
576
-
577
- #case d
578
- #when /Hello/
579
- # hello << d
580
- #end
581
- }
582
-
583
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
584
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
585
- assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
586
- # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
587
- #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
588
- end
589
-
590
- # Test pattern support in #descendants (works the same way in #children)
591
- def test_patterns_2
592
- a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl color='blue'>!</excl></foo>"
593
- a.normalize!
594
-
595
- bar = a.descendants(:bar)
596
- blue = a.descendants({:color=>'blue'})
597
- blue_bar = a.descendants(all(:bar, {:color=>'blue'}))
598
- #hello = a.descendants(/Hello/)
599
- xml = a.descendants(XML)
600
- string = a.descendants(String)
601
-
602
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
603
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<excl color='blue'>!</excl>")], blue, "Pattern matching should work")
604
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue_bar, "Pattern matching should work")
605
- # Commented out, as it requires overloading Regexp#=~ and therefore Binding.of_caller
606
- #assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
607
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>"), XML.parse("<excl color='blue'>!</excl>")], xml, "Pattern matching should work")
608
- assert_equal(['Hello', ', ', 'world', '!'], string, "Pattern matching should work")
609
- end
610
-
611
- # Test patterns =~ support
612
- def test_patterns_3
613
- a = XML.parse "<foo><bar color='blue'>Hello</bar>, <bar color='red'>world</bar><excl>!</excl></foo>"
614
- a.normalize!
615
-
616
- blue = []
617
- nocolor = []
618
- bar = []
619
- hello = []
620
-
621
- a.descendants{|d|
622
- if d.is_a?(XML) and d =~ :bar
623
- bar << d
624
- end
625
-
626
- if d =~ {:color => 'blue'}
627
- blue << d
628
- end
629
-
630
- if d =~ {:color => nil}
631
- nocolor << d
632
- end
633
-
634
- if d =~ /Hello/
635
- hello << d
636
- end
637
- }
638
-
639
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), XML.parse("<bar color='red'>world</bar>")], bar, "Pattern matching should work")
640
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>")], blue, "Pattern matching should work")
641
- assert_equal([XML.parse("<excl>!</excl>")], nocolor, "Pattern matching should work")
642
- assert_equal([XML.parse("<bar color='blue'>Hello</bar>"), "Hello"], hello, "Pattern matching should work")
643
- end
644
-
645
- def test_patterns_any_all
646
- a = XML.parse "<foo>
647
- <bar color='blue' size='big'>1</bar>
648
- <bar color='blue'>2</bar>
649
- <bar color='blue' size='normal'>3</bar>
650
- <bar color='red' size='big'>4</bar>
651
- <bar color='red'>5</bar>
652
- <bar color='red' size='normal'>6</bar>
653
- </foo>"
654
-
655
- p = all({:color => 'red'}, any({:size => nil}, {:size => 'normal'}))
656
- # Select childern which color red and size either normal or not specified
657
- b = a.children(p)
658
- c = a.find_all{|x| x =~ p }
659
- d = a.find_all{|x| p === x }
660
-
661
- assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", b.join, "Pattern matching with any/all should work")
662
- assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", c.join, "Pattern matching with any/all should work")
663
- assert_equal("<bar color='red'>5</bar><bar color='red' size='normal'>6</bar>", d.join, "Pattern matching with any/all should work")
664
- end
665
-
666
- # Test parse option :ignore_pretty_printing
667
- def test_remove_pretty_printing
668
- a = "<foo><bar>100</bar><bar>200</bar></foo>"
669
- b = "<foo>
670
- <bar>
671
- 100
672
- </bar>
673
- <bar>
674
- 200
675
- </bar>
676
- </foo>"
677
- c = XML.parse(a)
678
- d = XML.parse(b)
679
- e = XML.parse(b)
680
- e.remove_pretty_printing!
681
-
682
- assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
683
- assert_equal(c.to_s, e.to_s, "XML#remove_pretty_printing! should work")
684
-
685
- f = XML.parse("<foo> <bar>Hello world</bar> </foo>")
686
- f.remove_pretty_printing!
687
- g = XML.parse("<foo><bar>Hello world</bar></foo>")
688
- assert_equal(f.to_s, g.to_s, "XML#remove_pretty_printing! should work")
689
- end
690
-
691
- # Test remove_pretty_printing! with exception list
692
- def test_remove_pretty_printing_conditional
693
- a = "<foo>
694
- <pre>
695
- <a> 100 </a>
696
- </pre>
697
- <xyzzy>
698
- <a> 200 </a>
699
- </xyzzy>
700
- </foo>"
701
- b = "<foo><pre>
702
- <a> 100 </a>
703
- </pre><xyzzy><a>200</a></xyzzy></foo>"
704
-
705
- ax = XML.parse(a)
706
- bx = XML.parse(b)
707
-
708
- ax.remove_pretty_printing!([:pre])
709
-
710
- assert_equal(bx.to_s, ax.to_s, "XML#remove_pretty_printing!(exceptions) should work")
711
- end
712
-
713
- # Test extra arguments to XML#parse - :comments and :pi
714
- def test_parsing_extras
715
- a = "<foo><?xml-stylesheet href='http://www.blogger.com/styles/atom.css' type='text/css'?></foo>"
716
- b = "<foo><!-- This is a comment --></foo>"
717
-
718
- ax = XML.parse(a)
719
- bx = XML.parse(b)
720
-
721
- assert_equal("<foo/>", ax.to_s, "XML#parse should drop PI by default")
722
- assert_equal("<foo/>", bx.to_s, "XML#parse should drop comments by default")
723
-
724
- ay = XML.parse(a, :comments => true, :pi => true)
725
- by = XML.parse(b, :comments => true, :pi => true)
726
-
727
- assert_equal(a, ay.to_s, "XML#parse(str, :pi=>true) should include PI")
728
- assert_equal(b, by.to_s, "XML#parse(str, :comments=>true) should include comments")
729
- end
730
-
731
- # Test extra arguments to XML#parse - :remove_pretty_printing.
732
- # FIXME: How about a shorter (but still mnemonic) name for that ?
733
- def test_parsing_nopp
734
- a = "<foo><bar>100</bar><bar>200</bar></foo>"
735
- b = "<foo>
736
- <bar>
737
- 100
738
- </bar>
739
- <bar>
740
- 200
741
- </bar>
742
- </foo>"
743
- c = XML.parse(a)
744
- d = XML.parse(b)
745
- e = XML.parse(b, :remove_pretty_printing => true)
746
-
747
- assert_not_equal(c.to_s, d.to_s, "XML#parse should not ignore pretty printing by default")
748
- assert_equal(c.to_s, e.to_s, "XML#parse(str, :remove_pretty_printing=>true) should work")
749
- end
750
-
751
- # Test XML.parse(str, :extra_entities => ...)
752
- def test_parsing_entities
753
- a = "<foo>&cat; &amp; &dog;</foo>"
754
- b = XML.parse(a, :extra_entities => lambda{|e|
755
- case e
756
- when "cat"
757
- "neko"
758
- when "dog"
759
- "inu"
760
- end
761
- })
762
- c = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
763
-
764
- assert_equal("neko & inu", b.text, "XML#parse(str, :extra_entities=>Proc) should work")
765
- assert_equal("neko & inu", c.text, "XML#parse(str, :extra_entities=>Hash) should work")
766
-
767
- d = XML.parse(a, :extra_entities => {"cat" => "neko", "dog" => "inu"})
768
-
769
- # Central European characters escapes
770
- e = "<foo>&zdot;&oacute;&lstrok;w</foo>"
771
- f = XML.parse(e, :extra_entities => {"zdot" => 380, "oacute" => 243, "lstrok" => 322})
772
-
773
- # Assumes \number does bytes, UTF8
774
- assert_equal("\305\274\303\263\305\202w", f.text, "XML#parse(str, :extra_entities=>...) should work with integer codepoints")
775
- end
776
-
777
- # Test XML.load
778
- def test_load
779
- a = XML.load("test.xml")
780
- b = XML.load(File.open("test.xml"))
781
- c = XML.load("string:<foo><bar></bar></foo>")
782
- d = XML.load("file:test.xml")
783
-
784
- assert_equal("<foo><bar/></foo>", a.to_s, "XML#load should work")
785
- assert_equal("<foo><bar/></foo>", b.to_s, "XML#load should work")
786
- assert_equal("<foo><bar/></foo>", c.to_s, "XML#load should work")
787
- assert_equal("<foo><bar/></foo>", d.to_s, "XML#load should work")
788
- end
789
-
790
- # Test multielement selectors
791
- def test_multielement_selectors
792
- a = XML.parse("<foo><bar color='blue'><x/></bar><bar color='red'><x><y i='1'/></x><y i='2'/></bar></foo>")
793
- assert_equal("<x/><x><y i='1'/></x>", a.children(:bar, :x).join, "Multielement selectors should work")
794
- assert_equal("<y i='2'/>", a.children(:bar, :y).join, "Multielement selectors should work")
795
- assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).join, "Multielement selectors should work")
796
- assert_equal("<y i='1'/>", a.descendants(:x, :y).join, "Multielement selectors should work")
797
- assert_equal("<y i='1'/><y i='2'/>", a.children(:bar, :*, :y).join, "Multielement selectors should work")
798
- end
799
-
800
- # Test deep_map
801
- def test_deep_map
802
- a = XML.parse("<foo><bar>x</bar> <foo><bar>y</bar></foo></foo>")
803
- b = a.deep_map(:bar) {|c| XML.new(c.text.to_sym) }
804
- assert_equal("<foo><x/> <foo><y/></foo></foo>", b.to_s, "XML#deep_map should work")
805
-
806
- c = XML.parse("<foo><bar>x</bar> <bar><bar>y</bar></bar></foo>")
807
- d = c.deep_map(:bar) {|c| XML.new(:xyz, c.attrs, *c.children) }
808
- assert_equal("<foo><xyz>x</xyz> <xyz><bar>y</bar></xyz></foo>", d.to_s, "XML#deep_map should work")
809
- end
810
-
811
- # Test XML.load
812
- def test_pretty_printer
813
- a = XML.parse("<foo><bar>x</bar>Boo!<bar><y><z>f</z></y></bar><xyzzy /><bar>Mutiline\nText\n:-)</bar></foo>")
814
- a.add_pretty_printing!
815
- expected = "<foo>
816
- <bar>
817
- x
818
- </bar>
819
- Boo!
820
- <bar>
821
- <y>
822
- <z>
823
- f
824
- </z>
825
- </y>
826
- </bar>
827
- <xyzzy/>
828
- <bar>
829
- Mutiline
830
- Text
831
- :-)
832
- </bar>
833
- </foo>"
834
- assert_equal(expected, a.to_s, "XML#pretty_print! should work")
835
- end
836
- end