libxml-fixed-jruby 1.0.0-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +91 -0
  3. data/README.txt +50 -0
  4. data/Rakefile +40 -0
  5. data/lib/libxml-jruby.rb +84 -0
  6. data/lib/libxml-jruby/xml.rb +1 -0
  7. data/lib/libxml-jruby/xml/attr.rb +46 -0
  8. data/lib/libxml-jruby/xml/attributes.rb +68 -0
  9. data/lib/libxml-jruby/xml/document.rb +52 -0
  10. data/lib/libxml-jruby/xml/dtd.rb +25 -0
  11. data/lib/libxml-jruby/xml/node.rb +285 -0
  12. data/lib/libxml-jruby/xml/ns.rb +19 -0
  13. data/lib/libxml-jruby/xml/parser.rb +121 -0
  14. data/lib/libxml-jruby/xml/xpath.rb +98 -0
  15. data/lib/libxml.rb +1 -0
  16. data/lib/xml.rb +13 -0
  17. data/lib/xml/libxml.rb +8 -0
  18. data/script/benchmark/depixelate.rb +633 -0
  19. data/script/benchmark/hamlet.xml +9055 -0
  20. data/script/benchmark/sock_entries.xml +507 -0
  21. data/script/benchmark/throughput.rb +40 -0
  22. data/script/benchmark/xml_benchmarks.rb +228 -0
  23. data/script/test +6 -0
  24. data/tasks/ann.rake +81 -0
  25. data/tasks/bones.rake +21 -0
  26. data/tasks/gem.rake +126 -0
  27. data/tasks/git.rake +41 -0
  28. data/tasks/manifest.rake +49 -0
  29. data/tasks/notes.rake +28 -0
  30. data/tasks/post_load.rake +39 -0
  31. data/tasks/rdoc.rake +51 -0
  32. data/tasks/rubyforge.rake +57 -0
  33. data/tasks/setup.rb +268 -0
  34. data/tasks/spec.rake +55 -0
  35. data/tasks/svn.rake +48 -0
  36. data/tasks/test.rake +38 -0
  37. data/test/etc_doc_to_s.rb +19 -0
  38. data/test/ets_copy_bug.rb +21 -0
  39. data/test/ets_copy_bug3.rb +38 -0
  40. data/test/ets_doc_file.rb +15 -0
  41. data/test/ets_doc_to_s.rb +21 -0
  42. data/test/ets_gpx.rb +26 -0
  43. data/test/ets_node_gc.rb +21 -0
  44. data/test/ets_test.xml +2 -0
  45. data/test/ets_tsr.rb +9 -0
  46. data/test/model/books.xml +147 -0
  47. data/test/model/default_validation_bug.rb +0 -0
  48. data/test/model/merge_bug_data.xml +58 -0
  49. data/test/model/rubynet.xml +78 -0
  50. data/test/model/rubynet_project +1 -0
  51. data/test/model/saxtest.xml +5 -0
  52. data/test/model/shiporder.rnc +28 -0
  53. data/test/model/shiporder.rng +86 -0
  54. data/test/model/shiporder.xml +23 -0
  55. data/test/model/shiporder.xsd +31 -0
  56. data/test/model/simple.xml +7 -0
  57. data/test/model/soap.xml +27 -0
  58. data/test/model/xinclude.xml +5 -0
  59. data/test/tc_attributes.rb +110 -0
  60. data/test/tc_deprecated_require.rb +13 -0
  61. data/test/tc_document.rb +97 -0
  62. data/test/tc_document_write.rb +139 -0
  63. data/test/tc_dtd.rb +70 -0
  64. data/test/tc_html_parser.rb +63 -0
  65. data/test/tc_node.rb +108 -0
  66. data/test/tc_node_attr.rb +176 -0
  67. data/test/tc_node_cdata.rb +51 -0
  68. data/test/tc_node_comment.rb +32 -0
  69. data/test/tc_node_copy.rb +40 -0
  70. data/test/tc_node_edit.rb +98 -0
  71. data/test/tc_node_set.rb +24 -0
  72. data/test/tc_node_set2.rb +37 -0
  73. data/test/tc_node_text.rb +17 -0
  74. data/test/tc_node_xlink.rb +28 -0
  75. data/test/tc_ns.rb +18 -0
  76. data/test/tc_parser.rb +308 -0
  77. data/test/tc_parser_context.rb +126 -0
  78. data/test/tc_properties.rb +37 -0
  79. data/test/tc_reader.rb +112 -0
  80. data/test/tc_relaxng.rb +39 -0
  81. data/test/tc_sax_parser.rb +113 -0
  82. data/test/tc_schema.rb +39 -0
  83. data/test/tc_traversal.rb +220 -0
  84. data/test/tc_well_formed.rb +11 -0
  85. data/test/tc_xinclude.rb +26 -0
  86. data/test/tc_xpath.rb +130 -0
  87. data/test/tc_xpath_context.rb +72 -0
  88. data/test/tc_xpointer.rb +78 -0
  89. data/test/test_libxml-jruby.rb +0 -0
  90. data/test/test_suite.rb +31 -0
  91. data/test/ts_working.rb +31 -0
  92. metadata +146 -0
@@ -0,0 +1,37 @@
1
+ require "xml"
2
+ require 'test/unit'
3
+
4
+ # Properties is deprecated - use attributes instead.
5
+ # Tests for backwards compatibility
6
+
7
+ class TestProperties < Test::Unit::TestCase
8
+ def setup()
9
+ xp = XML::Parser.string('<ruby_array uga="booga" foo="bar"><fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>')
10
+ @doc = xp.parse
11
+ end
12
+
13
+ def teardown()
14
+ @doc = nil
15
+ end
16
+
17
+ def test_traversal
18
+ properties = @doc.root.properties
19
+
20
+ assert_instance_of(XML::Attributes, properties)
21
+ # FIXME ordering of Attributes
22
+ # attribute = properties.first
23
+ # assert_equal('uga', attribute.name)
24
+ # assert_equal('booga', attribute.value)
25
+ #
26
+ # attribute = attribute.next
27
+ # assert_instance_of(XML::Attr, attribute)
28
+ # assert_equal('foo', attribute.name)
29
+ # assert_equal('bar', attribute.value)
30
+ end
31
+
32
+ def test_no_properties
33
+ properties = @doc.root.child.properties
34
+ assert_instance_of(XML::Attributes, properties)
35
+ assert_equal(0, properties.length)
36
+ end
37
+ end
@@ -0,0 +1,112 @@
1
+ require 'xml'
2
+ require 'test/unit'
3
+
4
+ class TC_XML_Reader < Test::Unit::TestCase
5
+
6
+ SIMPLE_XML = File.join(File.dirname(__FILE__), 'model/simple.xml')
7
+
8
+ def test_new_file
9
+ reader = XML::Reader.file(SIMPLE_XML)
10
+ verify_simple(reader)
11
+ assert_raises(RuntimeError) { XML::Reader.file('/does/not/exist') }
12
+ end
13
+
14
+ def test_new_data
15
+ reader = XML::Reader.new(File.read(SIMPLE_XML))
16
+ verify_simple(reader)
17
+ end
18
+
19
+ def test_new_walker
20
+ reader = XML::Reader.walker(XML::Document.file(SIMPLE_XML))
21
+ verify_simple(reader)
22
+ end
23
+
24
+ def test_reader_error
25
+ reader = XML::Reader.new('<foo/>')
26
+ assert_raises(RuntimeError) { reader.set_error_handler }
27
+ called = false
28
+ reader.set_error_handler { |*a| called = true }
29
+ while reader.read > 0; end
30
+ assert(!called)
31
+ reader = XML::Reader.new('<foo blah')
32
+ reader.set_error_handler do |*a|
33
+ assert_equal(5, a.size)
34
+ assert_equal(reader, a[0])
35
+ assert_equal(XML::Reader::SEVERITY_ERROR, a[2])
36
+ assert_nil(a[3])
37
+ assert_equal(1, a[4])
38
+ called = true
39
+ end
40
+ while reader.read > 0; end
41
+ assert(called)
42
+ end
43
+
44
+ def test_attr
45
+ parser = XML::Reader.new("<foo x='1' y='2'/>")
46
+ assert_equal(1, parser.read)
47
+ assert_equal('foo', parser.name)
48
+ assert_equal('1', parser['x'])
49
+ assert_equal('1', parser[0])
50
+ assert_equal('2', parser['y'])
51
+ assert_equal('2', parser[1])
52
+ assert_equal(nil, parser['z'])
53
+ assert_equal(nil, parser[2])
54
+ end
55
+
56
+ def test_value
57
+ parser = XML::Reader.new("<foo><bar>1</bar><bar>2</bar><bar>3</bar></foo>")
58
+ assert_equal(1, parser.read)
59
+ assert_equal('foo', parser.name)
60
+ assert_equal(nil, parser.value)
61
+ 3.times do |i|
62
+ assert_equal(1, parser.read)
63
+ assert_equal(XML::Reader::TYPE_ELEMENT, parser.node_type)
64
+ assert_equal('bar', parser.name)
65
+ assert_equal(1, parser.read)
66
+ assert_equal(XML::Reader::TYPE_TEXT, parser.node_type)
67
+ assert_equal((i + 1).to_s, parser.value)
68
+ assert_equal(1, parser.read)
69
+ assert_equal(XML::Reader::TYPE_END_ELEMENT, parser.node_type)
70
+ end
71
+ end
72
+
73
+ def test_expand
74
+ reader = XML::Reader.file(SIMPLE_XML)
75
+ reader.read
76
+ node = reader.expand
77
+ doc = node.doc
78
+ reader.close
79
+ GC.start
80
+
81
+ doc.standalone?
82
+ end
83
+
84
+ def verify_simple(reader)
85
+ node_types = []
86
+ 19.times do
87
+ assert_equal(1, reader.read)
88
+ node_types << reader.node_type
89
+ end
90
+ assert_equal(0, reader.read)
91
+ assert_equal(node_types,
92
+ [XML::Reader::TYPE_ELEMENT,
93
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
94
+ XML::Reader::TYPE_ELEMENT,
95
+ XML::Reader::TYPE_TEXT,
96
+ XML::Reader::TYPE_END_ELEMENT,
97
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
98
+ XML::Reader::TYPE_ELEMENT,
99
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
100
+ XML::Reader::TYPE_ELEMENT,
101
+ XML::Reader::TYPE_TEXT,
102
+ XML::Reader::TYPE_END_ELEMENT,
103
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
104
+ XML::Reader::TYPE_ELEMENT,
105
+ XML::Reader::TYPE_TEXT,
106
+ XML::Reader::TYPE_END_ELEMENT,
107
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
108
+ XML::Reader::TYPE_END_ELEMENT,
109
+ XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
110
+ XML::Reader::TYPE_END_ELEMENT])
111
+ end
112
+ end
@@ -0,0 +1,39 @@
1
+ require "xml"
2
+ require 'test/unit'
3
+
4
+ class TestRelaxNG < Test::Unit::TestCase
5
+ def setup
6
+ xp = XML::Parser.new
7
+ @doc = XML::Document.file(File.join(File.dirname(__FILE__), 'model/shiporder.xml'))
8
+ end
9
+
10
+ def teardown
11
+ @doc = nil
12
+ end
13
+
14
+ def relaxng
15
+ document = XML::Document.file(File.join(File.dirname(__FILE__), 'model/shiporder.rng'))
16
+ relaxng = XML::RelaxNG.document(document)
17
+ end
18
+
19
+ def test_from_doc
20
+ assert_instance_of(XML::RelaxNG, relaxng)
21
+ end
22
+
23
+ def test_valid
24
+ assert(@doc.validate_relaxng(relaxng))
25
+ end
26
+
27
+ def test_invalid
28
+ new_node = XML::Node.new('invalid', 'this will mess up validation')
29
+ @doc.root.child_add(new_node)
30
+
31
+ messages = Hash.new
32
+ assert(!@doc.validate_relaxng(relaxng) do |message, error|
33
+ messages[message] = error
34
+ end)
35
+
36
+ expected = {"Did not expect element invalid there\n" => true}
37
+ assert_equal(expected, messages)
38
+ end
39
+ end
@@ -0,0 +1,113 @@
1
+ require 'xml'
2
+ require 'test/unit'
3
+
4
+ # TODO this is woefully inadequate
5
+
6
+ class TestCaseCallbacks
7
+ include XML::SaxParser::Callbacks
8
+
9
+ attr_accessor :test
10
+
11
+ def initialize
12
+ @test = Hash.new { |h,k| h[k] = [] }
13
+ @i = 0
14
+ end
15
+
16
+ def on_start_document
17
+ @test[:startdoc] << @i+=1
18
+ end
19
+
20
+ def on_start_element(name, attr_hash)
21
+ @test[:startel] << [@i+=1,name,attr_hash]
22
+ end
23
+
24
+ def on_characters(chars)
25
+ @test[:chars] << [@i+=1,chars]
26
+ end
27
+
28
+ def on_comment(msg)
29
+ @test[:comment] << [@i+=1,msg]
30
+ end
31
+
32
+ def on_processing_instruction(target, data)
33
+ @test[:pinstr] << [@i+=1, target, data]
34
+ end
35
+
36
+ def on_cdata_block(cdata)
37
+ @test[:cdata] << [@i+=1,cdata]
38
+ end
39
+
40
+ def on_end_element(name)
41
+ @test[:endel] << [@i+=1,name]
42
+ end
43
+
44
+ def on_end_document
45
+ @test[:enddoc] << @i+=1
46
+ end
47
+ end
48
+
49
+ class TestSaxParser < Test::Unit::TestCase
50
+ def setup
51
+ @xp = XML::SaxParser.new
52
+ end
53
+
54
+ def teardown
55
+ @xp = nil
56
+ end
57
+
58
+ def verify
59
+ @xp.parse
60
+ assert_equal [1], @xp.callbacks.test[:startdoc]
61
+ assert_equal [[2,'test',{'uga'=>'booga','foo'=>'bar'}],[3,'fixnum',{}],[6,'fixnum',{}]],
62
+ @xp.callbacks.test[:startel]
63
+ assert_equal [[4,'one'],[7,'two'],[9,"\n "],[11,"\n "],[13,"\n "],[15,"\n"]],
64
+ @xp.callbacks.test[:chars]
65
+ assert_equal [[10, ' msg ']], @xp.callbacks.test[:comment]
66
+ assert_equal [[12, 'custom', 'foo="bar"']], @xp.callbacks.test[:pinstr]
67
+ assert_equal [[14, 'here it goes']], @xp.callbacks.test[:cdata]
68
+ assert_equal [[5,'fixnum'],[8,'fixnum'],[16,'test']], @xp.callbacks.test[:endel]
69
+ assert_equal [17], @xp.callbacks.test[:enddoc]
70
+ end
71
+
72
+ def test_string_without_callbacks
73
+ @xp.string = File.read(File.join(File.dirname(__FILE__), 'model/saxtest.xml'))
74
+ assert_equal true, @xp.parse
75
+ end
76
+
77
+ def test_file_without_callbacks
78
+ @xp.filename = File.join(File.dirname(__FILE__), 'model/saxtest.xml')
79
+ assert_equal true, @xp.parse
80
+ end
81
+
82
+ def test_callbacks_with_string
83
+ @xp.callbacks = TestCaseCallbacks.new
84
+ @xp.string = File.read(File.join(File.dirname(__FILE__), 'model/saxtest.xml'))
85
+ verify
86
+ end
87
+
88
+ def test_callbacks_with_file
89
+ @xp.callbacks = TestCaseCallbacks.new
90
+ @xp.filename = File.join(File.dirname(__FILE__), 'model/saxtest.xml')
91
+ verify
92
+ end
93
+
94
+ class DocTypeCallback
95
+ include XML::SaxParser::Callbacks
96
+ def on_start_element(element, attributes)
97
+ puts element
98
+ end
99
+ end
100
+
101
+ def test_doctype
102
+ @xp.callbacks = DocTypeCallback.new
103
+ @xp.string = <<-EOS
104
+ <?xml version="1.0" encoding="UTF-8"?>
105
+ <!DOCTYPE Results SYSTEM "results.dtd">
106
+ <Results>
107
+ <a>a1</a>
108
+ </Results>
109
+ EOS
110
+ doc = @xp.parse
111
+ assert_not_nil(doc)
112
+ end
113
+ end
@@ -0,0 +1,39 @@
1
+ require "xml"
2
+ require 'test/unit'
3
+
4
+ class TestSchema < Test::Unit::TestCase
5
+ def setup
6
+ xp = XML::Parser.new
7
+ @doc = XML::Document.file(File.join(File.dirname(__FILE__), 'model/shiporder.xml'))
8
+ end
9
+
10
+ def teardown
11
+ @doc = nil
12
+ end
13
+
14
+ def schema
15
+ document = XML::Document.file(File.join(File.dirname(__FILE__), 'model/shiporder.xsd'))
16
+ schema = XML::Schema.document(document)
17
+ end
18
+
19
+ def test_from_doc
20
+ assert_instance_of(XML::Schema, schema)
21
+ end
22
+
23
+ def test_valid
24
+ assert(@doc.validate_schema(schema))
25
+ end
26
+
27
+ def test_invalid
28
+ new_node = XML::Node.new('invalid', 'this will mess up validation')
29
+ @doc.root.child_add(new_node)
30
+
31
+ messages = Hash.new
32
+ assert(!@doc.validate_schema(schema) do |message, error|
33
+ messages[message] = error
34
+ end)
35
+
36
+ expected = {"Element 'invalid': This element is not expected. Expected is ( item ).\n" => true}
37
+ assert_equal(expected, messages)
38
+ end
39
+ end
@@ -0,0 +1,220 @@
1
+ require 'xml'
2
+ require 'test/unit'
3
+
4
+ class TestTranversal < Test::Unit::TestCase
5
+ ROOT_NODES_LENGTH = 25
6
+ ROOT_ELEMENTS_LENGTH = 12
7
+
8
+ def setup
9
+ filename = File.join(File.dirname(__FILE__), 'model/books.xml')
10
+ @doc = XML::Document.file(filename)
11
+ end
12
+
13
+ def teardown
14
+ @doc = nil
15
+ end
16
+
17
+ def test_children
18
+ # Includes text nodes and such
19
+ assert_equal(ROOT_NODES_LENGTH, @doc.root.children.length)
20
+ end
21
+
22
+ def test_children_iteration
23
+ # Includes text nodes and such
24
+ nodes = @doc.root.children.inject([]) do |arr, node|
25
+ arr << node
26
+ arr
27
+ end
28
+
29
+ assert_equal(ROOT_NODES_LENGTH, nodes.length)
30
+ end
31
+
32
+ def test_each
33
+ # Includes text nodes and such
34
+ nodes = @doc.root.inject([]) do |arr, node|
35
+ arr << node
36
+ arr
37
+ end
38
+
39
+ assert_equal(ROOT_NODES_LENGTH, nodes.length)
40
+ end
41
+
42
+ def test_each_element
43
+ # Includes text nodes and such
44
+ nodes = []
45
+ @doc.root.each_element do |node|
46
+ nodes << node
47
+ end
48
+
49
+ assert_equal(ROOT_ELEMENTS_LENGTH, nodes.length)
50
+ end
51
+
52
+ def test_next
53
+ nodes = []
54
+
55
+ node = @doc.root.first
56
+
57
+ while node
58
+ nodes << node
59
+ node = node.next
60
+ end
61
+ assert_equal(ROOT_NODES_LENGTH, nodes.length)
62
+ end
63
+
64
+ def test_next?
65
+ first_node = @doc.root.first
66
+ assert(first_node.next?)
67
+
68
+ last_node = @doc.root.last
69
+ assert(!last_node.next?)
70
+ end
71
+
72
+ def test_prev
73
+ nodes = []
74
+
75
+ node = @doc.root.last
76
+
77
+ while node
78
+ nodes << node
79
+ node = node.prev
80
+ end
81
+ assert_equal(ROOT_NODES_LENGTH, nodes.length)
82
+ end
83
+
84
+ def test_prev?
85
+ first_node = @doc.root.first
86
+ assert(!first_node.prev?)
87
+
88
+ last_node = @doc.root.last
89
+ assert(last_node.prev?)
90
+ end
91
+
92
+ def test_parent?
93
+ assert(!@doc.parent?)
94
+ assert(@doc.root.parent?)
95
+ end
96
+
97
+ def test_child?
98
+ assert(@doc.child?)
99
+ assert(!@doc.root.first.child?)
100
+ end
101
+
102
+ def test_next_prev_equivalence
103
+ next_nodes = []
104
+ last_nodes = []
105
+
106
+ node = @doc.root.first
107
+ while node
108
+ next_nodes << node
109
+ node = node.next
110
+ end
111
+
112
+ node = @doc.root.last
113
+ while node
114
+ last_nodes << node
115
+ node = node.prev
116
+ end
117
+
118
+ assert_equal(next_nodes, last_nodes.reverse)
119
+ end
120
+
121
+ def test_next_children_equivalence
122
+ next_nodes = []
123
+
124
+ node = @doc.root.first
125
+ while node
126
+ next_nodes << node
127
+ node = node.next
128
+ end
129
+
130
+ assert_equal(@doc.root.children, next_nodes)
131
+ end
132
+
133
+ # node = @doc.find_first('book')
134
+ # node.children.each do |node|
135
+ # puts 1
136
+ #end
137
+ # @doc.root.children do |node|
138
+ # if node.node_type == XML::Node::ELEMENT_NODE
139
+ # puts node.name
140
+ #end
141
+ #end
142
+ #assert_equal(12,nodes.length)
143
+ #end
144
+
145
+ #def test_doc_class
146
+ #assert_instance_of(XML::Document, @doc)
147
+ #end
148
+
149
+ #def test_root_class
150
+ #assert_instance_of(XML::Node, @doc.root)
151
+ #end
152
+
153
+ #def test_node_class
154
+ #for n in nodes
155
+ #assert_instance_of(XML::Node, n)
156
+ #end
157
+ #end
158
+
159
+ #def test_find_class
160
+ #set = @doc.find('/ruby_array/fixnum')
161
+ #assert_instance_of(XML::XPath::Object, set)
162
+ #end
163
+
164
+ #def test_node_child_get
165
+ #assert_instance_of(TrueClass, @doc.root.child?)
166
+ #assert_instance_of(XML::Node, @doc.root.child)
167
+ #assert_equal('fixnum', @doc.root.child.name)
168
+ #end
169
+
170
+ #def test_node_doc
171
+ #for n in nodes
172
+ #assert_instance_of(XML::Document, n.doc) if n.document?
173
+ #end
174
+ #end
175
+
176
+ #def test_node_type_name
177
+ #assert_equal('element', nodes[0].node_type_name)
178
+ #assert_equal('element', nodes[1].node_type_name)
179
+ #end
180
+
181
+ #def test_node_find
182
+ #set = @doc.root.find('./fixnum').set
183
+ #assert_instance_of(XML::Node::Set, set)
184
+ #for node in set
185
+ #assert_instance_of(XML::Node, node)
186
+ #end
187
+ #end
188
+
189
+ #def test_equality
190
+ #node_a = @doc.find('/ruby_array/fixnum').first
191
+ #node_b = @doc.root.child
192
+ #assert(node_a == node_b)
193
+ #assert(node_a.eql?(node_b))
194
+ #assert(node_a.equal?(node_b))
195
+
196
+ #xp2 = XML::Parser.new()
197
+ #xp2.string = '<ruby_array uga="booga" foo="bar"><fixnum>one</fixnum><fixnum>two</fixnum></ruby_array>'
198
+ #doc2 = xp2.parse
199
+
200
+ #node_a2 = doc2.find('/ruby_array/fixnum').first
201
+
202
+ #assert(node_a.to_s == node_a2.to_s)
203
+ #assert(node_a == node_a2)
204
+ #assert(node_a.eql?(node_a2))
205
+ #assert(!node_a.equal?(node_a2))
206
+ #end
207
+
208
+ #def test_content()
209
+ #assert_equal('onetwo', @doc.root.content)
210
+
211
+ #first = @doc.root.child
212
+ #assert_equal('one', first.content)
213
+ #assert_equal('two', first.next.content)
214
+ #end
215
+
216
+ #def test_base
217
+ #doc = XML::Parser.string('<person />').parse
218
+ #assert_nil(doc.root.base)
219
+ #end
220
+ end