libxml-ruby 4.1.2 → 6.0.0

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY → CHANGELOG.md} +875 -887
  3. data/LICENSE +20 -20
  4. data/README.md +67 -0
  5. data/Rakefile +77 -98
  6. data/ext/libxml/extconf.rb +39 -20
  7. data/ext/libxml/libxml.c +67 -79
  8. data/ext/libxml/ruby_libxml.h +43 -44
  9. data/ext/libxml/ruby_xml.c +556 -899
  10. data/ext/libxml/ruby_xml.h +9 -10
  11. data/ext/libxml/ruby_xml_attr.c +338 -333
  12. data/ext/libxml/ruby_xml_attr.h +13 -12
  13. data/ext/libxml/ruby_xml_attr_decl.c +19 -12
  14. data/ext/libxml/ruby_xml_attr_decl.h +11 -11
  15. data/ext/libxml/ruby_xml_attributes.c +18 -9
  16. data/ext/libxml/ruby_xml_attributes.h +17 -15
  17. data/ext/libxml/ruby_xml_document.c +1142 -1129
  18. data/ext/libxml/ruby_xml_document.h +12 -11
  19. data/ext/libxml/ruby_xml_dtd.c +287 -248
  20. data/ext/libxml/ruby_xml_dtd.h +10 -9
  21. data/ext/libxml/ruby_xml_encoding.c +250 -250
  22. data/ext/libxml/ruby_xml_encoding.h +20 -18
  23. data/ext/libxml/ruby_xml_error.c +1003 -996
  24. data/ext/libxml/ruby_xml_error.h +14 -14
  25. data/ext/libxml/ruby_xml_html_parser.c +91 -91
  26. data/ext/libxml/ruby_xml_html_parser.h +10 -10
  27. data/ext/libxml/ruby_xml_html_parser_context.c +364 -337
  28. data/ext/libxml/ruby_xml_html_parser_context.h +11 -10
  29. data/ext/libxml/ruby_xml_html_parser_options.c +48 -48
  30. data/ext/libxml/ruby_xml_html_parser_options.h +10 -10
  31. data/ext/libxml/ruby_xml_input_cbg.c +216 -188
  32. data/ext/libxml/ruby_xml_input_cbg.h +20 -20
  33. data/ext/libxml/ruby_xml_io.c +49 -47
  34. data/ext/libxml/ruby_xml_io.h +10 -10
  35. data/ext/libxml/ruby_xml_namespace.c +159 -154
  36. data/ext/libxml/ruby_xml_namespace.h +11 -10
  37. data/ext/libxml/ruby_xml_namespaces.c +313 -293
  38. data/ext/libxml/ruby_xml_namespaces.h +9 -9
  39. data/ext/libxml/ruby_xml_node.c +1433 -1398
  40. data/ext/libxml/ruby_xml_node.h +15 -13
  41. data/ext/libxml/ruby_xml_parser.c +91 -91
  42. data/ext/libxml/ruby_xml_parser.h +10 -10
  43. data/ext/libxml/ruby_xml_parser_context.c +1016 -1001
  44. data/ext/libxml/ruby_xml_parser_context.h +11 -10
  45. data/ext/libxml/ruby_xml_parser_options.c +74 -66
  46. data/ext/libxml/ruby_xml_parser_options.h +10 -10
  47. data/ext/libxml/ruby_xml_reader.c +40 -31
  48. data/ext/libxml/ruby_xml_reader.h +14 -14
  49. data/ext/libxml/ruby_xml_registry.c +31 -0
  50. data/ext/libxml/ruby_xml_registry.h +22 -0
  51. data/ext/libxml/ruby_xml_relaxng.c +21 -5
  52. data/ext/libxml/ruby_xml_relaxng.h +9 -8
  53. data/ext/libxml/ruby_xml_sax2_handler.c +326 -326
  54. data/ext/libxml/ruby_xml_sax2_handler.h +10 -10
  55. data/ext/libxml/ruby_xml_sax_parser.c +108 -116
  56. data/ext/libxml/ruby_xml_sax_parser.h +10 -10
  57. data/ext/libxml/ruby_xml_schema.c +22 -15
  58. data/ext/libxml/ruby_xml_schema.h +26 -25
  59. data/ext/libxml/ruby_xml_schema_attribute.c +7 -7
  60. data/ext/libxml/ruby_xml_schema_attribute.h +37 -37
  61. data/ext/libxml/ruby_xml_schema_element.c +8 -8
  62. data/ext/libxml/ruby_xml_schema_element.h +11 -11
  63. data/ext/libxml/ruby_xml_schema_facet.c +50 -50
  64. data/ext/libxml/ruby_xml_schema_facet.h +9 -9
  65. data/ext/libxml/ruby_xml_schema_type.c +12 -19
  66. data/ext/libxml/ruby_xml_schema_type.h +9 -9
  67. data/ext/libxml/ruby_xml_version.h +9 -9
  68. data/ext/libxml/ruby_xml_writer.c +183 -185
  69. data/ext/libxml/ruby_xml_writer.h +6 -6
  70. data/ext/libxml/ruby_xml_xinclude.c +20 -20
  71. data/ext/libxml/ruby_xml_xinclude.h +11 -11
  72. data/ext/libxml/ruby_xml_xpath.c +195 -195
  73. data/ext/libxml/ruby_xml_xpath.h +15 -15
  74. data/ext/libxml/ruby_xml_xpath_context.c +408 -362
  75. data/ext/libxml/ruby_xml_xpath_context.h +9 -9
  76. data/ext/libxml/ruby_xml_xpath_expression.c +12 -6
  77. data/ext/libxml/ruby_xml_xpath_expression.h +11 -10
  78. data/ext/libxml/ruby_xml_xpath_object.c +69 -54
  79. data/ext/libxml/ruby_xml_xpath_object.h +19 -17
  80. data/ext/vc/libxml_ruby/libxml_ruby.vcxproj +271 -0
  81. data/ext/xcode/libxml-ruby.xcodeproj/project.pbxproj +633 -0
  82. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  83. data/ext/xcode/libxml-ruby.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  84. data/ext/xcode/libxml-ruby.xcodeproj/xcshareddata/xcschemes/libxml-ruby.xcscheme +80 -0
  85. data/lib/libxml/attr.rb +122 -122
  86. data/lib/libxml/attr_decl.rb +80 -80
  87. data/lib/libxml/attributes.rb +13 -13
  88. data/lib/libxml/document.rb +165 -194
  89. data/lib/libxml/error.rb +122 -95
  90. data/lib/libxml/html_parser.rb +80 -96
  91. data/lib/libxml/namespace.rb +61 -61
  92. data/lib/libxml/namespaces.rb +37 -37
  93. data/lib/libxml/node.rb +321 -323
  94. data/lib/libxml/parser.rb +94 -100
  95. data/lib/libxml/sax_callbacks.rb +179 -179
  96. data/lib/libxml/sax_parser.rb +40 -40
  97. data/lib/libxml/schema/attribute.rb +27 -19
  98. data/lib/libxml/schema/element.rb +20 -0
  99. data/lib/libxml/schema/type.rb +44 -21
  100. data/lib/libxml/schema.rb +47 -47
  101. data/lib/libxml/tree.rb +28 -28
  102. data/lib/libxml-ruby.rb +30 -30
  103. data/libxml-ruby.gemspec +46 -48
  104. data/test/c14n/result/1-1-without-comments/example-1 +3 -3
  105. data/test/c14n/result/1-1-without-comments/example-2 +10 -10
  106. data/test/c14n/result/1-1-without-comments/example-3 +13 -13
  107. data/test/c14n/result/1-1-without-comments/example-4 +8 -8
  108. data/test/c14n/result/1-1-without-comments/example-5 +2 -2
  109. data/test/c14n/result/with-comments/example-1 +5 -5
  110. data/test/c14n/result/with-comments/example-2 +10 -10
  111. data/test/c14n/result/with-comments/example-3 +13 -13
  112. data/test/c14n/result/with-comments/example-4 +8 -8
  113. data/test/c14n/result/with-comments/example-5 +3 -3
  114. data/test/c14n/result/without-comments/example-1 +3 -3
  115. data/test/c14n/result/without-comments/example-2 +10 -10
  116. data/test/c14n/result/without-comments/example-3 +13 -13
  117. data/test/c14n/result/without-comments/example-4 +8 -8
  118. data/test/c14n/result/without-comments/example-5 +2 -2
  119. data/test/test_attr.rb +179 -180
  120. data/test/test_attr_decl.rb +131 -131
  121. data/test/test_attributes.rb +135 -135
  122. data/test/test_canonicalize.rb +122 -120
  123. data/test/test_document.rb +138 -132
  124. data/test/test_document_write.rb +142 -145
  125. data/test/test_dtd.rb +134 -129
  126. data/test/test_encoding.rb +126 -129
  127. data/test/test_encoding_sax.rb +114 -114
  128. data/test/test_error.rb +197 -194
  129. data/test/test_helper.rb +21 -13
  130. data/test/test_html_parser.rb +166 -162
  131. data/test/test_html_parser_context.rb +22 -22
  132. data/test/test_input_callbacks.rb +36 -0
  133. data/test/test_namespace.rb +58 -60
  134. data/test/test_namespaces.rb +200 -200
  135. data/test/test_node.rb +251 -237
  136. data/test/test_node_cdata.rb +50 -50
  137. data/test/test_node_comment.rb +32 -32
  138. data/test/test_node_copy.rb +40 -40
  139. data/test/test_node_edit.rb +176 -158
  140. data/test/test_node_pi.rb +37 -37
  141. data/test/test_node_text.rb +69 -69
  142. data/test/test_node_write.rb +93 -96
  143. data/test/test_node_xlink.rb +28 -28
  144. data/test/test_parser.rb +297 -324
  145. data/test/test_parser_context.rb +198 -198
  146. data/test/test_properties.rb +38 -38
  147. data/test/test_reader.rb +413 -364
  148. data/test/test_relaxng.rb +59 -53
  149. data/test/test_sax_parser.rb +345 -326
  150. data/test/test_schema.rb +28 -0
  151. data/test/test_traversal.rb +152 -152
  152. data/test/test_writer.rb +469 -468
  153. data/test/test_xinclude.rb +20 -20
  154. data/test/test_xml.rb +164 -267
  155. data/test/test_xpath.rb +244 -244
  156. data/test/test_xpath_context.rb +87 -87
  157. data/test/test_xpath_expression.rb +37 -37
  158. metadata +49 -31
  159. data/README.rdoc +0 -217
  160. data/ext/libxml/extconf.h +0 -3
  161. data/ext/libxml/ruby_xml_cbg.c +0 -85
  162. data/lib/libxml/hpricot.rb +0 -78
  163. data/lib/libxml.rb +0 -5
  164. data/lib/xml/libxml.rb +0 -10
  165. data/lib/xml.rb +0 -14
  166. data/script/benchmark/depixelate +0 -634
  167. data/script/benchmark/hamlet.xml +0 -9055
  168. data/script/benchmark/parsecount +0 -170
  169. data/script/benchmark/sock_entries.xml +0 -507
  170. data/script/benchmark/throughput +0 -41
  171. data/script/test +0 -6
  172. data/test/test_deprecated_require.rb +0 -12
data/test/test_reader.rb CHANGED
@@ -1,364 +1,413 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './test_helper'
4
- require 'stringio'
5
-
6
- class TestReader < Minitest::Test
7
- XML_FILE = File.join(File.dirname(__FILE__), 'model/atom.xml')
8
-
9
- def verify_simple(reader)
10
- node_types = []
11
-
12
- # Read each node
13
- 26.times do
14
- assert(reader.read)
15
- node_types << reader.node_type
16
- end
17
-
18
- # There are no more nodes
19
- assert(!reader.read)
20
-
21
- # Check what was read
22
- expected = [LibXML::XML::Reader::TYPE_PROCESSING_INSTRUCTION,
23
- LibXML::XML::Reader::TYPE_ELEMENT,
24
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
25
- LibXML::XML::Reader::TYPE_COMMENT,
26
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
27
- LibXML::XML::Reader::TYPE_ELEMENT,
28
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
29
- LibXML::XML::Reader::TYPE_ELEMENT,
30
- LibXML::XML::Reader::TYPE_CDATA,
31
- LibXML::XML::Reader::TYPE_END_ELEMENT,
32
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
33
- LibXML::XML::Reader::TYPE_ELEMENT,
34
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
35
- LibXML::XML::Reader::TYPE_ELEMENT,
36
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
37
- LibXML::XML::Reader::TYPE_ELEMENT,
38
- LibXML::XML::Reader::TYPE_TEXT,
39
- LibXML::XML::Reader::TYPE_END_ELEMENT,
40
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
41
- LibXML::XML::Reader::TYPE_END_ELEMENT,
42
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
43
- LibXML::XML::Reader::TYPE_END_ELEMENT,
44
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
45
- LibXML::XML::Reader::TYPE_END_ELEMENT,
46
- LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
47
- LibXML::XML::Reader::TYPE_END_ELEMENT]
48
-
49
- assert_equal(expected, node_types)
50
- end
51
-
52
- def test_document
53
- reader = LibXML::XML::Reader.document(LibXML::XML::Document.file(XML_FILE))
54
- verify_simple(reader)
55
- end
56
-
57
- def test_file
58
- reader = LibXML::XML::Reader.file(XML_FILE)
59
- verify_simple(reader)
60
- end
61
-
62
- def test_invalid_file
63
- assert_raises(LibXML::XML::Error) do
64
- LibXML::XML::Reader.file('/does/not/exist')
65
- end
66
- end
67
-
68
- def test_string
69
- reader = LibXML::XML::Reader.string(File.read(XML_FILE))
70
- verify_simple(reader)
71
- end
72
-
73
- def test_io
74
- File.open(XML_FILE, 'rb') do |io|
75
- reader = LibXML::XML::Reader.io(io)
76
- verify_simple(reader)
77
- end
78
- end
79
-
80
- def test_io_gc
81
- # Test that the reader keeps a reference
82
- # to the io object
83
- file = File.open(XML_FILE, 'rb')
84
- reader = LibXML::XML::Reader.io(file)
85
- file = nil
86
- GC.start
87
- assert(reader.read)
88
- end
89
-
90
- def test_string_io
91
- data = File.read(XML_FILE)
92
- string_io = StringIO.new(data)
93
- reader = LibXML::XML::Reader.io(string_io)
94
- verify_simple(reader)
95
- end
96
-
97
- def test_error
98
- reader = LibXML::XML::Reader.string('<foo blah')
99
-
100
- error = assert_raises(LibXML::XML::Error) do
101
- reader.read
102
- end
103
- assert_equal("Fatal error: Couldn't find end of Start Tag foo at :1.", error.to_s)
104
- end
105
-
106
- def test_attr
107
- parser = LibXML::XML::Reader.string("<foo x='1' y='2'/>")
108
- assert(parser.read)
109
- assert_equal('foo', parser.name)
110
- assert_equal('1', parser['x'])
111
- assert_equal('1', parser[0])
112
- assert_equal('2', parser['y'])
113
- assert_equal('2', parser[1])
114
- assert_nil(parser['z'])
115
- assert_nil(parser[2])
116
- end
117
-
118
- def test_move_attr
119
- reader = LibXML::XML::Reader.string('<root xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xhtml="http://www.w3.org/1999/xhtml"><link xml:id="abc" xlink:href="def" xhtml:class="ghi" bar="jkl" /></root>')
120
- assert(reader.read) # <root/>
121
- assert(reader.read) # <link/>
122
-
123
- assert(reader.move_to_attribute_no(1))
124
- assert_equal(reader.value, 'def')
125
- assert(reader.move_to_attribute_ns('id', 'http://www.w3.org/XML/1998/namespace'))
126
- assert_equal(reader.value, 'abc')
127
- assert(reader.move_to_attribute('bar'))
128
- assert_equal(reader.value, 'jkl')
129
-
130
- # 1 in case of success, -1 in case of error, 0 if not found
131
- assert_equal(reader.move_to_attribute_no(12), 0)
132
- assert_equal(reader.move_to_attribute('baz'), 0)
133
- assert_equal(reader.move_to_attribute_ns('baz', 'http://ruby/namespace'), 0)
134
- end
135
-
136
- def test_get_attr
137
- reader = LibXML::XML::Reader.string('<root xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xhtml="http://www.w3.org/1999/xhtml"><link xml:id="abc" xlink:href="def" xhtml:class="ghi" bar="jkl" /></root>')
138
- assert(reader.read) # <root/>
139
- assert(reader.read) # <link/>
140
-
141
- assert_equal(reader.get_attribute_no(1), 'def')
142
- assert_equal(reader.get_attribute_ns('id', 'http://www.w3.org/XML/1998/namespace'), 'abc')
143
- assert_equal(reader.get_attribute('bar'), 'jkl')
144
-
145
- assert_nil(reader.get_attribute_no(12))
146
- assert_nil(reader.get_attribute('baz'))
147
- assert_nil(reader.get_attribute_ns('baz', 'http://ruby/namespace'))
148
- end
149
-
150
- def test_value
151
- parser = LibXML::XML::Reader.string("<foo><bar>1</bar><bar>2</bar><bar>3</bar></foo>")
152
- assert(parser.read)
153
- assert_equal('foo', parser.name)
154
- assert_nil(parser.value)
155
- 3.times do |i|
156
- assert(parser.read)
157
- assert_equal(LibXML::XML::Reader::TYPE_ELEMENT, parser.node_type)
158
- assert_equal('bar', parser.name)
159
- assert(parser.read)
160
- assert_equal(LibXML::XML::Reader::TYPE_TEXT, parser.node_type)
161
- assert_equal((i + 1).to_s, parser.value)
162
- assert(parser.read)
163
- assert_equal(LibXML::XML::Reader::TYPE_END_ELEMENT, parser.node_type)
164
- end
165
- end
166
-
167
- def test_expand
168
- reader = LibXML::XML::Reader.file(XML_FILE)
169
- reader.read.to_s
170
- reader.read
171
-
172
- # Read a node
173
- node = reader.expand
174
- refute_nil(node.doc)
175
- assert_equal('feed', node.name)
176
- assert_equal(::Encoding::UTF_8, node.name.encoding) if defined?(::Encoding)
177
- end
178
-
179
- def test_expand_find
180
- reader = LibXML::XML::Reader.file(XML_FILE)
181
- reader.read.to_s
182
- reader.read
183
-
184
- # Read first node which
185
- node = reader.expand
186
- assert_equal('feed', node.name)
187
-
188
- # We need to create document to use xpath
189
- reader.doc
190
-
191
- # Search for entries
192
- entries = node.find('atom:entry', 'atom:http://www.w3.org/2005/Atom')
193
-
194
- assert_equal(1, entries.length)
195
- end
196
-
197
- def test_expand_invalid
198
- reader = LibXML::XML::Reader.file(XML_FILE)
199
-
200
- # Expand a node before one has been read
201
- node = reader.expand
202
- assert_nil(node)
203
- end
204
-
205
- def test_expand_should_be_invalid
206
- reader = LibXML::XML::Reader.file(XML_FILE)
207
-
208
- # Read a couple of nodes
209
- reader.read
210
- reader.read
211
-
212
- # Expand the node
213
- node = reader.expand
214
- assert_equal('feed', node.name)
215
-
216
- # Read another node, this makes the last node invalid
217
- reader.next
218
-
219
- # The previous node is now invalid - this should be an error but isn't
220
- assert_equal('feed', node.name)
221
- end
222
-
223
- def test_expand_incorrectly_use_returned_node
224
- file = File.join(File.dirname(__FILE__), 'model/cwm_1_0.xml')
225
- reader = LibXML::XML::Reader.file(file)
226
-
227
- nodes = Array.new
228
- while reader.read
229
- node = reader.expand
230
- refute_nil(node)
231
- refute_nil(node.doc)
232
-
233
- # NOTE - DO NOT do this in real code, these nodes are invalid after the next read. This *will* cause
234
- # a segmentation fault next time the garbage collector runs. The reason is the parent node will be
235
- # called in the mark phase, but its underlying xml node will be gone. Same goes for calling children,
236
- # attributes, etc. You must let go of the expanded node *before* calling xml reader again and
237
- # call the garbage collector to be safe.
238
- #refute_nil(node.parent)
239
- nodes << node
240
- end
241
- assert(true)
242
- end
243
-
244
- def test_mode
245
- reader = LibXML::XML::Reader.string('<xml/>')
246
- assert_equal(LibXML::XML::Reader::MODE_INITIAL, reader.read_state)
247
- reader.read
248
- assert_equal(LibXML::XML::Reader::MODE_EOF, reader.read_state)
249
- end
250
-
251
- def test_bytes_consumed
252
- ending_are_rn = File.binread(XML_FILE).include? "\r\n"
253
- reader = LibXML::XML::Reader.file(XML_FILE)
254
- reader.read
255
- assert_equal(ending_are_rn ? 428 : 416, reader.byte_consumed)
256
- end
257
-
258
- def test_node
259
- LibXML::XML.default_line_numbers = true
260
- reader = LibXML::XML::Reader.file(XML_FILE)
261
-
262
- # first try to get a node
263
- assert_nil(reader.node)
264
-
265
- reader.read
266
- assert_instance_of(LibXML::XML::Node, reader.node)
267
- end
268
-
269
- def test_base_uri
270
- # UTF8:
271
- # ö - c3 b6 in hex, \303\266 in octal
272
- # ü - c3 bc in hex, \303\274 in octal
273
- xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><bands genre=\"metal\">\n <m\303\266tley_cr\303\274e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\303\266tley_cr\303\274e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
274
- reader = LibXML::XML::Reader.string(xml, :base_uri => "http://libxml.rubyforge.org")
275
-
276
- reader.read
277
- assert_equal(reader.base_uri, "http://libxml.rubyforge.org")
278
- assert_equal(::Encoding::UTF_8, reader.base_uri.encoding) if defined?(::Encoding)
279
- end
280
-
281
- def test_options
282
- xml = <<-EOS
283
- <!DOCTYPE foo [<!ENTITY foo 'bar'>]>
284
- <test>
285
- <cdata><![CDATA[something]]></cdata>
286
- <entity>&foo;</entity>
287
- </test>
288
- EOS
289
-
290
- # Parse normally
291
- reader = LibXML::XML::Reader.string(xml)
292
- reader.read # foo
293
- reader.read # test
294
- reader.read # text
295
- reader.read # cdata
296
- reader.read # cdata-section
297
- assert_equal(LibXML::XML::Node::CDATA_SECTION_NODE, reader.node_type)
298
-
299
- # Convert cdata section to text
300
- reader = LibXML::XML::Reader.string(xml, :options => LibXML::XML::Parser::Options::NOCDATA)
301
- reader.read # foo
302
- reader.read # test
303
- reader.read # text
304
- reader.read # cdata
305
- reader.read # cdata-section
306
- assert_equal(LibXML::XML::Node::TEXT_NODE, reader.node_type)
307
- end
308
-
309
- def test_encoding
310
- # ISO_8859_1:
311
- # ö - f6 in hex, \366 in octal
312
- # ü - fc in hex, \374 in octal
313
- xml = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
314
-
315
- reader = LibXML::XML::Reader.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
316
- reader.read
317
-
318
- assert_equal(Encoding::ISO8859_1, reader.read_outer_xml.encoding)
319
- assert_equal(Encoding::ISO8859_1, reader.read_inner_xml.encoding)
320
- assert_equal(Encoding::ISO8859_1, reader.read_string.encoding)
321
-
322
- assert_equal("<bands genre=\"metal\">\n <m\xC3\xB6tley_cr\xC3\xBCe country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\xC3\xB6tley_cr\xC3\xBCe>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>".force_encoding(Encoding::ISO8859_1),
323
- reader.read_outer_xml)
324
- assert_equal("\n <m\xC3\xB6tley_cr\xC3\xBCe country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\xC3\xB6tley_cr\xC3\xBCe>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n".force_encoding(Encoding::ISO8859_1),
325
- reader.read_inner_xml)
326
- assert_equal("\n An American heavy metal band formed in Los Angeles, California in 1981.\n British heavy metal band formed in 1975.\n".force_encoding(Encoding::ISO8859_1),
327
- reader.read_string)
328
- end
329
-
330
- def test_invalid_encoding
331
- # ISO_8859_1:
332
- # ö - f6 in hex, \366 in octal
333
- # ü - fc in hex, \374 in octal
334
- xml = "<bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
335
-
336
- reader = LibXML::XML::Reader.string(xml)
337
- error = assert_raises(LibXML::XML::Error) do
338
- reader.read
339
- end
340
-
341
- assert_equal("Fatal error: Input is not proper UTF-8, indicate encoding !\nBytes: 0xF6 0x74 0x6C 0x65 at :2.",
342
- error.to_s)
343
-
344
- end
345
-
346
- def test_file_encoding
347
- reader = LibXML::XML::Reader.file(XML_FILE)
348
- reader.read
349
- assert_equal(LibXML::XML::Encoding::UTF_8, reader.encoding)
350
- assert_equal(Encoding::UTF_8, reader.value.encoding)
351
- end
352
-
353
- def test_string_encoding
354
- # ISO_8859_1:
355
- # ö - f6 in hex, \366 in octal
356
- # ü - fc in hex, \374 in octal
357
- xml = "<bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
358
- reader = LibXML::XML::Reader.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
359
- reader.read
360
-
361
- # Encoding is always null for strings, very annoying!
362
- assert_equal(reader.encoding, LibXML::XML::Encoding::NONE)
363
- end
364
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './test_helper'
4
+ require 'stringio'
5
+
6
+ class TestReader < Minitest::Test
7
+ XML_FILE = File.join(File.dirname(__FILE__), 'model/atom.xml')
8
+
9
+ def verify_simple(reader)
10
+ node_types = []
11
+
12
+ # Read each node
13
+ 26.times do
14
+ assert(reader.read)
15
+ node_types << reader.node_type
16
+ end
17
+
18
+ # There are no more nodes
19
+ assert(!reader.read)
20
+
21
+ # Check what was read
22
+ expected = [LibXML::XML::Reader::TYPE_PROCESSING_INSTRUCTION,
23
+ LibXML::XML::Reader::TYPE_ELEMENT,
24
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
25
+ LibXML::XML::Reader::TYPE_COMMENT,
26
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
27
+ LibXML::XML::Reader::TYPE_ELEMENT,
28
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
29
+ LibXML::XML::Reader::TYPE_ELEMENT,
30
+ LibXML::XML::Reader::TYPE_CDATA,
31
+ LibXML::XML::Reader::TYPE_END_ELEMENT,
32
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
33
+ LibXML::XML::Reader::TYPE_ELEMENT,
34
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
35
+ LibXML::XML::Reader::TYPE_ELEMENT,
36
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
37
+ LibXML::XML::Reader::TYPE_ELEMENT,
38
+ LibXML::XML::Reader::TYPE_TEXT,
39
+ LibXML::XML::Reader::TYPE_END_ELEMENT,
40
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
41
+ LibXML::XML::Reader::TYPE_END_ELEMENT,
42
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
43
+ LibXML::XML::Reader::TYPE_END_ELEMENT,
44
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
45
+ LibXML::XML::Reader::TYPE_END_ELEMENT,
46
+ LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE,
47
+ LibXML::XML::Reader::TYPE_END_ELEMENT]
48
+
49
+ assert_equal(expected, node_types)
50
+ end
51
+
52
+ def test_document
53
+ reader = LibXML::XML::Reader.document(LibXML::XML::Document.file(XML_FILE))
54
+ verify_simple(reader)
55
+ end
56
+
57
+ def test_file
58
+ reader = LibXML::XML::Reader.file(XML_FILE)
59
+ verify_simple(reader)
60
+ end
61
+
62
+ def test_invalid_file
63
+ error = assert_raises(Errno::ENOENT) do
64
+ LibXML::XML::Reader.file('/does/not/exist')
65
+ end
66
+ assert_equal("No such file or directory - /does/not/exist", error.message)
67
+ end
68
+
69
+ def test_string
70
+ reader = LibXML::XML::Reader.string(File.read(XML_FILE))
71
+ verify_simple(reader)
72
+ end
73
+
74
+ def test_io
75
+ File.open(XML_FILE, 'rb') do |io|
76
+ reader = LibXML::XML::Reader.io(io)
77
+ verify_simple(reader)
78
+ end
79
+ end
80
+
81
+ def test_io_gc
82
+ # Test that the reader keeps a reference
83
+ # to the io object
84
+ file = File.open(XML_FILE, 'rb')
85
+ reader = LibXML::XML::Reader.io(file)
86
+ file = nil
87
+ GC.start
88
+ assert(reader.read)
89
+ end
90
+
91
+ def test_string_io
92
+ data = File.read(XML_FILE)
93
+ string_io = StringIO.new(data)
94
+ reader = LibXML::XML::Reader.io(string_io)
95
+ verify_simple(reader)
96
+ end
97
+
98
+ def test_error
99
+ reader = LibXML::XML::Reader.string('<foo blah')
100
+
101
+ error = assert_raises(LibXML::XML::Error) do
102
+ reader.read
103
+ end
104
+ assert_equal("Fatal error: Couldn't find end of Start Tag foo at :1.", error.to_s)
105
+ end
106
+
107
+ def test_attr
108
+ parser = LibXML::XML::Reader.string("<foo x='1' y='2'/>")
109
+ assert(parser.read)
110
+ assert_equal('foo', parser.name)
111
+ assert_equal('1', parser['x'])
112
+ assert_equal('1', parser[0])
113
+ assert_equal('2', parser['y'])
114
+ assert_equal('2', parser[1])
115
+ assert_nil(parser['z'])
116
+ assert_nil(parser[2])
117
+ end
118
+
119
+ def test_move_attr
120
+ reader = LibXML::XML::Reader.string('<root xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xhtml="http://www.w3.org/1999/xhtml"><link xml:id="abc" xlink:href="def" xhtml:class="ghi" bar="jkl" /></root>')
121
+ assert(reader.read) # <root/>
122
+ assert(reader.read) # <link/>
123
+
124
+ assert(reader.move_to_attribute_no(1))
125
+ assert_equal(reader.value, 'def')
126
+ assert(reader.move_to_attribute_ns('id', 'http://www.w3.org/XML/1998/namespace'))
127
+ assert_equal(reader.value, 'abc')
128
+ assert(reader.move_to_attribute('bar'))
129
+ assert_equal(reader.value, 'jkl')
130
+
131
+ # 1 in case of success, -1 in case of error, 0 if not found
132
+ assert_equal(reader.move_to_attribute_no(12), 0)
133
+ assert_equal(reader.move_to_attribute('baz'), 0)
134
+ assert_equal(reader.move_to_attribute_ns('baz', 'http://ruby/namespace'), 0)
135
+ end
136
+
137
+ def test_get_attr
138
+ reader = LibXML::XML::Reader.string('<root xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xhtml="http://www.w3.org/1999/xhtml"><link xml:id="abc" xlink:href="def" xhtml:class="ghi" bar="jkl" /></root>')
139
+ assert(reader.read) # <root/>
140
+ assert(reader.read) # <link/>
141
+
142
+ assert_equal(reader.get_attribute_no(1), 'def')
143
+ assert_equal(reader.get_attribute_ns('id', 'http://www.w3.org/XML/1998/namespace'), 'abc')
144
+ assert_equal(reader.get_attribute('bar'), 'jkl')
145
+
146
+ assert_nil(reader.get_attribute_no(12))
147
+ assert_nil(reader.get_attribute('baz'))
148
+ assert_nil(reader.get_attribute_ns('baz', 'http://ruby/namespace'))
149
+ end
150
+
151
+ def test_value
152
+ parser = LibXML::XML::Reader.string("<foo><bar>1</bar><bar>2</bar><bar>3</bar></foo>")
153
+ assert(parser.read)
154
+ assert_equal('foo', parser.name)
155
+ assert_nil(parser.value)
156
+ 3.times do |i|
157
+ assert(parser.read)
158
+ assert_equal(LibXML::XML::Reader::TYPE_ELEMENT, parser.node_type)
159
+ assert_equal('bar', parser.name)
160
+ assert(parser.read)
161
+ assert_equal(LibXML::XML::Reader::TYPE_TEXT, parser.node_type)
162
+ assert_equal((i + 1).to_s, parser.value)
163
+ assert(parser.read)
164
+ assert_equal(LibXML::XML::Reader::TYPE_END_ELEMENT, parser.node_type)
165
+ end
166
+ end
167
+
168
+ def test_expand
169
+ reader = LibXML::XML::Reader.file(XML_FILE)
170
+ reader.read.to_s
171
+ reader.read
172
+
173
+ # Read a node
174
+ node = reader.expand
175
+ # node.doc is nil until reader.doc is called to wrap the document
176
+ assert_nil(node.doc)
177
+ assert_equal('feed', node.name)
178
+ assert_equal(::Encoding::UTF_8, node.name.encoding) if defined?(::Encoding)
179
+ end
180
+
181
+ def test_expand_attribute_doc_requires_reader_doc
182
+ reader = LibXML::XML::Reader.string('<root a="1"/>')
183
+ reader.read
184
+
185
+ node = reader.expand
186
+ attr = node.attributes.get_attribute('a')
187
+
188
+ assert_nil(node.doc)
189
+ assert_nil(attr.doc)
190
+
191
+ doc = reader.doc
192
+ assert_same(doc, node.doc)
193
+ assert_same(doc, attr.doc)
194
+ ensure
195
+ begin
196
+ reader.doc if reader
197
+ rescue StandardError
198
+ end
199
+ end
200
+
201
+ def test_expand_attribute_doc
202
+ reader = LibXML::XML::Reader.string('<root a="1"/>')
203
+ reader.read
204
+
205
+ node = reader.expand
206
+ attr = node.attributes.get_attribute('a')
207
+
208
+ assert_nil(attr.doc)
209
+ end
210
+
211
+ def test_expand_find
212
+ reader = LibXML::XML::Reader.file(XML_FILE)
213
+ reader.read.to_s
214
+ reader.read
215
+
216
+ # Read first node which
217
+ node = reader.expand
218
+ assert_equal('feed', node.name)
219
+
220
+ # We need to create document to use xpath
221
+ reader.doc
222
+
223
+ # Search for entries
224
+ entries = node.find('atom:entry', 'atom:http://www.w3.org/2005/Atom')
225
+
226
+ assert_equal(1, entries.length)
227
+ end
228
+
229
+ def test_expand_invalid
230
+ reader = LibXML::XML::Reader.file(XML_FILE)
231
+
232
+ # Expand a node before one has been read
233
+ node = reader.expand
234
+ assert_nil(node)
235
+ end
236
+
237
+ def test_expand_should_be_invalid
238
+ reader = LibXML::XML::Reader.file(XML_FILE)
239
+
240
+ # Read a couple of nodes
241
+ reader.read
242
+ reader.read
243
+
244
+ # Expand the node
245
+ node = reader.expand
246
+ assert_equal('feed', node.name)
247
+
248
+ # Read another node, this makes the last node invalid
249
+ reader.next
250
+
251
+ # The previous node is now invalid - this should be an error but isn't
252
+ assert_equal('feed', node.name)
253
+ end
254
+
255
+ def test_expand_incorrectly_use_returned_node
256
+ file = File.join(File.dirname(__FILE__), 'model/cwm_1_0.xml')
257
+ reader = LibXML::XML::Reader.file(file)
258
+
259
+ nodes = Array.new
260
+ while reader.read
261
+ node = reader.expand
262
+ refute_nil(node)
263
+
264
+ # NOTE - DO NOT do this in real code, these nodes are invalid after the next read. This *will* cause
265
+ # a segmentation fault next time the garbage collector runs. The reason is the parent node will be
266
+ # called in the mark phase, but its underlying xml node will be gone. Same goes for calling children,
267
+ # attributes, etc. You must let go of the expanded node *before* calling xml reader again and
268
+ # call the garbage collector to be safe.
269
+ #refute_nil(node.parent)
270
+ nodes << node
271
+ end
272
+ assert(true)
273
+ end
274
+
275
+ def test_mode
276
+ reader = LibXML::XML::Reader.string('<xml/>')
277
+ assert_equal(LibXML::XML::Reader::MODE_INITIAL, reader.read_state)
278
+ reader.read
279
+ assert_equal(LibXML::XML::Reader::MODE_EOF, reader.read_state)
280
+ end
281
+
282
+ def test_bytes_consumed
283
+ ending_are_rn = File.binread(XML_FILE).include? "\r\n"
284
+ reader = LibXML::XML::Reader.file(XML_FILE)
285
+ reader.read
286
+ assert_equal(ending_are_rn ? 428 : 416, reader.byte_consumed)
287
+ end
288
+
289
+ def test_node
290
+ reader = LibXML::XML::Reader.file(XML_FILE)
291
+
292
+ # first try to get a node
293
+ assert_nil(reader.node)
294
+
295
+ reader.read
296
+ assert_instance_of(LibXML::XML::Node, reader.node)
297
+ end
298
+
299
+ def test_base_uri
300
+ # UTF8:
301
+ # ö - c3 b6 in hex, \303\266 in octal
302
+ # ü - c3 bc in hex, \303\274 in octal
303
+ xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><bands genre=\"metal\">\n <m\303\266tley_cr\303\274e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\303\266tley_cr\303\274e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
304
+ reader = LibXML::XML::Reader.string(xml, :base_uri => "http://libxml.rubyforge.org")
305
+
306
+ reader.read
307
+ assert_equal(reader.base_uri, "http://libxml.rubyforge.org")
308
+ assert_equal(::Encoding::UTF_8, reader.base_uri.encoding) if defined?(::Encoding)
309
+ end
310
+
311
+ def test_options
312
+ xml = <<-EOS
313
+ <!DOCTYPE foo [<!ENTITY foo 'bar'>]>
314
+ <test>
315
+ <cdata><![CDATA[something]]></cdata>
316
+ <entity>&foo;</entity>
317
+ </test>
318
+ EOS
319
+
320
+ # Parse normally
321
+ reader = LibXML::XML::Reader.string(xml)
322
+ reader.read # foo
323
+ reader.read # test
324
+ reader.read # text
325
+ reader.read # cdata
326
+ reader.read # cdata-section
327
+ assert_equal(LibXML::XML::Node::CDATA_SECTION_NODE, reader.node_type)
328
+
329
+ # Convert cdata section to text
330
+ reader = LibXML::XML::Reader.string(xml, :options => LibXML::XML::Parser::Options::NOCDATA)
331
+ reader.read # foo
332
+ reader.read # test
333
+ reader.read # text
334
+ reader.read # cdata
335
+ reader.read # cdata-section
336
+ assert_equal(LibXML::XML::Node::TEXT_NODE, reader.node_type)
337
+ end
338
+
339
+ def test_encoding
340
+ # ISO_8859_1:
341
+ # ö - f6 in hex, \366 in octal
342
+ # ü - fc in hex, \374 in octal
343
+ xml = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
344
+
345
+ reader = LibXML::XML::Reader.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
346
+ reader.read
347
+
348
+ assert_equal(Encoding::ISO8859_1, reader.read_outer_xml.encoding)
349
+ assert_equal(Encoding::ISO8859_1, reader.read_inner_xml.encoding)
350
+ assert_equal(Encoding::ISO8859_1, reader.read_string.encoding)
351
+
352
+ assert_equal("<bands genre=\"metal\">\n <m\xC3\xB6tley_cr\xC3\xBCe country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\xC3\xB6tley_cr\xC3\xBCe>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>".force_encoding(Encoding::ISO8859_1),
353
+ reader.read_outer_xml)
354
+ assert_equal("\n <m\xC3\xB6tley_cr\xC3\xBCe country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\xC3\xB6tley_cr\xC3\xBCe>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n".force_encoding(Encoding::ISO8859_1),
355
+ reader.read_inner_xml)
356
+ assert_equal("\n An American heavy metal band formed in Los Angeles, California in 1981.\n British heavy metal band formed in 1975.\n".force_encoding(Encoding::ISO8859_1),
357
+ reader.read_string)
358
+ end
359
+
360
+ def test_invalid_encoding
361
+ # ISO_8859_1:
362
+ # ö - f6 in hex, \366 in octal
363
+ # ü - fc in hex, \374 in octal
364
+ xml = "<bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
365
+
366
+ reader = LibXML::XML::Reader.string(xml)
367
+ error = assert_raises(LibXML::XML::Error) do
368
+ reader.read
369
+ end
370
+
371
+ assert_match(/Fatal error:.*at :2\./m, error.to_s)
372
+
373
+ end
374
+
375
+ def test_file_encoding
376
+ reader = LibXML::XML::Reader.file(XML_FILE)
377
+ reader.read
378
+ assert_equal(LibXML::XML::Encoding::UTF_8, reader.encoding)
379
+ assert_equal(Encoding::UTF_8, reader.value.encoding)
380
+ end
381
+
382
+ def test_string_encoding
383
+ # ISO_8859_1:
384
+ # ö - f6 in hex, \366 in octal
385
+ # ü - fc in hex, \374 in octal
386
+ xml = "<bands genre=\"metal\">\n <m\366tley_cr\374e country=\"us\">An American heavy metal band formed in Los Angeles, California in 1981.</m\366tley_cr\374e>\n <iron_maiden country=\"uk\">British heavy metal band formed in 1975.</iron_maiden>\n</bands>"
387
+ reader = LibXML::XML::Reader.string(xml, :encoding => LibXML::XML::Encoding::ISO_8859_1)
388
+ reader.read
389
+
390
+ if Gem::Version.new(LibXML::XML::LIBXML_VERSION) >= Gem::Version.new("2.12")
391
+ assert_equal(LibXML::XML::Encoding::ISO_8859_1, reader.encoding)
392
+ else
393
+ assert_equal(LibXML::XML::Encoding::NONE, reader.encoding)
394
+ end
395
+ end
396
+
397
+ def test_expand_gc_after_advance
398
+ GC.stress = true
399
+ expand_and_advance
400
+ ensure
401
+ GC.stress = false
402
+ end
403
+
404
+ private
405
+
406
+ def expand_and_advance
407
+ reader = LibXML::XML::Reader.string("<root><a/><b/></root>")
408
+ reader.read # root
409
+ reader.read # a
410
+ reader.expand
411
+ reader.next
412
+ end
413
+ end