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.
- checksums.yaml +4 -4
- data/.cross_rubies +2 -0
- data/.travis.yml +19 -9
- data/CHANGELOG.rdoc +73 -5
- data/CONTRIBUTING.md +42 -0
- data/Gemfile +10 -9
- data/LICENSE.txt +1 -1
- data/Manifest.txt +7 -2
- data/README.md +23 -27
- data/ROADMAP.md +11 -1
- data/Rakefile +36 -17
- data/bin/nokogiri +2 -2
- data/dependencies.yml +29 -4
- data/ext/java/nokogiri/HtmlElementDescription.java +5 -2
- data/ext/java/nokogiri/NokogiriService.java +19 -0
- data/ext/java/nokogiri/XmlAttr.java +3 -1
- data/ext/java/nokogiri/XmlDocumentFragment.java +0 -14
- data/ext/java/nokogiri/XmlNode.java +106 -63
- data/ext/java/nokogiri/XmlXpathContext.java +12 -12
- data/ext/java/nokogiri/XsltStylesheet.java +11 -4
- data/ext/java/nokogiri/internals/HtmlDomParserContext.java +8 -1
- data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +1 -2
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +7 -7
- data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +1 -1
- data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +0 -1
- data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +3 -3
- data/ext/java/nokogiri/internals/ParserContext.java +4 -0
- data/ext/java/nokogiri/internals/SaveContextVisitor.java +18 -13
- data/ext/nokogiri/extconf.rb +163 -79
- data/ext/nokogiri/html_document.c +6 -6
- data/ext/nokogiri/html_element_description.c +1 -1
- data/ext/nokogiri/html_entity_lookup.c +1 -1
- data/ext/nokogiri/html_sax_parser_context.c +4 -4
- data/ext/nokogiri/html_sax_push_parser.c +2 -2
- data/ext/nokogiri/nokogiri.c +0 -7
- data/ext/nokogiri/nokogiri.h +1 -34
- data/ext/nokogiri/xml_attr.c +2 -2
- data/ext/nokogiri/xml_comment.c +1 -1
- data/ext/nokogiri/xml_document.c +20 -22
- data/ext/nokogiri/xml_encoding_handler.c +3 -3
- data/ext/nokogiri/xml_entity_reference.c +1 -1
- data/ext/nokogiri/xml_namespace.c +56 -17
- data/ext/nokogiri/xml_node.c +73 -67
- data/ext/nokogiri/xml_node_set.c +164 -146
- data/ext/nokogiri/xml_node_set.h +3 -4
- data/ext/nokogiri/xml_processing_instruction.c +2 -2
- data/ext/nokogiri/xml_reader.c +5 -18
- data/ext/nokogiri/xml_sax_parser.c +9 -12
- data/ext/nokogiri/xml_sax_parser_context.c +1 -1
- data/ext/nokogiri/xml_sax_push_parser.c +1 -1
- data/ext/nokogiri/xml_schema.c +1 -1
- data/ext/nokogiri/xml_syntax_error.c +0 -4
- data/ext/nokogiri/xml_syntax_error.h +0 -1
- data/ext/nokogiri/xml_text.c +1 -1
- data/ext/nokogiri/xml_xpath_context.c +15 -24
- data/ext/nokogiri/xslt_stylesheet.c +6 -6
- data/lib/nekohtml.jar +0 -0
- data/lib/nokogiri.rb +14 -7
- data/lib/nokogiri/css/parser.rb +8 -2
- data/lib/nokogiri/css/parser.y +7 -2
- data/lib/nokogiri/html/document.rb +4 -2
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/document.rb +7 -1
- data/lib/nokogiri/xml/dtd.rb +4 -4
- data/lib/nokogiri/xml/node.rb +6 -10
- data/lib/nokogiri/xml/node_set.rb +3 -3
- data/lib/nokogiri/xml/parse_options.rb +22 -0
- data/lib/serializer.jar +0 -0
- data/lib/xalan.jar +0 -0
- data/lib/xercesImpl.jar +0 -0
- data/lib/xml-apis.jar +0 -0
- data/tasks/test.rb +5 -0
- data/test/css/test_parser.rb +7 -1
- data/test/files/GH_1042.html +18 -0
- data/test/files/namespace_pressure_test.xml +1684 -0
- data/test/files/tlm.html +2 -1
- data/test/helper.rb +4 -0
- data/test/html/sax/test_parser.rb +2 -2
- data/test/html/test_document.rb +47 -11
- data/test/html/test_document_encoding.rb +55 -58
- data/test/html/test_document_fragment.rb +27 -23
- data/test/html/test_node.rb +16 -0
- data/test/html/test_node_encoding.rb +71 -13
- data/test/namespaces/test_namespaces_in_parsed_doc.rb +14 -0
- data/test/test_css_cache.rb +1 -1
- data/test/test_encoding_handler.rb +2 -0
- data/test/test_xslt_transforms.rb +38 -3
- data/test/xml/sax/test_parser.rb +54 -53
- data/test/xml/test_document.rb +7 -2
- data/test/xml/test_document_encoding.rb +19 -16
- data/test/xml/test_document_fragment.rb +12 -0
- data/test/xml/test_dtd_encoding.rb +0 -2
- data/test/xml/test_namespace.rb +2 -2
- data/test/xml/test_node.rb +15 -4
- data/test/xml/test_node_attributes.rb +6 -0
- data/test/xml/test_node_encoding.rb +49 -87
- data/test/xml/test_node_reparenting.rb +193 -18
- data/test/xml/test_node_set.rb +1 -1
- data/test/xml/test_reader.rb +589 -0
- data/test/xml/test_reader_encoding.rb +100 -102
- data/test/xml/test_unparented_node.rb +14 -1
- data/test/xslt/test_exception_handling.rb +1 -1
- data/test_all +47 -33
- metadata +38 -36
- data/CHANGELOG.ja.rdoc +0 -1057
- 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
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
-
|
234
|
-
|
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
|
237
|
-
|
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
|
data/test/xml/test_node_set.rb
CHANGED
@@ -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
|