nokogiri 1.6.8.rc3 → 1.6.8

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/.travis.yml +5 -3
  3. data/CHANGELOG.rdoc +27 -4
  4. data/CONTRIBUTING.md +1 -1
  5. data/Gemfile +7 -7
  6. data/Manifest.txt +1 -1
  7. data/README.md +0 -3
  8. data/Rakefile +10 -11
  9. data/dependencies.yml +29 -4
  10. data/ext/nokogiri/extconf.rb +74 -19
  11. data/ext/nokogiri/xml_node.c +22 -9
  12. data/ext/nokogiri/xml_reader.c +0 -13
  13. data/ext/nokogiri/xml_sax_parser.c +7 -7
  14. data/lib/nokogiri.rb +11 -7
  15. data/lib/nokogiri/html/document.rb +4 -2
  16. data/lib/nokogiri/version.rb +1 -1
  17. data/lib/nokogiri/xml/document.rb +1 -1
  18. data/lib/nokogiri/xml/parse_options.rb +22 -0
  19. data/ports/archives/libxml2-2.9.4.tar.gz +0 -0
  20. data/ports/archives/libxslt-1.1.29.tar.gz +0 -0
  21. data/tasks/test.rb +5 -0
  22. data/test/html/test_document.rb +26 -0
  23. data/test/html/test_document_encoding.rb +5 -0
  24. data/test/html/test_document_fragment.rb +5 -0
  25. data/test/test_encoding_handler.rb +2 -0
  26. data/test/test_xslt_transforms.rb +33 -0
  27. data/test/xml/sax/test_parser.rb +15 -7
  28. data/test/xml/test_document_encoding.rb +5 -0
  29. data/test/xml/test_document_fragment.rb +12 -0
  30. data/test/xml/test_node_attributes.rb +6 -0
  31. data/test/xml/test_node_reparenting.rb +193 -18
  32. data/test/xml/test_reader.rb +589 -0
  33. data/test/xml/test_unparented_node.rb +13 -0
  34. data/test_all +33 -42
  35. metadata +34 -51
  36. data/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +0 -222
  37. data/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +0 -53
  38. data/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +0 -60
  39. data/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +0 -42
  40. data/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +0 -164
  41. data/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +0 -587
  42. data/patches/libxslt/0008-Fix-direct-pattern-matching.patch +0 -80
  43. data/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +0 -185
  44. data/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +0 -126
  45. data/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +0 -25
  46. data/patches/libxslt/0014-Fix-for-bug-436589.patch +0 -43
  47. data/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +0 -41
  48. data/patches/libxslt/0016-Fix-for-type-confusion-in-preprocessing-attributes.patch +0 -29
  49. data/patches/libxslt/0017-Updated-config.guess.patch +0 -1226
  50. data/ports/archives/libxml2-2.9.3.tar.gz +0 -0
  51. data/ports/archives/libxslt-1.1.28.tar.gz +0 -0
  52. data/test/test_reader.rb +0 -577
@@ -219,19 +219,6 @@ static VALUE reader_attribute(VALUE self, VALUE name)
219
219
  name = StringValue(name) ;
220
220
 
221
221
  value = xmlTextReaderGetAttribute(reader, (xmlChar*)StringValueCStr(name));
222
- if(value == NULL) {
223
- /* this section is an attempt to workaround older versions of libxml that
224
- don't handle namespaces properly in all attribute-and-friends functions */
225
- xmlChar *prefix = NULL ;
226
- xmlChar *localname = xmlSplitQName2((xmlChar*)StringValueCStr(name), &prefix);
227
- if (localname != NULL) {
228
- value = xmlTextReaderLookupNamespace(reader, localname);
229
- xmlFree(localname) ;
230
- } else {
231
- value = xmlTextReaderLookupNamespace(reader, prefix);
232
- }
233
- xmlFree(prefix);
234
- }
235
222
  if(value == NULL) return Qnil;
236
223
 
237
224
  rb_value = NOKOGIRI_STR_NEW2(value);
@@ -18,16 +18,16 @@ static void start_document(void * ctx)
18
18
 
19
19
  if(NULL != ctxt && ctxt->html != 1) {
20
20
  if(ctxt->standalone != -1) { /* -1 means there was no declaration */
21
- VALUE encoding = ctxt->encoding ?
22
- NOKOGIRI_STR_NEW2(ctxt->encoding) :
23
- Qnil;
21
+ VALUE encoding = Qnil ;
22
+ if (ctxt->encoding) {
23
+ encoding = NOKOGIRI_STR_NEW2(ctxt->encoding) ;
24
+ } else if (ctxt->input && ctxt->input->encoding) {
25
+ encoding = NOKOGIRI_STR_NEW2(ctxt->input->encoding) ;
26
+ }
24
27
 
25
- VALUE version = ctxt->version ?
26
- NOKOGIRI_STR_NEW2(ctxt->version) :
27
- Qnil;
28
+ VALUE version = ctxt->version ? NOKOGIRI_STR_NEW2(ctxt->version) : Qnil;
28
29
 
29
30
  VALUE standalone = Qnil;
30
-
31
31
  switch(ctxt->standalone)
32
32
  {
33
33
  case 0:
@@ -114,15 +114,19 @@ module Nokogiri
114
114
  def Slop(*args, &block)
115
115
  Nokogiri(*args, &block).slop!
116
116
  end
117
+
118
+ def install_default_aliases
119
+ # Make sure to support some popular encoding aliases not known by
120
+ # all iconv implementations.
121
+ {
122
+ 'Windows-31J' => 'CP932', # Windows-31J is the IANA registered name of CP932.
123
+ }.each { |alias_name, name|
124
+ EncodingHandler.alias(name, alias_name) if EncodingHandler[alias_name].nil?
125
+ }
126
+ end
117
127
  end
118
128
 
119
- # Make sure to support some popular encoding aliases not known by
120
- # all iconv implementations.
121
- {
122
- 'Windows-31J' => 'CP932', # Windows-31J is the IANA registered name of CP932.
123
- }.each { |alias_name, name|
124
- EncodingHandler.alias(name, alias_name) if EncodingHandler[alias_name].nil?
125
- }
129
+ Nokogiri.install_default_aliases
126
130
  end
127
131
 
128
132
  ###
@@ -173,7 +173,7 @@ module Nokogiri
173
173
 
174
174
  if string_or_io.respond_to?(:read)
175
175
  url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
176
- if !encoding
176
+ unless encoding
177
177
  # Libxml2's parser has poor support for encoding
178
178
  # detection. First, it does not recognize the HTML5
179
179
  # style meta charset declaration. Secondly, even if it
@@ -196,7 +196,9 @@ module Nokogiri
196
196
  end
197
197
 
198
198
  # read_memory pukes on empty docs
199
- return new if string_or_io.nil? or string_or_io.empty?
199
+ if string_or_io.nil? or string_or_io.empty?
200
+ return encoding ? new.tap { |i| i.encoding = encoding } : new
201
+ end
200
202
 
201
203
  encoding ||= EncodingReader.detect_encoding(string_or_io)
202
204
 
@@ -1,6 +1,6 @@
1
1
  module Nokogiri
2
2
  # The version of Nokogiri you are using
3
- VERSION = '1.6.8.rc3'
3
+ VERSION = '1.6.8'
4
4
 
5
5
  class VersionInfo # :nodoc:
6
6
  def jruby?
@@ -49,7 +49,7 @@ module Nokogiri
49
49
  if options.strict?
50
50
  raise Nokogiri::XML::SyntaxError.new("Empty document")
51
51
  else
52
- return new
52
+ return encoding ? new.tap { |i| i.encoding = encoding } : new
53
53
  end
54
54
  end
55
55
 
@@ -2,6 +2,28 @@ module Nokogiri
2
2
  module XML
3
3
  ###
4
4
  # Parse options for passing to Nokogiri.XML or Nokogiri.HTML
5
+ #
6
+ # == Building combinations of parse options
7
+ # You can build your own combinations of these parse options by using any of the following methods:
8
+ # *Note*: All examples attempt to set the +RECOVER+ & +NOENT+ options. All examples use Ruby 2 optional parameter syntax.
9
+ # [Ruby's bitwise operators] You can use the Ruby bitwise operators to set various combinations.
10
+ # <code>Nokogiri.XML('<content>Chapter 1</content', options: Nokogiri::XML::ParseOptions.new((1 << 0) | (1 << 1)))</code>
11
+ # [Method chaining] Every option has an equivalent method in lowercase. You can chain these methods together to set various combinations.
12
+ # <code>Nokogiri.XML('<content>Chapter 1</content', options: Nokogiri::XML::ParseOptions.new.recover.noent)</code>
13
+ # [Using Ruby Blocks] You can also setup parse combinations in the block passed to Nokogiri.XML or Nokogiri.HTML
14
+ # <code>Nokogiri.XML('<content>Chapter 1</content') {|config| config.recover.noent}</code>
15
+ #
16
+ # == Removing particular parse options
17
+ # You can also remove options from an instance of +ParseOptions+ dynamically.
18
+ # Every option has an equivalent <code>no{option}</code> method in lowercase. You can call these methods on an instance of +ParseOptions+ to remove the option.
19
+ # Note that this is not available for +STRICT+.
20
+ #
21
+ # # Setting the RECOVER & NOENT options...
22
+ # options = Nokogiri::XML::ParseOptions.new.recover.noent
23
+ # # later...
24
+ # options.norecover # Removes the Nokogiri::XML::ParseOptions::RECOVER option
25
+ # options.nonoent # Removes the Nokogiri::XML::ParseOptions::NOENT option
26
+ #
5
27
  class ParseOptions
6
28
  # Strict parsing
7
29
  STRICT = 0
@@ -5,6 +5,11 @@ namespace :test do
5
5
  Rake::Task["test"].invoke
6
6
  end
7
7
 
8
+ task :installed do
9
+ ENV['RUBY_FLAGS'] = "-w -Itest:."
10
+ sh 'rake test'
11
+ end
12
+
8
13
  desc "find call-seq in the rdoc"
9
14
  task :rdoc_call_seq => 'docs' do
10
15
  Dir['doc/**/*.html'].each { |docfile|
@@ -670,6 +670,32 @@ eohtml
670
670
  Nokogiri::XML::Element.new("div", doc).set_attribute('id', 'unique-issue-1262')
671
671
  assert_equal 0, doc.errors.length
672
672
  end
673
+
674
+ it "skips encoding for script tags" do
675
+ html = Nokogiri::HTML <<-EOHTML
676
+ <html>
677
+ <head>
678
+ <script>var isGreater = 4 > 5;</script>
679
+ </head>
680
+ <body></body>
681
+ </html>
682
+ EOHTML
683
+ node = html.xpath("//script").first
684
+ assert_equal("var isGreater = 4 > 5;", node.inner_html)
685
+ end
686
+
687
+ it "skips encoding for style tags" do
688
+ html = Nokogiri::HTML <<-EOHTML
689
+ <html>
690
+ <head>
691
+ <style>tr > div { display:block; }</style>
692
+ </head>
693
+ <body></body>
694
+ </html>
695
+ EOHTML
696
+ node = html.xpath("//style").first
697
+ assert_equal("tr > div { display:block; }", node.inner_html)
698
+ end
673
699
  end
674
700
  end
675
701
  end
@@ -80,6 +80,11 @@ module Nokogiri
80
80
  assert_equal ['http://tenderlovemaking.com/'],
81
81
  doc.css('a').map { |a| a['href'] }
82
82
  end
83
+
84
+ def test_empty_doc_encoding
85
+ encoding = 'US-ASCII'
86
+ assert_equal encoding, Nokogiri::HTML.parse(nil, nil, encoding).encoding
87
+ end
83
88
  end
84
89
 
85
90
  class TestDocumentEncodingDetection < Nokogiri::TestCase
@@ -21,6 +21,11 @@ module Nokogiri
21
21
  assert_equal 'EUC-JP', f.document.encoding
22
22
  assert_equal "こんにちは!", f.content
23
23
  end
24
+
25
+ def test_unlink_empty_document
26
+ frag = Nokogiri::HTML::DocumentFragment.parse('').unlink # must_not_raise
27
+ assert_nil frag.parent
28
+ end
24
29
 
25
30
  def test_colons_are_not_removed
26
31
  doc = Nokogiri::HTML::DocumentFragment.parse("<span>3:30pm</span>")
@@ -5,6 +5,8 @@ require "helper"
5
5
  class TestEncodingHandler < Nokogiri::TestCase
6
6
  def teardown
7
7
  Nokogiri::EncodingHandler.clear_aliases!
8
+ #Replace default aliases removed by clear_aliases!
9
+ Nokogiri.install_default_aliases
8
10
  end
9
11
 
10
12
  def test_get
@@ -35,6 +35,39 @@ class TestXsltTransforms < Nokogiri::TestCase
35
35
  assert_match %r{<h1></h1>|<h1/>}, result
36
36
  end
37
37
 
38
+ def test_xml_declaration
39
+ input_xml = <<-EOS
40
+ <?xml version="1.0" encoding="utf-8"?>
41
+ <report>
42
+ <title>My Report</title>
43
+ </report>
44
+ EOS
45
+
46
+ input_xsl = <<-EOS
47
+ <?xml version="1.0" encoding="utf-8"?>
48
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
49
+ <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
50
+ <xsl:template match="/">
51
+ <html>
52
+ <head>
53
+ <title><xsl:value-of select="report/title"/></title>
54
+ </head>
55
+ <body>
56
+ <h1><xsl:value-of select="report/title"/></h1>
57
+ </body>
58
+ </html>
59
+ </xsl:template>
60
+ </xsl:stylesheet>
61
+ EOS
62
+
63
+ require 'nokogiri'
64
+
65
+ xml = ::Nokogiri::XML(input_xml)
66
+ xsl = ::Nokogiri::XSLT(input_xsl)
67
+
68
+ assert_includes xsl.apply_to(xml), '<?xml version="1.0" encoding="utf-8"?>'
69
+ end
70
+
38
71
  def test_transform_with_output_style
39
72
  xslt = ""
40
73
  if Nokogiri.jruby?
@@ -44,13 +44,21 @@ module Nokogiri
44
44
  end
45
45
 
46
46
  def test_xml_decl
47
- {
48
- '' => nil,
49
- '<?xml version="1.0" ?>' => ['1.0'],
50
- '<?xml version="1.0" encoding="UTF-8" ?>' => ['1.0', 'UTF-8'],
51
- '<?xml version="1.0" standalone="yes"?>' => ['1.0', 'yes'],
52
- '<?xml version="1.0" standalone="no"?>' => ['1.0', 'no'],
53
- }.each do |decl,value|
47
+ [
48
+ ['', nil],
49
+ ['<?xml version="1.0" ?>',
50
+ ['1.0']],
51
+ ['<?xml version="1.0" encoding="UTF-8" ?>',
52
+ ['1.0', 'UTF-8']],
53
+ ['<?xml version="1.0" standalone="yes"?>',
54
+ ['1.0', 'yes']],
55
+ ['<?xml version="1.0" standalone="no"?>',
56
+ ['1.0', 'no']],
57
+ ['<?xml version="1.0" encoding="UTF-8" standalone="no"?>',
58
+ ['1.0', "UTF-8", 'no']],
59
+ ['<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>',
60
+ ['1.0', "ISO-8859-1", 'yes']]
61
+ ].each do |decl, value|
54
62
  parser = XML::SAX::Parser.new(Doc.new)
55
63
 
56
64
  xml = "#{decl}\n<root />"
@@ -21,6 +21,11 @@ module Nokogiri
21
21
  assert_equal 'UTF-8', Nokogiri::LIBXML_VERSION.encoding.name
22
22
  end
23
23
  end
24
+
25
+ def test_empty_doc_encoding
26
+ encoding = 'US-ASCII'
27
+ assert_equal encoding, Nokogiri::XML(nil, nil, encoding).encoding
28
+ end
24
29
  end
25
30
  end
26
31
  end
@@ -224,6 +224,18 @@ module Nokogiri
224
224
  Nokogiri::XML::Comment.new(frag,'moo')
225
225
  end
226
226
 
227
+ def test_issue_1077_parsing_of_frozen_strings
228
+ input = <<-EOS
229
+ <?xml version="1.0" encoding="utf-8"?>
230
+ <library>
231
+ <book title="I like turtles"/>
232
+ </library>
233
+ EOS
234
+ input.freeze
235
+
236
+ Nokogiri::XML::DocumentFragment.parse(input) # assert_nothing_raised
237
+ end
238
+
227
239
  if Nokogiri.uses_libxml?
228
240
  def test_for_libxml_in_context_fragment_parsing_bug_workaround
229
241
  10.times do
@@ -26,6 +26,12 @@ module Nokogiri
26
26
  assert_equal nil, node['lang']
27
27
  end
28
28
 
29
+ def test_unknown_namespace_prefix_should_not_be_removed
30
+ doc = Nokogiri::XML ''
31
+ elem = doc.create_element 'foo', 'bar:attr' => 'something'
32
+ assert_equal elem.attribute_nodes.first.name, 'bar:attr'
33
+ end
34
+
29
35
  def test_set_prefixed_attributes
30
36
  doc = Nokogiri::XML %Q{<root xmlns:foo="x"/>}
31
37
 
@@ -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