nokogiri 1.6.5-java → 1.6.6.1-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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.cross_rubies +5 -0
  3. data/.travis.yml +10 -20
  4. data/CHANGELOG.ja.rdoc +28 -1
  5. data/CHANGELOG.rdoc +28 -1
  6. data/Gemfile +1 -1
  7. data/Manifest.txt +5 -1
  8. data/README.ja.rdoc +10 -9
  9. data/README.rdoc +6 -9
  10. data/ROADMAP.md +15 -3
  11. data/Rakefile +1 -3
  12. data/bin/nokogiri +48 -8
  13. data/ext/java/nokogiri/HtmlSaxParserContext.java +1 -1
  14. data/ext/java/nokogiri/HtmlSaxPushParser.java +244 -0
  15. data/ext/java/nokogiri/NokogiriService.java +9 -0
  16. data/ext/java/nokogiri/XmlComment.java +2 -0
  17. data/ext/java/nokogiri/XmlNode.java +57 -30
  18. data/ext/java/nokogiri/XmlSyntaxError.java +11 -9
  19. data/ext/nokogiri/extconf.rb +18 -3
  20. data/ext/nokogiri/xml_comment.c +17 -2
  21. data/ext/nokogiri/xml_node.c +66 -6
  22. data/ext/nokogiri/xml_syntax_error.c +4 -0
  23. data/ext/nokogiri/xml_syntax_error.h +1 -0
  24. data/lib/nokogiri.rb +2 -2
  25. data/lib/nokogiri/decorators/slop.rb +7 -8
  26. data/lib/nokogiri/html/document_fragment.rb +0 -2
  27. data/lib/nokogiri/html/sax/push_parser.rb +22 -2
  28. data/lib/nokogiri/nokogiri.jar +0 -0
  29. data/lib/nokogiri/version.rb +1 -1
  30. data/lib/nokogiri/xml.rb +1 -0
  31. data/lib/nokogiri/xml/document.rb +4 -4
  32. data/lib/nokogiri/xml/document_fragment.rb +39 -2
  33. data/lib/nokogiri/xml/node.rb +11 -181
  34. data/lib/nokogiri/xml/node_set.rb +41 -85
  35. data/lib/nokogiri/xml/searchable.rb +221 -0
  36. data/ports/patches/sort-patches-by-date +25 -0
  37. data/test/css/test_nthiness.rb +1 -1
  38. data/test/html/sax/test_push_parser.rb +87 -0
  39. data/test/html/test_document.rb +20 -5
  40. data/test/html/test_document_fragment.rb +25 -0
  41. data/test/xml/test_attr.rb +5 -2
  42. data/test/xml/test_builder.rb +27 -1
  43. data/test/xml/test_comment.rb +11 -0
  44. data/test/xml/test_document.rb +34 -0
  45. data/test/xml/test_document_fragment.rb +40 -9
  46. data/test/xml/test_namespace.rb +1 -0
  47. data/test/xml/test_node.rb +37 -1
  48. data/test/xml/test_node_set.rb +56 -36
  49. data/test/xml/test_xpath.rb +65 -19
  50. data/test_all +11 -1
  51. metadata +12 -7
  52. data/tasks/nokogiri.org.rb +0 -24
@@ -355,7 +355,7 @@ eohtml
355
355
  File.open(HTML_FILE, 'rb') { |f| temp_html_file.write f.read }
356
356
  temp_html_file.close
357
357
  temp_html_file.open
358
- assert_equal Nokogiri::HTML.parse(File.read(HTML_FILE)).xpath('//div/a').length,
358
+ assert_equal Nokogiri::HTML.parse(File.read(HTML_FILE)).xpath('//div/a').length,
359
359
  Nokogiri::HTML.parse(temp_html_file).xpath('//div/a').length
360
360
  end
361
361
 
@@ -450,7 +450,7 @@ eohtml
450
450
  assert_equal "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", html.internal_subset.system_id
451
451
  assert_equal "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">", html.to_s[0,97]
452
452
  end
453
-
453
+
454
454
  def test_content_size
455
455
  html = Nokogiri::HTML("<div>\n</div>")
456
456
  assert_equal 1, html.content.size
@@ -613,15 +613,30 @@ eohtml
613
613
  assert_equal "", Nokogiri::HTML.parse("").text
614
614
  end
615
615
 
616
- def test_capturing_nonparse_errors_during_clone
616
+ def test_capturing_nonparse_errors_during_document_clone
617
617
  # see https://github.com/sparklemotion/nokogiri/issues/1196 for background
618
618
  original = Nokogiri::HTML.parse("<div id='unique'></div><div id='unique'></div>")
619
- original_errors = original.errors
619
+ original_errors = original.errors.dup
620
620
 
621
621
  copy = original.dup
622
622
  assert_equal original_errors, copy.errors
623
623
  end
624
+
625
+ def test_capturing_nonparse_errors_during_node_copy_between_docs
626
+ skip("JRuby HTML parse errors are different than libxml2's") if Nokogiri.jruby?
627
+
628
+ doc1 = Nokogiri::HTML("<div id='unique'>one</div>")
629
+ doc2 = Nokogiri::HTML("<div id='unique'>two</div>")
630
+ node1 = doc1.at_css("#unique")
631
+ node2 = doc2.at_css("#unique")
632
+
633
+ original_errors = doc1.errors.dup
634
+
635
+ node1.add_child node2
636
+
637
+ assert_equal original_errors.length+1, doc1.errors.length
638
+ assert_match(/ID unique already defined/, doc1.errors.last.to_s)
639
+ end
624
640
  end
625
641
  end
626
642
  end
627
-
@@ -267,6 +267,31 @@ module Nokogiri
267
267
  assert frag.errors.any?{|err| err.to_s =~ /Tag hello invalid/}, "errors should be on the context node's document"
268
268
  assert frag.errors.none?{|err| err.to_s =~ /jimmy/}, "errors should not include pre-existing document errors"
269
269
  end
270
+
271
+ def test_capturing_nonparse_errors_during_fragment_clone
272
+ # see https://github.com/sparklemotion/nokogiri/issues/1196 for background
273
+ original = Nokogiri::HTML.fragment("<div id='unique'></div>")
274
+ original_errors = original.errors.dup
275
+
276
+ copy = original.dup
277
+ assert_equal original_errors, copy.errors
278
+ end
279
+
280
+ def test_capturing_nonparse_errors_during_node_copy_between_fragments
281
+ skip("JRuby HTML parse errors are different than libxml2's") if Nokogiri.jruby?
282
+
283
+ frag1 = Nokogiri::HTML.fragment("<div id='unique'>one</div>")
284
+ frag2 = Nokogiri::HTML.fragment("<div id='unique'>two</div>")
285
+ node1 = frag1.at_css("#unique")
286
+ node2 = frag2.at_css("#unique")
287
+
288
+ original_errors = frag1.errors.dup
289
+
290
+ node1.add_child node2 # we should also not see an error on stderr
291
+
292
+ assert_equal original_errors.length+1, frag1.errors.length
293
+ assert_match(/ID unique already defined/, frag1.errors.last.to_s)
294
+ end
270
295
  end
271
296
  end
272
297
  end
@@ -27,12 +27,15 @@ module Nokogiri
27
27
  assert_equal "Y&ent1;", street.value
28
28
  end
29
29
 
30
- def test_unlink
30
+ def test_unlink # aliased as :remove
31
31
  xml = Nokogiri::XML.parse(File.read(XML_FILE), XML_FILE)
32
32
  address = xml.xpath('/staff/employee/address').first
33
33
  assert_equal 'Yes', address['domestic']
34
- address.attribute_nodes.first.unlink
34
+
35
+ attr = address.attribute_nodes.first
36
+ return_val = attr.unlink
35
37
  assert_nil address['domestic']
38
+ assert_equal attr, return_val
36
39
  end
37
40
 
38
41
  def test_parsing_attribute_namespace
@@ -305,7 +305,33 @@ module Nokogiri
305
305
  builder.to_xml.gsub(/\n/, ''))
306
306
  end
307
307
 
308
- private
308
+ def test_builder_can_inherit_parent_namespace
309
+ builder = Nokogiri::XML::Builder.new
310
+ builder.products {
311
+ builder.parent.default_namespace = "foo"
312
+ builder.product {
313
+ builder.parent.default_namespace = nil
314
+ }
315
+ }
316
+ doc = builder.doc
317
+ ['product', 'products'].each do |n|
318
+ assert_equal doc.at_xpath("//*[local-name() = '#{n}']").namespace.href, 'foo'
319
+ end
320
+ end
321
+
322
+ def test_builder_can_handle_namespace_override
323
+ builder = Nokogiri::XML::Builder.new
324
+ builder.products('xmlns:foo' => 'bar') {
325
+ builder.product('xmlns:foo' => 'baz')
326
+ }
327
+
328
+ doc = builder.doc
329
+ assert_equal doc.at_xpath("//*[local-name() = 'product']").namespaces['xmlns:foo'], 'baz'
330
+ assert_equal doc.at_xpath("//*[local-name() = 'products']").namespaces['xmlns:foo'], 'bar'
331
+ assert_nil doc.at_xpath("//*[local-name() = 'products']").namespace
332
+ end
333
+
334
+ private
309
335
 
310
336
  def namespaces_defined_on(node)
311
337
  Hash[*node.namespace_definitions.collect{|n| ["xmlns:" + n.prefix, n.href]}.flatten]
@@ -19,6 +19,17 @@ module Nokogiri
19
19
  assert(!@xml.root.comment?)
20
20
  end
21
21
 
22
+ def test_passing_a_node_uses_the_node_document
23
+ comment = Nokogiri::XML::Comment.new(@xml.at_css("employee"), 'hello world')
24
+ assert_equal @xml, comment.document
25
+ end
26
+
27
+ def test_passing_anything_else
28
+ assert_raises ArgumentError do
29
+ Nokogiri::XML::Comment.new("NOT A NOKOGIRI CLASS", 'hello world')
30
+ end
31
+ end
32
+
22
33
  def test_many_comments
23
34
  100.times {
24
35
  Nokogiri::XML::Comment.new(@xml, 'hello world')
@@ -701,6 +701,26 @@ module Nokogiri
701
701
  assert_equal 0, ns.length
702
702
  end
703
703
 
704
+ def test_document_search_with_multiple_queries
705
+ xml = '<document>
706
+ <thing>
707
+ <div class="title">important thing</div>
708
+ </thing>
709
+ <thing>
710
+ <div class="content">stuff</div>
711
+ </thing>
712
+ <thing>
713
+ <p class="blah">more stuff</div>
714
+ </thing>
715
+ </document>'
716
+ document = Nokogiri::XML(xml)
717
+ assert_kind_of Nokogiri::XML::Document, document
718
+
719
+ assert_equal 3, document.xpath('.//div', './/p').length
720
+ assert_equal 3, document.css('.title', '.content', 'p').length
721
+ assert_equal 3, document.search('.//div', 'p.blah').length
722
+ end
723
+
704
724
  def test_bad_xpath_raises_syntax_error
705
725
  assert_raises(XML::XPath::SyntaxError) {
706
726
  @xml.xpath('\\')
@@ -832,6 +852,13 @@ module Nokogiri
832
852
  assert_equal 1, doc.xpath("//a:foo").length
833
853
  assert_equal 1, doc.xpath("//x:foo", "x" => "http://c.flavorjon.es/").length
834
854
  assert_match %r{foo c:attr}, doc.to_xml
855
+ doc.at_xpath("//x:foo", "x" => "http://c.flavorjon.es/").tap do |node|
856
+ assert_equal nil, node["attr"]
857
+ assert_equal "attr-value", node["c:attr"]
858
+ assert_equal nil, node.attribute_with_ns("attr", nil)
859
+ assert_equal "attr-value", node.attribute_with_ns("attr", "http://c.flavorjon.es/").value
860
+ assert_equal "attr-value", node.attributes["attr"].value
861
+ end
835
862
 
836
863
  doc.remove_namespaces!
837
864
 
@@ -842,6 +869,13 @@ module Nokogiri
842
869
  assert_equal 0, doc.xpath("//a:foo", namespaces).length
843
870
  assert_equal 0, doc.xpath("//x:foo", "x" => "http://c.flavorjon.es/").length
844
871
  assert_match %r{foo attr}, doc.to_xml
872
+ doc.at_xpath("//container/foo").tap do |node|
873
+ assert_equal "attr-value", node["attr"]
874
+ assert_equal nil, node["c:attr"]
875
+ assert_equal "attr-value", node.attribute_with_ns("attr", nil).value
876
+ assert_equal nil, node.attribute_with_ns("attr", "http://c.flavorjon.es/")
877
+ assert_equal "attr-value", node.attributes["attr"].value # doesn't change!
878
+ end
845
879
  end
846
880
 
847
881
  # issue #785
@@ -125,18 +125,49 @@ module Nokogiri
125
125
  fragment = Nokogiri::XML::Document.new.fragment(
126
126
  '<div><p id="content">hi</p></div>'
127
127
  )
128
- css = fragment.children.css('p')
129
- xpath = fragment.children.xpath('.//p')
130
- assert_equal css, xpath
128
+ expected = fragment.children.xpath('.//p')
129
+ assert_equal 1, expected.length
130
+
131
+ css = fragment.children.css('p')
132
+ search_css = fragment.children.search('p')
133
+ search_xpath = fragment.children.search('.//p')
134
+ assert_equal expected, css
135
+ assert_equal expected, search_css
136
+ assert_equal expected, search_xpath
131
137
  end
132
138
 
133
- def test_fragment_search
134
- frag = Nokogiri::XML::Document.new.fragment '<p id="content">hi</p>'
135
-
136
- p_tag = frag.css('#content').first
137
- assert_equal 'p', p_tag.name
139
+ def test_fragment_search_three_ways
140
+ frag = Nokogiri::XML::Document.new.fragment '<p id="content">foo</p><p id="content">bar</p>'
141
+ expected = frag.xpath('./*[@id = "content"]')
142
+ assert_equal 2, expected.length
143
+
144
+ [
145
+ [:css, '#content'],
146
+ [:search, '#content'],
147
+ [:search, './*[@id = \'content\']'],
148
+ ].each do |method, query|
149
+ result = frag.send(method, query)
150
+ assert_equal(expected, result,
151
+ "fragment search with :#{method} using '#{query}' expected '#{expected}' got '#{result}'")
152
+ end
153
+ end
138
154
 
139
- assert_equal p_tag, frag.xpath('./*[@id = \'content\']').first
155
+ def test_fragment_search_with_multiple_queries
156
+ xml = '<thing>
157
+ <div class="title">important thing</div>
158
+ </thing>
159
+ <thing>
160
+ <div class="content">stuff</div>
161
+ </thing>
162
+ <thing>
163
+ <p class="blah">more stuff</div>
164
+ </thing>'
165
+ fragment = Nokogiri::XML.fragment(xml)
166
+ assert_kind_of Nokogiri::XML::DocumentFragment, fragment
167
+
168
+ assert_equal 3, fragment.xpath('.//div', './/p').length
169
+ assert_equal 3, fragment.css('.title', '.content', 'p').length
170
+ assert_equal 3, fragment.search('.//div', 'p.blah').length
140
171
  end
141
172
 
142
173
  def test_fragment_without_a_namespace_does_not_get_a_namespace
@@ -69,6 +69,7 @@ module Nokogiri
69
69
  def test_remove_entity_namespace
70
70
  s = %q{<?xml version='1.0'?><!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "XMLSchema.dtd" [<!ENTITY % p ''>]>}
71
71
  Nokogiri::XML(s).remove_namespaces!
72
+ # TODO: we should probably assert something here. See commit 14d2f59.
72
73
  end
73
74
 
74
75
  def test_maintain_element_namespaces
@@ -635,8 +635,17 @@ module Nokogiri
635
635
  def test_remove_attribute
636
636
  address = @xml.xpath('/staff/employee/address').first
637
637
  assert_equal 'Yes', address['domestic']
638
- address.remove_attribute 'domestic'
638
+ attr = address.attributes['domestic']
639
+
640
+ returned_attr = address.remove_attribute 'domestic'
639
641
  assert_nil address['domestic']
642
+ assert_equal attr, returned_attr
643
+ end
644
+
645
+ def test_remove_attribute_when_not_found
646
+ address = @xml.xpath('/staff/employee/address').first
647
+ attr = address.remove_attribute 'not-an-attribute'
648
+ assert_nil attr
640
649
  end
641
650
 
642
651
  def test_attribute_setter_accepts_non_string
@@ -1192,6 +1201,33 @@ eoxml
1192
1201
  assert pi_node.processing_instruction?
1193
1202
  assert ! div_node.processing_instruction?
1194
1203
  end
1204
+
1205
+ def test_node_lang
1206
+ document = Nokogiri::XML <<-EOXML
1207
+ <root>
1208
+ <div class='english' xml:lang='en'>
1209
+ <div class='english_child'>foo</div>
1210
+ </div>
1211
+ <div class='japanese' xml:lang='jp'>bar</div>
1212
+ <div class='unspecified'>bar</div>
1213
+ </root>
1214
+ EOXML
1215
+ assert_equal "en", document.at_css(".english").lang
1216
+ assert_equal "en", document.at_css(".english_child").lang
1217
+ assert_equal "jp", document.at_css(".japanese").lang
1218
+ assert_nil document.at_css(".unspecified").lang
1219
+ end
1220
+
1221
+ def test_set_node_lang
1222
+ document = Nokogiri::XML "<root><div class='subject'>foo</div></root>"
1223
+ subject = document.at_css(".subject")
1224
+
1225
+ subject.lang = "de"
1226
+ assert_equal "de", subject.lang
1227
+
1228
+ subject.lang = "fr"
1229
+ assert_equal "fr", subject.lang
1230
+ end
1195
1231
  end
1196
1232
  end
1197
1233
  end
@@ -124,26 +124,54 @@ module Nokogiri
124
124
  assert_equal 0, set.search('foo').length
125
125
  end
126
126
 
127
- def test_xpath_with_custom_object
127
+ def test_node_set_search_with_multiple_queries
128
+ xml = '<document>
129
+ <thing>
130
+ <div class="title">important thing</div>
131
+ </thing>
132
+ <thing>
133
+ <div class="content">stuff</div>
134
+ </thing>
135
+ <thing>
136
+ <p class="blah">more stuff</div>
137
+ </thing>
138
+ </document>'
139
+ set = Nokogiri::XML(xml).xpath(".//thing")
140
+ assert_kind_of Nokogiri::XML::NodeSet, set
141
+
142
+ assert_equal 3, set.xpath('./div', './p').length
143
+ assert_equal 3, set.css('.title', '.content', 'p').length
144
+ assert_equal 3, set.search('./div', 'p.blah').length
145
+ end
146
+
147
+ def test_search_with_custom_selector
128
148
  set = @xml.xpath('//staff')
129
- custom_employees = set.xpath('//*[awesome(.)]', Class.new {
130
- def awesome ns
131
- ns.select { |n| n.name == 'employee' }
132
- end
133
- }.new)
134
149
 
135
- assert_equal @xml.xpath('//employee'), custom_employees
150
+ [
151
+ [:xpath, '//*[awesome(.)]'],
152
+ [:search, '//*[awesome(.)]'],
153
+ [:css, '*:awesome'],
154
+ [:search, '*:awesome']
155
+ ].each do |method, query|
156
+ custom_employees = set.send(method, query, Class.new {
157
+ def awesome ns
158
+ ns.select { |n| n.name == 'employee' }
159
+ end
160
+ }.new)
161
+
162
+ assert_equal(@xml.xpath('//employee'), custom_employees,
163
+ "using #{method} with custom selector '#{query}'")
164
+ end
136
165
  end
137
166
 
138
- def test_css_with_custom_object
167
+ def test_search_with_variable_bindings
139
168
  set = @xml.xpath('//staff')
140
- custom_employees = set.css('*:awesome', Class.new {
141
- def awesome ns
142
- ns.select { |n| n.name == 'employee' }
143
- end
144
- }.new)
145
169
 
146
- assert_equal @xml.xpath('//employee'), custom_employees
170
+ assert_equal(4, set.xpath('//address[@domestic=$value]', nil, :value => 'Yes').length,
171
+ "using #xpath with variable binding")
172
+
173
+ assert_equal(4, set.search('//address[@domestic=$value]', nil, :value => 'Yes').length,
174
+ "using #search with variable binding")
147
175
  end
148
176
 
149
177
  def test_search_self
@@ -151,26 +179,10 @@ module Nokogiri
151
179
  assert_equal set.to_a, set.search('.').to_a
152
180
  end
153
181
 
154
- def test_search_with_custom_object
155
- set = @xml.xpath('//staff')
156
- custom_employees = set.search('//*[awesome(.)]', Class.new {
157
- def awesome ns
158
- ns.select { |n| n.name == 'employee' }
159
- end
160
- }.new)
161
-
162
- assert_equal @xml.xpath('//employee'), custom_employees
163
- end
164
-
165
182
  def test_css_searches_match_self
166
183
  html = Nokogiri::HTML("<html><body><div class='a'></div></body></html>")
167
184
  set = html.xpath("/html/body/div")
168
185
  assert_equal set.first, set.css(".a").first
169
- end
170
-
171
- def test_search_with_css_matches_self
172
- html = Nokogiri::HTML("<html><body><div class='a'></div></body></html>")
173
- set = html.xpath("/html/body/div")
174
186
  assert_equal set.first, set.search(".a").first
175
187
  end
176
188
 
@@ -311,9 +323,22 @@ module Nokogiri
311
323
  assert_equal node_set.xpath('./employeeId'), (node_set > 'employeeId')
312
324
  end
313
325
 
314
- def test_at
326
+ def test_at_performs_a_search_with_css
327
+ assert node_set = @xml.search('//employee')
328
+ assert_equal node_set.first.first_element_child, node_set.at('employeeId')
329
+ assert_equal node_set.first.first_element_child, node_set.%('employeeId')
330
+ end
331
+
332
+ def test_at_performs_a_search_with_xpath
333
+ assert node_set = @xml.search('//employee')
334
+ assert_equal node_set.first.first_element_child, node_set.at('./employeeId')
335
+ assert_equal node_set.first.first_element_child, node_set.%('./employeeId')
336
+ end
337
+
338
+ def test_at_with_integer_index
315
339
  assert node_set = @xml.search('//employee')
316
340
  assert_equal node_set.first, node_set.at(0)
341
+ assert_equal node_set.first, node_set % 0
317
342
  end
318
343
 
319
344
  def test_at_xpath
@@ -326,11 +351,6 @@ module Nokogiri
326
351
  assert_equal node_set.first.first_element_child, node_set.at_css('employeeId')
327
352
  end
328
353
 
329
- def test_percent
330
- assert node_set = @xml.search('//employee')
331
- assert_equal node_set.first, node_set % 0
332
- end
333
-
334
354
  def test_to_ary
335
355
  assert node_set = @xml.search('//employee')
336
356
  foo = []