nokogiri 1.6.7.2-java → 1.6.8-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.cross_rubies +2 -0
  3. data/.travis.yml +19 -9
  4. data/CHANGELOG.rdoc +73 -5
  5. data/CONTRIBUTING.md +42 -0
  6. data/Gemfile +10 -9
  7. data/LICENSE.txt +1 -1
  8. data/Manifest.txt +7 -2
  9. data/README.md +23 -27
  10. data/ROADMAP.md +11 -1
  11. data/Rakefile +36 -17
  12. data/bin/nokogiri +2 -2
  13. data/dependencies.yml +29 -4
  14. data/ext/java/nokogiri/HtmlElementDescription.java +5 -2
  15. data/ext/java/nokogiri/NokogiriService.java +19 -0
  16. data/ext/java/nokogiri/XmlAttr.java +3 -1
  17. data/ext/java/nokogiri/XmlDocumentFragment.java +0 -14
  18. data/ext/java/nokogiri/XmlNode.java +106 -63
  19. data/ext/java/nokogiri/XmlXpathContext.java +12 -12
  20. data/ext/java/nokogiri/XsltStylesheet.java +11 -4
  21. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +8 -1
  22. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +1 -2
  23. data/ext/java/nokogiri/internals/NokogiriHelpers.java +7 -7
  24. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +1 -1
  25. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +0 -1
  26. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +3 -3
  27. data/ext/java/nokogiri/internals/ParserContext.java +4 -0
  28. data/ext/java/nokogiri/internals/SaveContextVisitor.java +18 -13
  29. data/ext/nokogiri/extconf.rb +163 -79
  30. data/ext/nokogiri/html_document.c +6 -6
  31. data/ext/nokogiri/html_element_description.c +1 -1
  32. data/ext/nokogiri/html_entity_lookup.c +1 -1
  33. data/ext/nokogiri/html_sax_parser_context.c +4 -4
  34. data/ext/nokogiri/html_sax_push_parser.c +2 -2
  35. data/ext/nokogiri/nokogiri.c +0 -7
  36. data/ext/nokogiri/nokogiri.h +1 -34
  37. data/ext/nokogiri/xml_attr.c +2 -2
  38. data/ext/nokogiri/xml_comment.c +1 -1
  39. data/ext/nokogiri/xml_document.c +20 -22
  40. data/ext/nokogiri/xml_encoding_handler.c +3 -3
  41. data/ext/nokogiri/xml_entity_reference.c +1 -1
  42. data/ext/nokogiri/xml_namespace.c +56 -17
  43. data/ext/nokogiri/xml_node.c +73 -67
  44. data/ext/nokogiri/xml_node_set.c +164 -146
  45. data/ext/nokogiri/xml_node_set.h +3 -4
  46. data/ext/nokogiri/xml_processing_instruction.c +2 -2
  47. data/ext/nokogiri/xml_reader.c +5 -18
  48. data/ext/nokogiri/xml_sax_parser.c +9 -12
  49. data/ext/nokogiri/xml_sax_parser_context.c +1 -1
  50. data/ext/nokogiri/xml_sax_push_parser.c +1 -1
  51. data/ext/nokogiri/xml_schema.c +1 -1
  52. data/ext/nokogiri/xml_syntax_error.c +0 -4
  53. data/ext/nokogiri/xml_syntax_error.h +0 -1
  54. data/ext/nokogiri/xml_text.c +1 -1
  55. data/ext/nokogiri/xml_xpath_context.c +15 -24
  56. data/ext/nokogiri/xslt_stylesheet.c +6 -6
  57. data/lib/nekohtml.jar +0 -0
  58. data/lib/nokogiri.rb +14 -7
  59. data/lib/nokogiri/css/parser.rb +8 -2
  60. data/lib/nokogiri/css/parser.y +7 -2
  61. data/lib/nokogiri/html/document.rb +4 -2
  62. data/lib/nokogiri/nokogiri.jar +0 -0
  63. data/lib/nokogiri/version.rb +1 -1
  64. data/lib/nokogiri/xml/document.rb +7 -1
  65. data/lib/nokogiri/xml/dtd.rb +4 -4
  66. data/lib/nokogiri/xml/node.rb +6 -10
  67. data/lib/nokogiri/xml/node_set.rb +3 -3
  68. data/lib/nokogiri/xml/parse_options.rb +22 -0
  69. data/lib/serializer.jar +0 -0
  70. data/lib/xalan.jar +0 -0
  71. data/lib/xercesImpl.jar +0 -0
  72. data/lib/xml-apis.jar +0 -0
  73. data/tasks/test.rb +5 -0
  74. data/test/css/test_parser.rb +7 -1
  75. data/test/files/GH_1042.html +18 -0
  76. data/test/files/namespace_pressure_test.xml +1684 -0
  77. data/test/files/tlm.html +2 -1
  78. data/test/helper.rb +4 -0
  79. data/test/html/sax/test_parser.rb +2 -2
  80. data/test/html/test_document.rb +47 -11
  81. data/test/html/test_document_encoding.rb +55 -58
  82. data/test/html/test_document_fragment.rb +27 -23
  83. data/test/html/test_node.rb +16 -0
  84. data/test/html/test_node_encoding.rb +71 -13
  85. data/test/namespaces/test_namespaces_in_parsed_doc.rb +14 -0
  86. data/test/test_css_cache.rb +1 -1
  87. data/test/test_encoding_handler.rb +2 -0
  88. data/test/test_xslt_transforms.rb +38 -3
  89. data/test/xml/sax/test_parser.rb +54 -53
  90. data/test/xml/test_document.rb +7 -2
  91. data/test/xml/test_document_encoding.rb +19 -16
  92. data/test/xml/test_document_fragment.rb +12 -0
  93. data/test/xml/test_dtd_encoding.rb +0 -2
  94. data/test/xml/test_namespace.rb +2 -2
  95. data/test/xml/test_node.rb +15 -4
  96. data/test/xml/test_node_attributes.rb +6 -0
  97. data/test/xml/test_node_encoding.rb +49 -87
  98. data/test/xml/test_node_reparenting.rb +193 -18
  99. data/test/xml/test_node_set.rb +1 -1
  100. data/test/xml/test_reader.rb +589 -0
  101. data/test/xml/test_reader_encoding.rb +100 -102
  102. data/test/xml/test_unparented_node.rb +14 -1
  103. data/test/xslt/test_exception_handling.rb +1 -1
  104. data/test_all +47 -33
  105. metadata +38 -36
  106. data/CHANGELOG.ja.rdoc +0 -1057
  107. data/test/test_reader.rb +0 -558
@@ -49,6 +49,15 @@ module Nokogiri
49
49
  # end
50
50
  # end
51
51
 
52
+
53
+ before do
54
+ @doc = Nokogiri::XML "<root><a1>First node</a1><a2>Second node</a2><a3>Third <bx />node</a3></root>"
55
+ @doc2 = @doc.dup
56
+ @fragment_string = "<b1>foo</b1><b2>bar</b2>"
57
+ @fragment = Nokogiri::XML::DocumentFragment.parse @fragment_string
58
+ @node_set = Nokogiri::XML("<root><b1>foo</b1><b2>bar</b2></root>").xpath("/root/node()")
59
+ end
60
+
52
61
  {
53
62
  :add_child => {:target => "/root/a1", :returns_self => false, :children_tags => %w[text b1 b2]},
54
63
  :<< => {:target => "/root/a1", :returns_self => true, :children_tags => %w[text b1 b2]},
@@ -67,15 +76,6 @@ module Nokogiri
67
76
  :next= => {:target => "/root/a1/text()", :returns_self => false, :children_tags => %w[text b1 b2]},
68
77
  :after => {:target => "/root/a1/text()", :returns_self => true, :children_tags => %w[text b1 b2]}
69
78
  }.each do |method, params|
70
-
71
- before do
72
- @doc = Nokogiri::XML "<root><a1>First node</a1><a2>Second node</a2><a3>Third <bx />node</a3></root>"
73
- @doc2 = @doc.dup
74
- @fragment_string = "<b1>foo</b1><b2>bar</b2>"
75
- @fragment = Nokogiri::XML::DocumentFragment.parse @fragment_string
76
- @node_set = Nokogiri::XML("<root><b1>foo</b1><b2>bar</b2></root>").xpath("/root/node()")
77
- end
78
-
79
79
  describe "##{method}" do
80
80
  describe "passed a Node" do
81
81
  [:current, :another].each do |which|
@@ -215,7 +215,7 @@ module Nokogiri
215
215
  end
216
216
  end
217
217
 
218
- describe "given a parent node with a non-default namespace" do
218
+ describe "given a parent node with a default and non-default namespace" do
219
219
  before do
220
220
  @doc = Nokogiri::XML(<<-eoxml)
221
221
  <root xmlns="http://tenderlovemaking.com/" xmlns:foo="http://flavorjon.es/">
@@ -223,18 +223,156 @@ module Nokogiri
223
223
  </first>
224
224
  </root>
225
225
  eoxml
226
+ assert @node = @doc.at('//xmlns:first')
227
+ @child = Nokogiri::XML::Node.new('second', @doc)
226
228
  end
227
229
 
228
- describe "and a child node with a namespace matching the parent's non-default namespace" do
229
- it "inserts a node that inherits the matching parent namespace" do
230
- assert node = @doc.at('//xmlns:first')
231
- child = Nokogiri::XML::Node.new('second', @doc)
230
+ describe "and a child with a namespace matching the parent's default namespace" do
231
+ describe "and as the default prefix" do
232
+ before do
233
+ @ns = @child.add_namespace(nil, 'http://tenderlovemaking.com/')
234
+ @child.namespace = @ns
235
+ end
232
236
 
233
- ns = @doc.root.namespace_definitions.detect { |x| x.prefix == "foo" }
234
- child.namespace = ns
237
+ it "inserts a node that inherits the parent's default namespace" do
238
+ @node.add_child(@child)
239
+ assert reparented = @doc.at('//bar:second', "bar" => "http://tenderlovemaking.com/")
240
+ assert reparented.namespace_definitions.empty?
241
+ assert_equal @ns, reparented.namespace
242
+ assert_equal(
243
+ {
244
+ "xmlns" => "http://tenderlovemaking.com/",
245
+ "xmlns:foo" => "http://flavorjon.es/",
246
+ },
247
+ reparented.namespaces)
248
+ end
249
+ end
250
+
251
+ describe "but with a different prefix" do
252
+ before do
253
+ @ns = @child.add_namespace("baz", 'http://tenderlovemaking.com/')
254
+ @child.namespace = @ns
255
+ end
235
256
 
236
- node.add_child(child)
237
- assert @doc.at('//foo:second', "foo" => "http://flavorjon.es/")
257
+ it "inserts a node that uses its own namespace" do
258
+ @node.add_child(@child)
259
+ assert reparented = @doc.at('//bar:second', "bar" => "http://tenderlovemaking.com/")
260
+ assert reparented.namespace_definitions.include?(@ns)
261
+ assert_equal @ns, reparented.namespace
262
+ assert_equal(
263
+ {
264
+ "xmlns" => "http://tenderlovemaking.com/",
265
+ "xmlns:foo" => "http://flavorjon.es/",
266
+ "xmlns:baz" => "http://tenderlovemaking.com/",
267
+ },
268
+ reparented.namespaces)
269
+ end
270
+ end
271
+ end
272
+
273
+ describe "and a child with a namespace matching the parent's non-default namespace" do
274
+ describe "set by #namespace=" do
275
+ before do
276
+ @ns = @doc.root.namespace_definitions.detect { |x| x.prefix == "foo" }
277
+ @child.namespace = @ns
278
+ end
279
+
280
+ it "inserts a node that inherits the matching parent namespace" do
281
+ @node.add_child(@child)
282
+ assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
283
+ assert reparented.namespace_definitions.empty?
284
+ assert_equal @ns, reparented.namespace
285
+ assert_equal(
286
+ {
287
+ "xmlns" => "http://tenderlovemaking.com/",
288
+ "xmlns:foo" => "http://flavorjon.es/",
289
+ },
290
+ reparented.namespaces)
291
+ end
292
+ end
293
+
294
+ describe "with the same prefix" do
295
+ before do
296
+ @ns = @child.add_namespace("foo", 'http://flavorjon.es/')
297
+ @child.namespace = @ns
298
+ end
299
+
300
+ it "inserts a node that uses the parent's namespace" do
301
+ @node.add_child(@child)
302
+ assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
303
+ assert reparented.namespace_definitions.empty?
304
+ assert_equal @ns, reparented.namespace
305
+ assert_equal(
306
+ {
307
+ "xmlns" => "http://tenderlovemaking.com/",
308
+ "xmlns:foo" => "http://flavorjon.es/",
309
+ },
310
+ reparented.namespaces)
311
+ end
312
+ end
313
+
314
+ describe "as the default prefix" do
315
+ before do
316
+ @ns = @child.add_namespace(nil, 'http://flavorjon.es/')
317
+ @child.namespace = @ns
318
+ end
319
+
320
+ it "inserts a node that keeps its namespace" do
321
+ @node.add_child(@child)
322
+ assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
323
+ assert reparented.namespace_definitions.include?(@ns)
324
+ assert_equal @ns, reparented.namespace
325
+ assert_equal(
326
+ {
327
+ "xmlns" => "http://flavorjon.es/",
328
+ "xmlns:foo" => "http://flavorjon.es/",
329
+ },
330
+ reparented.namespaces)
331
+ end
332
+ end
333
+
334
+ describe "but with a different prefix" do
335
+ before do
336
+ @ns = @child.add_namespace('baz', 'http://flavorjon.es/')
337
+ @child.namespace = @ns
338
+ end
339
+
340
+ it "inserts a node that keeps its namespace" do
341
+ @node.add_child(@child)
342
+ assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
343
+ assert reparented.namespace_definitions.include?(@ns)
344
+ assert_equal @ns, reparented.namespace
345
+ assert_equal(
346
+ {
347
+ "xmlns" =>"http://tenderlovemaking.com/",
348
+ "xmlns:foo" =>"http://flavorjon.es/",
349
+ "xmlns:baz" =>"http://flavorjon.es/",
350
+ },
351
+ reparented.namespaces)
352
+ end
353
+ end
354
+ end
355
+
356
+ describe "and a child node with a default namespace not matching the parent's default namespace and a namespace matching a parent namespace but with a different prefix" do
357
+ before do
358
+ @ns = @child.add_namespace(nil, 'http://example.org/')
359
+ @child.namespace = @ns
360
+ @ns2 = @child.add_namespace('baz', 'http://tenderlovemaking.com/')
361
+ end
362
+
363
+ it "inserts a node that keeps its namespace" do
364
+ @node.add_child(@child)
365
+ assert reparented = @doc.at('//bar:second', "bar" => "http://example.org/")
366
+ assert reparented.namespace_definitions.include?(@ns)
367
+ assert reparented.namespace_definitions.include?(@ns2)
368
+ assert_equal @ns, reparented.namespace
369
+ assert_equal(
370
+ {
371
+ "xmlns" => "http://example.org/",
372
+ "xmlns:foo" => "http://flavorjon.es/",
373
+ "xmlns:baz" => "http://tenderlovemaking.com/",
374
+ },
375
+ reparented.namespaces)
238
376
  end
239
377
  end
240
378
  end
@@ -368,6 +506,43 @@ module Nokogiri
368
506
  end
369
507
  end
370
508
  end
509
+
510
+ describe "reparenting into another document" do
511
+ it "correctly sets default namespace of a reparented node" do
512
+ # issue described in #391
513
+ # thanks to Nick Canzoneri @nickcanz for this test case!
514
+ source_doc = Nokogiri::XML <<-EOX
515
+ <?xml version="1.0" encoding="utf-8"?>
516
+ <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
517
+ <Product>
518
+ <Package />
519
+ <Directory Id="TARGETDIR" Name="SourceDir">
520
+ <Component>
521
+ <File />
522
+ </Component>
523
+ </Directory>
524
+ </Product>
525
+ </Wix>
526
+ EOX
527
+
528
+ dest_doc = Nokogiri::XML <<-EOX
529
+ <?xml version="1.0" encoding="utf-8"?>
530
+ <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
531
+ <Fragment Id='MSIComponents'>
532
+ <DirectoryRef Id='InstallDir'>
533
+ </DirectoryRef>
534
+ </Fragment>
535
+ </Wix>
536
+ EOX
537
+
538
+ stuff = source_doc.at_css("Directory[Id='TARGETDIR']")
539
+ insert_point = dest_doc.at_css("DirectoryRef[Id='InstallDir']")
540
+ insert_point.children = stuff.children()
541
+
542
+ assert_no_match(/default:/, insert_point.children.to_xml)
543
+ assert_match(/<Component>/, insert_point.children.to_xml)
544
+ end
545
+ end
371
546
  end
372
547
  end
373
548
  end
@@ -660,7 +660,7 @@ module Nokogiri
660
660
  employees = @xml.search("//employee")
661
661
  inspected = employees.inspect
662
662
 
663
- assert_equal "[#{employees.map { |x| x.inspect }.join(', ')}]",
663
+ assert_equal "[#{employees.map(&:inspect).join(', ')}]",
664
664
  inspected
665
665
  end
666
666
 
@@ -0,0 +1,589 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "helper"
3
+
4
+ module Nokogiri
5
+ module XML
6
+ class TestReader < Nokogiri::TestCase
7
+ def test_from_io_sets_io_as_source
8
+ io = File.open SNUGGLES_FILE
9
+ reader = Nokogiri::XML::Reader.from_io(io)
10
+ assert_equal io, reader.source
11
+ end
12
+
13
+ def test_empty_element?
14
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
15
+ <xml><city>Paris</city><state/></xml>
16
+ eoxml
17
+
18
+ results = reader.map do |node|
19
+ if node.node_type == Nokogiri::XML::Node::ELEMENT_NODE
20
+ node.empty_element?
21
+ end
22
+ end
23
+ assert_equal [false, false, nil, nil, true, nil], results
24
+ end
25
+
26
+ def test_self_closing?
27
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
28
+ <xml><city>Paris</city><state/></xml>
29
+ eoxml
30
+
31
+ results = reader.map do |node|
32
+ if node.node_type == Nokogiri::XML::Node::ELEMENT_NODE
33
+ node.self_closing?
34
+ end
35
+ end
36
+ assert_equal [false, false, nil, nil, true, nil], results
37
+ end
38
+
39
+ # Issue #831
40
+ # Make sure that the reader doesn't block reading the entire input
41
+ def test_reader_blocking
42
+ rd, wr = IO.pipe()
43
+ node_out = nil
44
+ t = Thread.start do
45
+ reader = Nokogiri::XML::Reader(rd, 'UTF-8')
46
+ reader.each do |node|
47
+ node_out = node
48
+ break
49
+ end
50
+ rd.close
51
+ end
52
+ sleep(1) # sleep for one second to make sure the reader will actually block for input
53
+ begin
54
+ wr.puts "<foo>"
55
+ wr.puts "<bar/>" * 10000
56
+ wr.flush
57
+ rescue Errno::EPIPE
58
+ end
59
+ res = t.join(5) # wait 5 seconds for the thread to finish
60
+ wr.close
61
+ refute_nil node_out, "Didn't read any nodes, exclude the trivial case"
62
+ refute_nil res, "Reader blocks trying to read the entire stream"
63
+ end
64
+
65
+ def test_reader_takes_block
66
+ options = nil
67
+ Nokogiri::XML::Reader(File.read(XML_FILE), XML_FILE) do |cfg|
68
+ options = cfg
69
+ options.nonet.nowarning.dtdattr
70
+ end
71
+ assert options.nonet?
72
+ assert options.nowarning?
73
+ assert options.dtdattr?
74
+ end
75
+
76
+ def test_nil_raises
77
+ assert_raises(ArgumentError) {
78
+ Nokogiri::XML::Reader.from_memory(nil)
79
+ }
80
+ assert_raises(ArgumentError) {
81
+ Nokogiri::XML::Reader.from_io(nil)
82
+ }
83
+ end
84
+
85
+ def test_from_io
86
+ io = File.open SNUGGLES_FILE
87
+ reader = Nokogiri::XML::Reader.from_io(io)
88
+ assert_equal false, reader.default?
89
+ assert_equal [false, false, false, false, false, false, false],
90
+ reader.map(&:default?)
91
+ end
92
+
93
+ def test_io
94
+ io = File.open SNUGGLES_FILE
95
+ reader = Nokogiri::XML::Reader(io)
96
+ assert_equal false, reader.default?
97
+ assert_equal [false, false, false, false, false, false, false],
98
+ reader.map(&:default?)
99
+ end
100
+
101
+ def test_string_io
102
+ io = StringIO.new(<<-eoxml)
103
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
104
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
105
+ </x>
106
+ eoxml
107
+ reader = Nokogiri::XML::Reader(io)
108
+ assert_equal false, reader.default?
109
+ assert_equal [false, false, false, false, false, false, false],
110
+ reader.map(&:default?)
111
+ end
112
+
113
+ class ReallyBadIO
114
+ def read(size)
115
+ 'a' * size ** 10
116
+ end
117
+ end
118
+
119
+ class ReallyBadIO4Java
120
+ def read(size=1)
121
+ 'a' * size ** 10
122
+ end
123
+ end
124
+
125
+ def test_io_that_reads_too_much
126
+ if Nokogiri.jruby?
127
+ io = ReallyBadIO4Java.new
128
+ Nokogiri::XML::Reader(io)
129
+ else
130
+ io = ReallyBadIO.new
131
+ Nokogiri::XML::Reader(io)
132
+ end
133
+ end
134
+
135
+ def test_in_memory
136
+ assert Nokogiri::XML::Reader(<<-eoxml)
137
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
138
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
139
+ </x>
140
+ eoxml
141
+ end
142
+
143
+ def test_reader_holds_on_to_string
144
+ xml = <<-eoxml
145
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
146
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
147
+ </x>
148
+ eoxml
149
+ reader = Nokogiri::XML::Reader(xml)
150
+ assert_equal xml, reader.source
151
+ end
152
+
153
+ def test_default?
154
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
155
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
156
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
157
+ </x>
158
+ eoxml
159
+ assert_equal false, reader.default?
160
+ assert_equal [false, false, false, false, false, false, false],
161
+ reader.map(&:default?)
162
+ end
163
+
164
+ def test_value?
165
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
166
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
167
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
168
+ </x>
169
+ eoxml
170
+ assert_equal false, reader.value?
171
+ assert_equal [false, true, false, true, false, true, false],
172
+ reader.map(&:value?)
173
+ end
174
+
175
+ def test_read_error_document
176
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
177
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
178
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
179
+ <foo>
180
+ </x>
181
+ eoxml
182
+ assert_raises(Nokogiri::XML::SyntaxError) do
183
+ reader.each { |node| }
184
+ end
185
+ assert 1, reader.errors.length
186
+ end
187
+
188
+ def test_attributes?
189
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
190
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
191
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
192
+ </x>
193
+ eoxml
194
+ assert_equal false, reader.attributes?
195
+ assert_equal [true, false, true, false, true, false, true],
196
+ reader.map(&:attributes?)
197
+ end
198
+
199
+ def test_attributes
200
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
201
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'
202
+ xmlns='http://mothership.connection.com/'
203
+ >
204
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
205
+ </x>
206
+ eoxml
207
+ assert_equal({}, reader.attributes)
208
+ assert_equal [{'xmlns:tenderlove'=>'http://tenderlovemaking.com/',
209
+ 'xmlns'=>'http://mothership.connection.com/'},
210
+ {}, {"awesome"=>"true"}, {}, {"awesome"=>"true"}, {},
211
+ {'xmlns:tenderlove'=>'http://tenderlovemaking.com/',
212
+ 'xmlns'=>'http://mothership.connection.com/'}],
213
+ reader.map(&:attributes)
214
+ end
215
+
216
+ def test_attribute_roundtrip
217
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
218
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'
219
+ xmlns='http://mothership.connection.com/'
220
+ >
221
+ <tenderlove:foo awesome='true' size='giant'>snuggles!</tenderlove:foo>
222
+ </x>
223
+ eoxml
224
+ reader.each do |node|
225
+ node.attributes.each do |key, value|
226
+ assert_equal value, node.attribute(key)
227
+ end
228
+ end
229
+ end
230
+
231
+ def test_attribute_at
232
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
233
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
234
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
235
+ </x>
236
+ eoxml
237
+ assert_nil reader.attribute_at(nil)
238
+ assert_nil reader.attribute_at(0)
239
+ assert_equal ['http://tenderlovemaking.com/', nil, 'true', nil, 'true', nil, 'http://tenderlovemaking.com/'],
240
+ reader.map { |x| x.attribute_at(0) }
241
+ end
242
+
243
+ def test_attribute
244
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
245
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
246
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
247
+ </x>
248
+ eoxml
249
+ assert_nil reader.attribute(nil)
250
+ assert_nil reader.attribute('awesome')
251
+ assert_equal [nil, nil, 'true', nil, 'true', nil, nil],
252
+ reader.map { |x| x.attribute('awesome') }
253
+ end
254
+
255
+ def test_attribute_length
256
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
257
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
258
+ <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
259
+ </x>
260
+ eoxml
261
+ assert_equal 0, reader.attribute_count
262
+ assert_equal [1, 0, 1, 0, 0, 0, 0], reader.map(&:attribute_count)
263
+ end
264
+
265
+ def test_depth
266
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
267
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
268
+ <tenderlove:foo>snuggles!</tenderlove:foo>
269
+ </x>
270
+ eoxml
271
+ assert_equal 0, reader.depth
272
+ assert_equal [0, 1, 1, 2, 1, 1, 0], reader.map(&:depth)
273
+ end
274
+
275
+ def test_encoding
276
+ string = <<-eoxml
277
+ <awesome>
278
+ <p xml:lang="en">The quick brown fox jumps over the lazy dog.</p>
279
+ <p xml:lang="ja">日本語が上手です</p>
280
+ </awesome>
281
+ eoxml
282
+ reader = Nokogiri::XML::Reader.from_memory(string, nil, 'UTF-8')
283
+ assert_equal ['UTF-8'], reader.map(&:encoding).uniq
284
+ end
285
+
286
+ def test_xml_version
287
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
288
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
289
+ <tenderlove:foo>snuggles!</tenderlove:foo>
290
+ </x>
291
+ eoxml
292
+ assert_nil reader.xml_version
293
+ assert_equal ['1.0'], reader.map(&:xml_version).uniq
294
+ end
295
+
296
+ def test_lang
297
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
298
+ <awesome>
299
+ <p xml:lang="en">The quick brown fox jumps over the lazy dog.</p>
300
+ <p xml:lang="ja">日本語が上手です</p>
301
+ </awesome>
302
+ eoxml
303
+ assert_nil reader.lang
304
+ assert_equal [nil, nil, "en", "en", "en", nil, "ja", "ja", "ja", nil, nil],
305
+ reader.map(&:lang)
306
+ end
307
+
308
+ def test_value
309
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
310
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'>
311
+ <tenderlove:foo>snuggles!</tenderlove:foo>
312
+ </x>
313
+ eoxml
314
+ assert_nil reader.value
315
+ assert_equal [nil, "\n ", nil, "snuggles!", nil, "\n ", nil],
316
+ reader.map(&:value)
317
+ end
318
+
319
+ def test_prefix
320
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
321
+ <x xmlns:edi='http://ecommerce.example.org/schema'>
322
+ <edi:foo>hello</edi:foo>
323
+ </x>
324
+ eoxml
325
+ assert_nil reader.prefix
326
+ assert_equal [nil, nil, "edi", nil, "edi", nil, nil],
327
+ reader.map(&:prefix)
328
+ end
329
+
330
+ def test_node_type
331
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
332
+ <x>
333
+ <y>hello</y>
334
+ </x>
335
+ eoxml
336
+ assert_equal 0, reader.node_type
337
+ assert_equal [1, 14, 1, 3, 15, 14, 15], reader.map(&:node_type)
338
+ end
339
+
340
+ def test_inner_xml
341
+ str = "<x><y>hello</y></x>"
342
+ reader = Nokogiri::XML::Reader.from_memory(str)
343
+
344
+ reader.read
345
+
346
+ assert_equal "<y>hello</y>", reader.inner_xml
347
+ end
348
+
349
+ def test_outer_xml
350
+ str = ["<x><y>hello</y></x>", "<y>hello</y>", "hello", "<y/>", "<x/>"]
351
+ reader = Nokogiri::XML::Reader.from_memory(str.first)
352
+
353
+ xml = []
354
+ reader.map { |node| xml << node.outer_xml }
355
+
356
+ assert_equal str, xml
357
+ end
358
+
359
+ def test_outer_xml_with_empty_nodes
360
+ str = ["<x><y/></x>", "<y/>", "<x/>"]
361
+ reader = Nokogiri::XML::Reader.from_memory(str.first)
362
+
363
+ xml = []
364
+ reader.map { |node| xml << node.outer_xml }
365
+
366
+ assert_equal str, xml
367
+ end
368
+
369
+ def test_state
370
+ reader = Nokogiri::XML::Reader.from_memory('<foo>bar</bar>')
371
+ assert reader.state
372
+ end
373
+
374
+ def test_ns_uri
375
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
376
+ <x xmlns:edi='http://ecommerce.example.org/schema'>
377
+ <edi:foo>hello</edi:foo>
378
+ </x>
379
+ eoxml
380
+ assert_nil reader.namespace_uri
381
+ assert_equal([nil,
382
+ nil,
383
+ "http://ecommerce.example.org/schema",
384
+ nil,
385
+ "http://ecommerce.example.org/schema",
386
+ nil,
387
+ nil],
388
+ reader.map(&:namespace_uri))
389
+ end
390
+
391
+ def test_namespaced_attributes
392
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
393
+ <x xmlns:edi='http://ecommerce.example.org/schema' xmlns:commons="http://rets.org/xsd/RETSCommons">
394
+ <edi:foo commons:street-number="43">hello</edi:foo>
395
+ <y edi:name="francis" bacon="87"/>
396
+ </x>
397
+ eoxml
398
+ attr_ns = []
399
+ while reader.read
400
+ if reader.node_type == Nokogiri::XML::Node::ELEMENT_NODE
401
+ reader.attribute_nodes.each {|attr| attr_ns << (attr.namespace.nil? ? nil : attr.namespace.prefix) }
402
+ end
403
+ end
404
+ assert_equal(['commons',
405
+ 'edi',
406
+ nil],
407
+ attr_ns)
408
+ end
409
+
410
+ def test_local_name
411
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
412
+ <x xmlns:edi='http://ecommerce.example.org/schema'>
413
+ <edi:foo>hello</edi:foo>
414
+ </x>
415
+ eoxml
416
+ assert_nil reader.local_name
417
+ assert_equal(["x", "#text", "foo", "#text", "foo", "#text", "x"],
418
+ reader.map(&:local_name))
419
+ end
420
+
421
+ def test_name
422
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
423
+ <x xmlns:edi='http://ecommerce.example.org/schema'>
424
+ <edi:foo>hello</edi:foo>
425
+ </x>
426
+ eoxml
427
+ assert_nil reader.name
428
+ assert_equal(["x", "#text", "edi:foo", "#text", "edi:foo", "#text", "x"],
429
+ reader.map(&:name))
430
+ end
431
+
432
+ def test_base_uri
433
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
434
+ <x xml:base="http://base.example.org/base/">
435
+ <link href="link"/>
436
+ <other xml:base="http://other.example.org/"/>
437
+ <relative xml:base="relative">
438
+ <link href="stuff" />
439
+ </relative>
440
+ </x>
441
+ eoxml
442
+
443
+ assert_nil reader.base_uri
444
+ assert_equal(["http://base.example.org/base/",
445
+ "http://base.example.org/base/",
446
+ "http://base.example.org/base/",
447
+ "http://base.example.org/base/",
448
+ "http://other.example.org/",
449
+ "http://base.example.org/base/",
450
+ "http://base.example.org/base/relative",
451
+ "http://base.example.org/base/relative",
452
+ "http://base.example.org/base/relative",
453
+ "http://base.example.org/base/relative",
454
+ "http://base.example.org/base/relative",
455
+ "http://base.example.org/base/",
456
+ "http://base.example.org/base/"],
457
+ reader.map(&:base_uri))
458
+ end
459
+
460
+ def test_xlink_href_without_base_uri
461
+ reader = Nokogiri::XML::Reader(<<-eoxml)
462
+ <x xmlns:xlink="http://www.w3.org/1999/xlink">
463
+ <link xlink:href="#other">Link</link>
464
+ <other id="other">Linked Element</other>
465
+ </x>
466
+ eoxml
467
+
468
+ reader.each do |node|
469
+ if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
470
+ if node.name == 'link'
471
+ assert_nil node.base_uri
472
+ end
473
+ end
474
+ end
475
+ end
476
+
477
+ def test_xlink_href_with_base_uri
478
+ reader = Nokogiri::XML::Reader(<<-eoxml)
479
+ <x xml:base="http://base.example.org/base/"
480
+ xmlns:xlink="http://www.w3.org/1999/xlink">
481
+ <link xlink:href="#other">Link</link>
482
+ <other id="other">Linked Element</other>
483
+ </x>
484
+ eoxml
485
+
486
+ reader.each do |node|
487
+ if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
488
+ assert_equal node.base_uri, "http://base.example.org/base/"
489
+ end
490
+ end
491
+ end
492
+
493
+ def test_read_from_memory
494
+ called = false
495
+ reader = Nokogiri::XML::Reader.from_memory('<foo>bar</foo>')
496
+ reader.each do |node|
497
+ called = true
498
+ assert node
499
+ end
500
+ assert called
501
+ end
502
+
503
+ def test_large_document_smoke_test
504
+ # simply run on a large document to verify that there no GC issues
505
+ xml = []
506
+ xml << "<elements>"
507
+ 10000.times { |j| xml << "<element id=\"#{j}\"/>" }
508
+ xml << "</elements>"
509
+ xml = xml.join("\n")
510
+
511
+ Nokogiri::XML::Reader.from_memory(xml).each do |e|
512
+ e.attributes
513
+ end
514
+ end
515
+
516
+ def test_correct_outer_xml_inclusion
517
+ xml = Nokogiri::XML::Reader.from_io(StringIO.new(<<-eoxml))
518
+ <root-element>
519
+ <children>
520
+ <child n="1">
521
+ <field>child-1</field>
522
+ </child>
523
+ <child n="2">
524
+ <field>child-2</field>
525
+ </child>
526
+ <child n="3">
527
+ <field>child-3</field>
528
+ </child>
529
+ </children>
530
+ </root-element>
531
+ eoxml
532
+
533
+ nodelengths = []
534
+ has_child2 = []
535
+
536
+ xml.each do |node|
537
+ if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT and node.name == "child"
538
+ nodelengths << node.outer_xml.length
539
+ has_child2 << !!(node.outer_xml =~ /child-2/)
540
+ end
541
+ end
542
+
543
+ assert_equal(nodelengths[0], nodelengths[1])
544
+ assert(has_child2[1])
545
+ assert(!has_child2[0])
546
+ end
547
+
548
+ def test_correct_inner_xml_inclusion
549
+ xml = Nokogiri::XML::Reader.from_io(StringIO.new(<<-eoxml))
550
+ <root-element>
551
+ <children>
552
+ <child n="1">
553
+ <field>child-1</field>
554
+ </child>
555
+ <child n="2">
556
+ <field>child-2</field>
557
+ </child>
558
+ <child n="3">
559
+ <field>child-3</field>
560
+ </child>
561
+ </children>
562
+ </root-element>
563
+ eoxml
564
+
565
+ nodelengths = []
566
+ has_child2 = []
567
+
568
+ xml.each do |node|
569
+ if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT and node.name == "child"
570
+ nodelengths << node.inner_xml.length
571
+ has_child2 << !!(node.inner_xml =~ /child-2/)
572
+ end
573
+ end
574
+
575
+ assert_equal(nodelengths[0], nodelengths[1])
576
+ assert(has_child2[1])
577
+ assert(!has_child2[0])
578
+ end
579
+
580
+ def test_nonexistent_attribute
581
+ require 'nokogiri'
582
+ reader = Nokogiri::XML::Reader("<root xmlns='bob'><el attr='fred' /></root>")
583
+ reader.read # root
584
+ reader.read # el
585
+ assert_equal nil, reader.attribute('other')
586
+ end
587
+ end
588
+ end
589
+ end