nokogiri 1.8.5 → 1.9.0.rc1
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/CHANGELOG.md +34 -0
- data/Gemfile +4 -4
- data/Manifest.txt +2 -1
- data/README.md +0 -1
- data/Rakefile +14 -4
- data/build_all +5 -1
- data/ext/nokogiri/extconf.rb +10 -6
- data/ext/nokogiri/xml_attr.c +26 -21
- data/ext/nokogiri/xml_document.c +4 -1
- data/ext/nokogiri/xml_namespace.c +3 -3
- data/ext/nokogiri/xml_namespace.h +1 -2
- data/ext/nokogiri/xml_node.c +55 -15
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/document_fragment.rb +11 -0
- data/lib/nokogiri/xml/node.rb +12 -0
- data/lib/nokogiri/xml/node_set.rb +4 -8
- data/test/helper.rb +1 -1
- data/test/html/test_document.rb +10 -0
- data/test/test_memory_leak.rb +71 -1
- data/test/xml/test_attr.rb +23 -1
- data/test/xml/test_builder.rb +12 -0
- data/test/xml/test_document_fragment.rb +14 -0
- data/test/xml/test_node.rb +55 -1
- data/test/xml/test_node_reparenting.rb +75 -6
- data/test/xml/test_node_set.rb +19 -0
- data/test/xml/test_text.rb +9 -0
- metadata +19 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d658fc7d5957c3a7ebb52b4760fe6a3e1b65bacdacd70c1ed6e193aea0742d3d
|
4
|
+
data.tar.gz: 2078571efdde9bc3a78b97545f3edbe5953b6ae4b977604362fcc2d22b14469c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8683c1e51a8ede1daf265e9a33af1aba329b91489c75da8608d40f0c06d2823d833236f21f05914acd860b7722822d8f9a9f36f3120a907eb126be8fe5b984b9
|
7
|
+
data.tar.gz: 134e6617355b1bb6aac6729c7a0ca0ceeead11304eaf28dd383a8c90b1e20be83aa16246e7bb90abddaba20cf7f203baba49756f4931735814502542cb40ad3c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
# 1.9.0.rc1 / 2018-12-10
|
2
|
+
|
3
|
+
## Security Notes
|
4
|
+
|
5
|
+
* [JRuby] Upgrade Xerces dependency from 2.11.0 to 2.12.0 to address upstream vulnerability CVE-2012-0881 [#1831] (Thanks @grajagandev for reporting.)
|
6
|
+
|
7
|
+
|
8
|
+
## Features
|
9
|
+
|
10
|
+
* `XML::Attr#value=` allows HTML node attribute values to be set to either a blank string or an empty boolean attribute. [#1800]
|
11
|
+
* Introduce `XML::Node#wrap` which does what `XML::NodeSet#wrap` has always done, but for a single node. [#1531] (Thanks, @ethirajsrinivasan!)
|
12
|
+
* [MRI] Improve installation experience on macOS High Sierra (Darwin). [#1812, #1813] (Thanks, @gpakosz and @nurse!)
|
13
|
+
* [MRI] Node#dup supports copying a node directly to a new document. See the method documentation for details.
|
14
|
+
* [MRI] DocumentFragment#dup is now more memory-efficient, avoiding making unnecessary copies. [#1063]
|
15
|
+
* [JRuby] NodeSet has been rewritten to improve performance! [#1795]
|
16
|
+
|
17
|
+
|
18
|
+
## Bug fixes
|
19
|
+
|
20
|
+
* `NodeSet#each` now returns `self` instead of zero. [#1822] (Thanks, @olehif!)
|
21
|
+
* [MRI] Address a memory leak when using XML::Builder to create nodes with namespaces. [#1810]
|
22
|
+
* [MRI] Address a memory leak when unparenting a DTD. [#1784] (Thanks, @stevecheckoway!)
|
23
|
+
* [MRI] Decrease large memory usage when making nested XPath queries. [#1749]
|
24
|
+
* [MRI] Use RbConfig::CONFIG instead of ::MAKEFILE_CONFIG to fix installations that use Makefile macros. [#1820] (Thanks, @nobu!)
|
25
|
+
* [JRuby] Fix failing tests on JRuby 9.2.x
|
26
|
+
* [JRuby] Fix default namespaces in nodes reparented into a different document [#1774]
|
27
|
+
* [JRuby] Fix support for Java 9. [#1759] (Thanks, @Taywee!)
|
28
|
+
|
29
|
+
|
30
|
+
## Dependencies
|
31
|
+
|
32
|
+
* [MRI] Upgrade mini_portile2 dependency from `~> 2.3.0` to `~> 2.4.0`
|
33
|
+
|
34
|
+
|
1
35
|
# 1.8.5 / 2018-10-04
|
2
36
|
|
3
37
|
## Security Notes
|
data/Gemfile
CHANGED
@@ -4,10 +4,10 @@
|
|
4
4
|
|
5
5
|
source "https://rubygems.org/"
|
6
6
|
|
7
|
-
gem "mini_portile2", "~>2.
|
7
|
+
gem "mini_portile2", "~>2.4.0"
|
8
8
|
|
9
9
|
gem "hoe-bundler", "~>1.2", :group => [:development, :test]
|
10
|
-
gem "hoe-debugging", "~>
|
10
|
+
gem "hoe-debugging", "~>2.0", :group => [:development, :test]
|
11
11
|
gem "hoe-gemspec", "~>1.0", :group => [:development, :test]
|
12
12
|
gem "hoe-git", "~>1.6", :group => [:development, :test]
|
13
13
|
gem "minitest", "~>5.8.4", :group => [:development, :test]
|
@@ -17,7 +17,7 @@ gem "rake-compiler-dock", "~>0.6.2", :group => [:development, :test]
|
|
17
17
|
gem "racc", "~>1.4.14", :group => [:development, :test], :platform => [:ruby, :mingw, :x64_mingw]
|
18
18
|
gem "rexical", "~>1.0.5", :group => [:development, :test], :platform => [:ruby, :mingw, :x64_mingw]
|
19
19
|
gem "concourse", "~>0.15", :group => [:development, :test]
|
20
|
-
gem "rdoc", "
|
21
|
-
gem "hoe", "~>3.
|
20
|
+
gem "rdoc", ">=4.0", "<7", :group => [:development, :test]
|
21
|
+
gem "hoe", "~>3.17", :group => [:development, :test]
|
22
22
|
|
23
23
|
# vim: syntax=ruby
|
data/Manifest.txt
CHANGED
@@ -81,6 +81,8 @@ ext/java/nokogiri/internals/XalanDTMManagerPatch.java
|
|
81
81
|
ext/java/nokogiri/internals/XmlDeclHandler.java
|
82
82
|
ext/java/nokogiri/internals/XmlDomParserContext.java
|
83
83
|
ext/java/nokogiri/internals/XmlSaxParser.java
|
84
|
+
ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java
|
85
|
+
ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java
|
84
86
|
ext/java/nokogiri/internals/c14n/AttrCompare.java
|
85
87
|
ext/java/nokogiri/internals/c14n/C14nHelper.java
|
86
88
|
ext/java/nokogiri/internals/c14n/CanonicalFilter.java
|
@@ -108,7 +110,6 @@ ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java
|
|
108
110
|
ext/java/nokogiri/internals/c14n/NodeFilter.java
|
109
111
|
ext/java/nokogiri/internals/c14n/UtfHelpper.java
|
110
112
|
ext/java/nokogiri/internals/c14n/XMLUtils.java
|
111
|
-
ext/java/org/apache/xml/dtm/ref/dom2dtm/DOM2DTMExt.java
|
112
113
|
ext/nokogiri/depend
|
113
114
|
ext/nokogiri/extconf.rb
|
114
115
|
ext/nokogiri/html_document.c
|
data/README.md
CHANGED
@@ -18,7 +18,6 @@ or CSS3 selectors.
|
|
18
18
|
|
19
19
|
[![Concourse CI](https://ci.nokogiri.org/api/v1/teams/nokogiri-core/pipelines/nokogiri/jobs/ruby-2.4-system/badge)](https://ci.nokogiri.org/teams/nokogiri-core/pipelines/nokogiri?groups=master)
|
20
20
|
[![Code Climate](https://codeclimate.com/github/sparklemotion/nokogiri.svg)](https://codeclimate.com/github/sparklemotion/nokogiri)
|
21
|
-
[![Version Eye](https://www.versioneye.com/ruby/nokogiri/badge.png)](https://www.versioneye.com/ruby/nokogiri)
|
22
21
|
[![Join the chat at https://gitter.im/sparklemotion/nokogiri](https://badges.gitter.im/sparklemotion/nokogiri.svg)](https://gitter.im/sparklemotion/nokogiri?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
23
22
|
|
24
23
|
|
data/Rakefile
CHANGED
@@ -127,13 +127,13 @@ HOE = Hoe.spec 'nokogiri' do
|
|
127
127
|
|
128
128
|
unless java?
|
129
129
|
self.extra_deps += [
|
130
|
-
["mini_portile2", "~> 2.
|
130
|
+
["mini_portile2", "~> 2.4.0"], # keep version in sync with extconf.rb
|
131
131
|
]
|
132
132
|
end
|
133
133
|
|
134
134
|
self.extra_dev_deps += [
|
135
135
|
["hoe-bundler", "~> 1.2"],
|
136
|
-
["hoe-debugging", "~>
|
136
|
+
["hoe-debugging", "~> 2.0"],
|
137
137
|
["hoe-gemspec", "~> 1.0"],
|
138
138
|
["hoe-git", "~> 1.6"],
|
139
139
|
["minitest", "~> 5.8.4"],
|
@@ -266,11 +266,21 @@ task 'bundler:gemfile' do
|
|
266
266
|
end
|
267
267
|
|
268
268
|
file GENERATED_PARSER => "lib/nokogiri/css/parser.y" do |t|
|
269
|
-
|
269
|
+
if java?
|
270
|
+
warn "WARNING: #{GENERATED_PARSER} may be out of date:"
|
271
|
+
sh "ls -lt #{t.name} #{t.prerequisites.first}"
|
272
|
+
else
|
273
|
+
sh "racc -l -o #{t.name} #{t.prerequisites.first}"
|
274
|
+
end
|
270
275
|
end
|
271
276
|
|
272
277
|
file GENERATED_TOKENIZER => "lib/nokogiri/css/tokenizer.rex" do |t|
|
273
|
-
|
278
|
+
if java?
|
279
|
+
warn "WARNING: #{GENERATED_TOKENIZER} may be out of date:"
|
280
|
+
sh "ls -lt #{t.name} #{t.prerequisites.first}"
|
281
|
+
else
|
282
|
+
sh "rex --independent -o #{t.name} #{t.prerequisites.first}"
|
283
|
+
end
|
274
284
|
end
|
275
285
|
|
276
286
|
[:compile, :check_manifest].each do |task_name|
|
data/build_all
CHANGED
@@ -17,6 +17,10 @@ fi
|
|
17
17
|
|
18
18
|
set -o errexit
|
19
19
|
|
20
|
+
# check that we have the latest jruby
|
21
|
+
rvm use jruby
|
22
|
+
rvm use ruby
|
23
|
+
|
20
24
|
rm -rf tmp pkg
|
21
25
|
bundle exec rake clean clobber
|
22
26
|
|
@@ -37,7 +41,7 @@ cp -v pkg/nokogiri*.gem gems
|
|
37
41
|
bundle exec rake clean clobber
|
38
42
|
bundle exec rake generate
|
39
43
|
|
40
|
-
rvm jruby
|
44
|
+
rvm use jruby
|
41
45
|
gem install bundler --conservative
|
42
46
|
bundle install --quiet --local || bundle install
|
43
47
|
bundle exec ruby -S rake gem
|
data/ext/nokogiri/extconf.rb
CHANGED
@@ -400,9 +400,11 @@ if openbsd? && !using_system_libraries?
|
|
400
400
|
ENV['CFLAGS'] = "#{ENV['CFLAGS']} -I /usr/local/include"
|
401
401
|
end
|
402
402
|
|
403
|
-
|
403
|
+
if ENV['CC']
|
404
|
+
RbConfig::CONFIG['CC'] = RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC']
|
405
|
+
end
|
404
406
|
# use same c compiler for libxml and libxslt
|
405
|
-
ENV['CC'] = RbConfig::
|
407
|
+
ENV['CC'] = RbConfig::CONFIG['CC']
|
406
408
|
|
407
409
|
$LIBS << " #{ENV["LIBS"]}"
|
408
410
|
|
@@ -432,7 +434,7 @@ if RUBY_PLATFORM =~ /mingw/i
|
|
432
434
|
$CPPFLAGS << ' "-Idummypath"'
|
433
435
|
end
|
434
436
|
|
435
|
-
if RbConfig::
|
437
|
+
if RbConfig::CONFIG['CC'] =~ /gcc/
|
436
438
|
$CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
|
437
439
|
$CFLAGS << " -Wall -Wcast-qual -Wwrite-strings -Wmissing-noreturn -Winline"
|
438
440
|
end
|
@@ -460,7 +462,7 @@ else
|
|
460
462
|
# The gem version constraint in the Rakefile is not respected at install time.
|
461
463
|
# Keep this version in sync with the one in the Rakefile !
|
462
464
|
require 'rubygems'
|
463
|
-
gem 'mini_portile2', '~> 2.
|
465
|
+
gem 'mini_portile2', '~> 2.4.0'
|
464
466
|
require 'mini_portile2'
|
465
467
|
message "Using mini_portile version #{MiniPortile::VERSION}\n"
|
466
468
|
|
@@ -560,7 +562,8 @@ EOM
|
|
560
562
|
*(libiconv_recipe ? "--with-iconv=#{libiconv_recipe.path}" : iconv_configure_flags),
|
561
563
|
"--with-c14n",
|
562
564
|
"--with-debug",
|
563
|
-
"--with-threads"
|
565
|
+
"--with-threads",
|
566
|
+
*(darwin? ? ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"] : "")
|
564
567
|
]
|
565
568
|
end
|
566
569
|
|
@@ -573,7 +576,8 @@ EOM
|
|
573
576
|
"--without-python",
|
574
577
|
"--without-crypto",
|
575
578
|
"--with-debug",
|
576
|
-
"--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}"
|
579
|
+
"--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}",
|
580
|
+
*(darwin? ? ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"] : "")
|
577
581
|
]
|
578
582
|
end
|
579
583
|
|
data/ext/nokogiri/xml_attr.c
CHANGED
@@ -4,37 +4,40 @@
|
|
4
4
|
* call-seq:
|
5
5
|
* value=(content)
|
6
6
|
*
|
7
|
-
* Set the value for this Attr to +content
|
7
|
+
* Set the value for this Attr to +content+. Use `nil` to remove the value
|
8
|
+
* (e.g., a HTML boolean attribute).
|
8
9
|
*/
|
9
10
|
static VALUE set_value(VALUE self, VALUE content)
|
10
11
|
{
|
11
12
|
xmlAttrPtr attr;
|
12
|
-
|
13
|
+
xmlChar *value;
|
14
|
+
xmlNode *cur;
|
13
15
|
|
14
|
-
|
16
|
+
Data_Get_Struct(self, xmlAttr, attr);
|
15
17
|
|
18
|
+
if (attr->children) {
|
19
|
+
xmlFreeNodeList(attr->children);
|
20
|
+
}
|
16
21
|
attr->children = attr->last = NULL;
|
17
22
|
|
18
|
-
if (content) {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
/* Encode our content */
|
23
|
-
buffer = xmlEncodeEntitiesReentrant(attr->doc, (unsigned char *)StringValueCStr(content));
|
23
|
+
if (content == Qnil) {
|
24
|
+
return content;
|
25
|
+
}
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
value = xmlEncodeEntitiesReentrant(attr->doc, (unsigned char *)StringValueCStr(content));
|
28
|
+
if (xmlStrlen(value) == 0) {
|
29
|
+
attr->children = xmlNewDocText(attr->doc, value);
|
30
|
+
} else {
|
31
|
+
attr->children = xmlStringGetNodeList(attr->doc, value);
|
32
|
+
}
|
33
|
+
xmlFree(value);
|
28
34
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
for (cur = attr->children; cur; cur = cur->next) {
|
36
|
+
cur->parent = (xmlNode *)attr;
|
37
|
+
cur->doc = attr->doc;
|
38
|
+
if (cur->next == NULL) {
|
39
|
+
attr->last = cur;
|
34
40
|
}
|
35
|
-
|
36
|
-
/* Free up memory */
|
37
|
-
xmlFree(buffer);
|
38
41
|
}
|
39
42
|
|
40
43
|
return content;
|
@@ -74,7 +77,9 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
|
|
74
77
|
rb_node = Nokogiri_wrap_xml_node(klass, (xmlNodePtr)node);
|
75
78
|
rb_obj_call_init(rb_node, argc, argv);
|
76
79
|
|
77
|
-
if (rb_block_given_p()) {
|
80
|
+
if (rb_block_given_p()) {
|
81
|
+
rb_yield(rb_node);
|
82
|
+
}
|
78
83
|
|
79
84
|
return rb_node;
|
80
85
|
}
|
data/ext/nokogiri/xml_document.c
CHANGED
@@ -7,7 +7,10 @@ static int dealloc_node_i(xmlNodePtr key, xmlNodePtr node, xmlDocPtr doc)
|
|
7
7
|
xmlFreePropList((xmlAttrPtr)node);
|
8
8
|
break;
|
9
9
|
case XML_NAMESPACE_DECL:
|
10
|
-
|
10
|
+
xmlFreeNs((xmlNsPtr)node);
|
11
|
+
break;
|
12
|
+
case XML_DTD_NODE:
|
13
|
+
xmlFreeDtd((xmlDtdPtr)node);
|
11
14
|
break;
|
12
15
|
default:
|
13
16
|
if(node->parent == NULL) {
|
@@ -63,7 +63,7 @@ static int part_of_an_xpath_node_set_eh(xmlNsPtr node)
|
|
63
63
|
|
64
64
|
VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
|
65
65
|
{
|
66
|
-
VALUE ns, document, node_cache;
|
66
|
+
VALUE ns = 0, document, node_cache;
|
67
67
|
|
68
68
|
assert(doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE);
|
69
69
|
|
@@ -71,8 +71,6 @@ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
|
|
71
71
|
|
72
72
|
if (doc->type == XML_DOCUMENT_FRAG_NODE) doc = doc->doc;
|
73
73
|
|
74
|
-
ns = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, node);
|
75
|
-
|
76
74
|
if (DOC_RUBY_OBJECT_TEST(doc)) {
|
77
75
|
document = DOC_RUBY_OBJECT(doc);
|
78
76
|
|
@@ -91,6 +89,8 @@ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
|
|
91
89
|
}
|
92
90
|
|
93
91
|
rb_iv_set(ns, "@document", document);
|
92
|
+
} else {
|
93
|
+
ns = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, node);
|
94
94
|
}
|
95
95
|
|
96
96
|
node->_private = (void *)ns;
|
@@ -7,8 +7,7 @@ void init_xml_namespace();
|
|
7
7
|
|
8
8
|
extern VALUE cNokogiriXmlNamespace ;
|
9
9
|
|
10
|
-
VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
|
11
|
-
VALUE Nokogiri_wrap_xml_namespace2(VALUE document, xmlNsPtr node) ;
|
10
|
+
VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node);
|
12
11
|
|
13
12
|
#define NOKOGIRI_NAMESPACE_EH(node) ((node)->type == XML_NAMESPACE_DECL)
|
14
13
|
|
data/ext/nokogiri/xml_node.c
CHANGED
@@ -31,13 +31,13 @@ typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
|
|
31
31
|
static void relink_namespace(xmlNodePtr reparented)
|
32
32
|
{
|
33
33
|
xmlNodePtr child;
|
34
|
-
xmlNsPtr ns;
|
35
34
|
|
36
35
|
if (reparented->type != XML_ATTRIBUTE_NODE &&
|
37
36
|
reparented->type != XML_ELEMENT_NODE) { return; }
|
38
37
|
|
39
38
|
if (reparented->ns == NULL || reparented->ns->prefix == NULL) {
|
40
|
-
|
39
|
+
xmlNsPtr ns = NULL;
|
40
|
+
xmlChar *name = NULL, *prefix = NULL;
|
41
41
|
|
42
42
|
name = xmlSplitQName2(reparented->name, &prefix);
|
43
43
|
|
@@ -99,6 +99,25 @@ static void relink_namespace(xmlNodePtr reparented)
|
|
99
99
|
}
|
100
100
|
}
|
101
101
|
|
102
|
+
/*
|
103
|
+
* Search our parents for an existing definition of current namespace,
|
104
|
+
* because the definition it's pointing to may have just been removed nsDef.
|
105
|
+
*
|
106
|
+
* And although that would technically probably be OK, I'd feel better if we
|
107
|
+
* referred to a namespace that's still present in a node's nsDef somewhere
|
108
|
+
* in the doc.
|
109
|
+
*/
|
110
|
+
if (reparented->ns) {
|
111
|
+
xmlNsPtr ns = xmlSearchNs(reparented->doc, reparented, reparented->ns->prefix);
|
112
|
+
if (ns
|
113
|
+
&& ns != reparented->ns
|
114
|
+
&& xmlStrEqual(ns->prefix, reparented->ns->prefix)
|
115
|
+
&& xmlStrEqual(ns->href, reparented->ns->href)
|
116
|
+
) {
|
117
|
+
xmlSetNs(reparented, ns);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
102
121
|
/* Only walk all children if there actually is a namespace we need to */
|
103
122
|
/* reparent. */
|
104
123
|
if (NULL == reparented->ns) { return; }
|
@@ -282,7 +301,11 @@ ok:
|
|
282
301
|
}
|
283
302
|
|
284
303
|
if (original_ns_prefix_is_default && reparentee->ns != NULL && reparentee->ns->prefix != NULL) {
|
285
|
-
/*
|
304
|
+
/*
|
305
|
+
* issue #391, where new node's prefix may become the string "default"
|
306
|
+
* see libxml2 tree.c xmlNewReconciliedNs which implements this behavior.
|
307
|
+
*/
|
308
|
+
xmlFree(reparentee->ns->prefix);
|
286
309
|
reparentee->ns->prefix = NULL;
|
287
310
|
}
|
288
311
|
}
|
@@ -509,22 +532,39 @@ static VALUE internal_subset(VALUE self)
|
|
509
532
|
/*
|
510
533
|
* call-seq:
|
511
534
|
* dup
|
535
|
+
* dup(depth)
|
536
|
+
* dup(depth, new_parent_doc)
|
512
537
|
*
|
513
|
-
* Copy this node.
|
514
|
-
*
|
538
|
+
* Copy this node.
|
539
|
+
* An optional depth may be passed in. 0 is a shallow copy, 1 (the default) is a deep copy.
|
540
|
+
* An optional new_parent_doc may also be passed in, which will be the new
|
541
|
+
* node's parent document. Defaults to the current node's document.
|
542
|
+
* current document.
|
515
543
|
*/
|
516
544
|
static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
|
517
545
|
{
|
518
|
-
VALUE
|
546
|
+
VALUE r_level, r_new_parent_doc;
|
547
|
+
int level;
|
548
|
+
int n_args;
|
549
|
+
xmlDocPtr new_parent_doc;
|
519
550
|
xmlNodePtr node, dup;
|
520
551
|
|
521
|
-
|
522
|
-
|
552
|
+
Data_Get_Struct(self, xmlNode, node);
|
553
|
+
|
554
|
+
n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
|
555
|
+
|
556
|
+
if (n_args < 1) {
|
557
|
+
r_level = INT2NUM((long)1);
|
523
558
|
}
|
559
|
+
level = (int)NUM2INT(r_level);
|
524
560
|
|
525
|
-
|
561
|
+
if (n_args < 2) {
|
562
|
+
new_parent_doc = node->doc;
|
563
|
+
} else {
|
564
|
+
Data_Get_Struct(r_new_parent_doc, xmlDoc, new_parent_doc);
|
565
|
+
}
|
526
566
|
|
527
|
-
dup = xmlDocCopyNode(node,
|
567
|
+
dup = xmlDocCopyNode(node, new_parent_doc, level);
|
528
568
|
if(dup == NULL) { return Qnil; }
|
529
569
|
|
530
570
|
nokogiri_root_node(dup);
|
@@ -1308,11 +1348,11 @@ static VALUE line(VALUE self)
|
|
1308
1348
|
*/
|
1309
1349
|
static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
|
1310
1350
|
{
|
1311
|
-
xmlNodePtr node,
|
1351
|
+
xmlNodePtr node, namespace;
|
1312
1352
|
xmlNsPtr ns;
|
1313
1353
|
|
1314
1354
|
Data_Get_Struct(self, xmlNode, node);
|
1315
|
-
|
1355
|
+
namespace = node ;
|
1316
1356
|
|
1317
1357
|
ns = xmlSearchNs(
|
1318
1358
|
node->doc,
|
@@ -1322,10 +1362,10 @@ static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
|
|
1322
1362
|
|
1323
1363
|
if(!ns) {
|
1324
1364
|
if (node->type != XML_ELEMENT_NODE) {
|
1325
|
-
|
1365
|
+
namespace = node->parent;
|
1326
1366
|
}
|
1327
1367
|
ns = xmlNewNs(
|
1328
|
-
|
1368
|
+
namespace,
|
1329
1369
|
(const xmlChar *)StringValueCStr(href),
|
1330
1370
|
(const xmlChar *)(NIL_P(prefix) ? NULL : StringValueCStr(prefix))
|
1331
1371
|
);
|
@@ -1333,7 +1373,7 @@ static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
|
|
1333
1373
|
|
1334
1374
|
if (!ns) { return Qnil ; }
|
1335
1375
|
|
1336
|
-
if(NIL_P(prefix) || node !=
|
1376
|
+
if(NIL_P(prefix) || node != namespace) { xmlSetNs(node, ns); }
|
1337
1377
|
|
1338
1378
|
return Nokogiri_wrap_xml_namespace(node->doc, ns);
|
1339
1379
|
}
|
data/lib/nokogiri/version.rb
CHANGED
@@ -25,6 +25,17 @@ module Nokogiri
|
|
25
25
|
children.each { |child| child.parent = self }
|
26
26
|
end
|
27
27
|
|
28
|
+
if Nokogiri.uses_libxml?
|
29
|
+
def dup
|
30
|
+
new_document = document.dup
|
31
|
+
new_fragment = XML::DocumentFragment.new(new_document)
|
32
|
+
children.each do |child|
|
33
|
+
child.dup(1, new_document).parent = new_fragment
|
34
|
+
end
|
35
|
+
new_fragment
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
28
39
|
###
|
29
40
|
# return the name for DocumentFragment
|
30
41
|
def name
|
data/lib/nokogiri/xml/node.rb
CHANGED
@@ -161,6 +161,18 @@ module Nokogiri
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
+
|
165
|
+
###
|
166
|
+
# Add html around this node
|
167
|
+
#
|
168
|
+
# Returns self
|
169
|
+
def wrap(html)
|
170
|
+
new_parent = document.parse(html).first
|
171
|
+
add_next_sibling(new_parent)
|
172
|
+
new_parent.add_child(self)
|
173
|
+
self
|
174
|
+
end
|
175
|
+
|
164
176
|
###
|
165
177
|
# Add +node_or_tags+ as a child of this Node.
|
166
178
|
# +node_or_tags+ can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.
|
@@ -203,6 +203,7 @@ module Nokogiri
|
|
203
203
|
0.upto(length - 1) do |x|
|
204
204
|
yield self[x]
|
205
205
|
end
|
206
|
+
self
|
206
207
|
end
|
207
208
|
|
208
209
|
###
|
@@ -230,14 +231,9 @@ module Nokogiri
|
|
230
231
|
end
|
231
232
|
|
232
233
|
###
|
233
|
-
# Wrap this NodeSet with +html+
|
234
|
-
def wrap
|
235
|
-
|
236
|
-
new_parent = document.parse(html).first
|
237
|
-
j.add_next_sibling(new_parent)
|
238
|
-
new_parent.add_child(j)
|
239
|
-
end
|
240
|
-
self
|
234
|
+
# Wrap this NodeSet with +html+
|
235
|
+
def wrap html
|
236
|
+
map { |node| node.wrap html }
|
241
237
|
end
|
242
238
|
|
243
239
|
###
|
data/test/helper.rb
CHANGED
data/test/html/test_document.rb
CHANGED
@@ -707,6 +707,16 @@ eohtml
|
|
707
707
|
assert_equal 'ISO-8859-1', html.encoding.name
|
708
708
|
end
|
709
709
|
|
710
|
+
def test_leaking_dtd_nodes_after_internal_subset_removal
|
711
|
+
# see https://github.com/sparklemotion/nokogiri/issues/1784
|
712
|
+
#
|
713
|
+
# just checking that this doesn't raise a valgrind error. we
|
714
|
+
# don't otherwise have any test coverage for removing DTDs.
|
715
|
+
#
|
716
|
+
100.times do |i|
|
717
|
+
Nokogiri::HTML::Document.new.internal_subset.remove
|
718
|
+
end
|
719
|
+
end
|
710
720
|
end
|
711
721
|
end
|
712
722
|
end
|
data/test/test_memory_leak.rb
CHANGED
@@ -13,6 +13,22 @@ class TestMemoryLeak < Nokogiri::TestCase
|
|
13
13
|
EOF
|
14
14
|
end
|
15
15
|
|
16
|
+
#
|
17
|
+
# this suite is turned off unless the env var NOKOGIRI_GC is non-nil
|
18
|
+
#
|
19
|
+
# to run any of these tests, do something like this on the commandline:
|
20
|
+
#
|
21
|
+
# $ NOKOGIRI_GC=t ruby -Ilib:test \
|
22
|
+
# test/test_memory_leak.rb \
|
23
|
+
# -n /test_leaking_namespace_node_strings/
|
24
|
+
#
|
25
|
+
# also see:
|
26
|
+
#
|
27
|
+
# https://github.com/sparklemotion/nokogiri/issues/1603
|
28
|
+
#
|
29
|
+
# which is an open issue to resurrect these tests and run them as
|
30
|
+
# part of the CI pipeline.
|
31
|
+
#
|
16
32
|
if ENV['NOKOGIRI_GC'] # turning these off by default for now
|
17
33
|
def test_dont_hurt_em_why
|
18
34
|
content = File.open("#{File.dirname(__FILE__)}/files/dont_hurt_em_why.xml").read
|
@@ -126,7 +142,7 @@ EOF
|
|
126
142
|
end
|
127
143
|
|
128
144
|
def test_in_context_parser_leak
|
129
|
-
loop do
|
145
|
+
loop do
|
130
146
|
doc = Nokogiri::XML::Document.new
|
131
147
|
fragment1 = Nokogiri::XML::DocumentFragment.new(doc, '<foo/>')
|
132
148
|
node = fragment1.children[0]
|
@@ -144,8 +160,62 @@ EOF
|
|
144
160
|
doc.xpath('name(//node())')
|
145
161
|
end
|
146
162
|
end
|
163
|
+
|
164
|
+
def test_leaking_namespace_node_strings
|
165
|
+
# see https://github.com/sparklemotion/nokogiri/issues/1810 for memory leak report
|
166
|
+
ns = {'xmlns' => 'http://schemas.xmlsoap.org/soap/envelope/'}
|
167
|
+
20.times do
|
168
|
+
10_000.times do
|
169
|
+
Nokogiri::XML::Builder.new do |xml|
|
170
|
+
xml.send 'Envelope', ns do
|
171
|
+
xml.send 'Foobar', ns
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
puts MemInfo.rss
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_leaking_namespace_node_strings_with_prefix
|
180
|
+
# see https://github.com/sparklemotion/nokogiri/issues/1810 for memory leak report
|
181
|
+
ns = {'xmlns:foo' => 'http://schemas.xmlsoap.org/soap/envelope/'}
|
182
|
+
20.times do
|
183
|
+
10_000.times do
|
184
|
+
Nokogiri::XML::Builder.new do |xml|
|
185
|
+
xml.send 'Envelope', ns do
|
186
|
+
xml.send 'Foobar', ns
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
puts MemInfo.rss
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_leaking_dtd_nodes_after_internal_subset_removal
|
195
|
+
# see https://github.com/sparklemotion/nokogiri/issues/1784
|
196
|
+
100_000.times do |i|
|
197
|
+
doc = Nokogiri::HTML::Document.new
|
198
|
+
doc.internal_subset.remove
|
199
|
+
puts MemInfo.rss if (i % 1000 == 0)
|
200
|
+
end
|
201
|
+
end
|
147
202
|
end # if NOKOGIRI_GC
|
148
203
|
|
204
|
+
module MemInfo
|
205
|
+
# from https://stackoverflow.com/questions/7220896/get-current-ruby-process-memory-usage
|
206
|
+
# this is only going to work on linux
|
207
|
+
PAGE_SIZE = `getconf PAGESIZE`.chomp.to_i rescue 4096
|
208
|
+
STATM_PATH = "/proc/#{Process.pid}/statm"
|
209
|
+
STATM_FOUND = File.exist?(STATM_PATH)
|
210
|
+
|
211
|
+
def self.rss
|
212
|
+
if STATM_FOUND
|
213
|
+
return (File.read(STATM_PATH).split(' ')[1].to_i * PAGE_SIZE) / 1024
|
214
|
+
end
|
215
|
+
return 0
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
149
219
|
private
|
150
220
|
|
151
221
|
def count_object_space_documents
|
data/test/xml/test_attr.rb
CHANGED
@@ -26,12 +26,34 @@ module Nokogiri
|
|
26
26
|
assert_equal "Y&ent1;", street.value
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def test_set_value
|
30
30
|
xml = Nokogiri::XML.parse(File.read(XML_FILE), XML_FILE)
|
31
31
|
address = xml.xpath('//address')[3]
|
32
32
|
street = address.attributes['street']
|
33
33
|
street.value = "Y&ent1;"
|
34
34
|
assert_equal "Y&ent1;", street.value
|
35
|
+
assert_includes %Q{ street="Y&ent1;"}, street.to_xml
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_set_value_with_entity_string_in_html_file
|
39
|
+
html = Nokogiri::HTML("<html><body><div foo='asdf'>")
|
40
|
+
foo = html.at_css("div").attributes["foo"]
|
41
|
+
foo.value = "Y&ent1;"
|
42
|
+
assert_includes %Q{ foo="Y&ent1;"}, foo.to_html
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_set_value_with_blank_string_in_html_file
|
46
|
+
html = Nokogiri::HTML("<html><body><div foo='asdf'>")
|
47
|
+
foo = html.at_css("div").attributes["foo"]
|
48
|
+
foo.value = ""
|
49
|
+
assert_includes %Q{ foo=""}, foo.to_html
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_set_value_of_boolean_attr_with_nil_in_html_file
|
53
|
+
html = Nokogiri::HTML("<html><body><div disabled='asdf'>")
|
54
|
+
disabled = html.at_css("div").attributes["disabled"]
|
55
|
+
disabled.value = nil
|
56
|
+
assert_includes %Q{ disabled}, disabled.to_html
|
35
57
|
end
|
36
58
|
|
37
59
|
def test_unlink # aliased as :remove
|
data/test/xml/test_builder.rb
CHANGED
@@ -331,6 +331,18 @@ module Nokogiri
|
|
331
331
|
assert_nil doc.at_xpath("//*[local-name() = 'products']").namespace
|
332
332
|
end
|
333
333
|
|
334
|
+
def test_builder_reuses_namespaces
|
335
|
+
# see https://github.com/sparklemotion/nokogiri/issues/1810 for memory leak report
|
336
|
+
builder = Nokogiri::XML::Builder.new
|
337
|
+
builder.send "envelope", {'xmlns' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
|
338
|
+
builder.send "package", {'xmlns' => 'http://schemas.xmlsoap.org/soap/envelope/'}
|
339
|
+
end
|
340
|
+
envelope = builder.doc.at_css("envelope")
|
341
|
+
package = builder.doc.at_css("package")
|
342
|
+
assert_equal envelope.namespace, package.namespace
|
343
|
+
assert_equal envelope.namespace.object_id, package.namespace.object_id
|
344
|
+
end
|
345
|
+
|
334
346
|
private
|
335
347
|
|
336
348
|
def namespaces_defined_on(node)
|
@@ -263,6 +263,20 @@ EOS
|
|
263
263
|
Nokogiri::XML::DocumentFragment.parse(input) # assert_nothing_raised
|
264
264
|
end
|
265
265
|
|
266
|
+
def test_dup_creates_tree_with_identical_structure
|
267
|
+
original = Nokogiri::XML::DocumentFragment.parse("<div><p>hello</p></div>")
|
268
|
+
duplicate = original.dup
|
269
|
+
assert_equal original.to_html, duplicate.to_html
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_dup_creates_mutable_tree
|
273
|
+
original = Nokogiri::XML::DocumentFragment.parse("<div><p>hello</p></div>")
|
274
|
+
duplicate = original.dup
|
275
|
+
duplicate.at_css("div").add_child("<b>hello there</b>")
|
276
|
+
assert_nil original.at_css("b")
|
277
|
+
assert_not_nil duplicate.at_css("b")
|
278
|
+
end
|
279
|
+
|
266
280
|
if Nokogiri.uses_libxml?
|
267
281
|
def test_for_libxml_in_context_fragment_parsing_bug_workaround
|
268
282
|
10.times do
|
data/test/xml/test_node.rb
CHANGED
@@ -165,6 +165,44 @@ module Nokogiri
|
|
165
165
|
assert_equal x.first.name, "span"
|
166
166
|
end
|
167
167
|
|
168
|
+
def test_dup_is_deep_copy_by_default
|
169
|
+
doc = XML::Document.parse "<root><div><p>hello</p></div></root>"
|
170
|
+
div = doc.at_css "div"
|
171
|
+
node = div.dup
|
172
|
+
assert_equal 1, node.children.length
|
173
|
+
assert_equal "<p>hello</p>", node.children.first.to_html
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_dup_deep_copy
|
177
|
+
doc = XML::Document.parse "<root><div><p>hello</p></div></root>"
|
178
|
+
div = doc.at_css "div"
|
179
|
+
node = div.dup(1)
|
180
|
+
assert_equal 1, node.children.length
|
181
|
+
assert_equal "<p>hello</p>", node.children.first.to_html
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_dup_shallow_copy
|
185
|
+
doc = XML::Document.parse "<root><div><p>hello</p></div></root>"
|
186
|
+
div = doc.at_css "div"
|
187
|
+
node = div.dup(0)
|
188
|
+
assert_equal 0, node.children.length
|
189
|
+
end
|
190
|
+
|
191
|
+
if Nokogiri.uses_libxml?
|
192
|
+
def test_dup_to_another_document
|
193
|
+
doc1 = HTML::Document.parse "<root><div><p>hello</p></div></root>"
|
194
|
+
doc2 = HTML::Document.parse "<div></div>"
|
195
|
+
|
196
|
+
div = doc1.at_css "div"
|
197
|
+
duplicate_div = div.dup(1, doc2)
|
198
|
+
|
199
|
+
assert_not_nil doc1.at_css("div")
|
200
|
+
assert_equal doc2, duplicate_div.document
|
201
|
+
assert_equal 1, duplicate_div.children.length
|
202
|
+
assert_equal "<p>hello</p>", duplicate_div.children.first.to_html
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
168
206
|
def test_subclass_dup
|
169
207
|
subclass = Class.new(Nokogiri::XML::Node)
|
170
208
|
node = subclass.new('foo', @xml).dup
|
@@ -415,12 +453,19 @@ module Nokogiri
|
|
415
453
|
assert_equal ns, ns2
|
416
454
|
end
|
417
455
|
|
418
|
-
def
|
456
|
+
def test_add_default_namespace
|
419
457
|
node = @xml.at('address')
|
420
458
|
node.add_namespace(nil, 'http://tenderlovemaking.com')
|
421
459
|
assert_equal 'http://tenderlovemaking.com', node.namespaces['xmlns']
|
422
460
|
end
|
423
461
|
|
462
|
+
def test_add_default_namespace_twice
|
463
|
+
node = @xml.at('address')
|
464
|
+
ns = node.add_namespace(nil, 'http://tenderlovemaking.com')
|
465
|
+
ns2 = node.add_namespace(nil, 'http://tenderlovemaking.com')
|
466
|
+
assert_equal ns.object_id, ns2.object_id
|
467
|
+
end
|
468
|
+
|
424
469
|
def test_add_multiple_namespaces
|
425
470
|
node = @xml.at('address')
|
426
471
|
|
@@ -1320,6 +1365,15 @@ eoxml
|
|
1320
1365
|
node.add_next_sibling(Nokogiri::XML::Text.new('after', node.document))
|
1321
1366
|
end
|
1322
1367
|
end
|
1368
|
+
|
1369
|
+
def test_wrap
|
1370
|
+
xml = '<root><thing><div class="title">important thing</div></thing></root>'
|
1371
|
+
doc = Nokogiri::XML(xml)
|
1372
|
+
thing = doc.at_css("thing")
|
1373
|
+
thing.wrap("<wrapper/>")
|
1374
|
+
assert_equal 'wrapper', thing.parent.name
|
1375
|
+
assert_equal 'thing', doc.at_css("wrapper").children.first.name
|
1376
|
+
end
|
1323
1377
|
end
|
1324
1378
|
end
|
1325
1379
|
end
|
@@ -204,7 +204,7 @@ module Nokogiri
|
|
204
204
|
node = doc1.at_xpath("//value")
|
205
205
|
node.remove
|
206
206
|
doc2.add_child(node)
|
207
|
-
assert_match
|
207
|
+
assert_match(/<value>3<\/value>/, doc2.to_xml)
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
@@ -224,6 +224,59 @@ module Nokogiri
|
|
224
224
|
node.add_child(child)
|
225
225
|
assert @doc.at('//xmlns:second')
|
226
226
|
end
|
227
|
+
|
228
|
+
describe "and a child node was added to a new doc with the a different namespace using the same prefix" do
|
229
|
+
before do
|
230
|
+
@doc = Nokogiri::XML %Q{<root xmlns:bar="http://tenderlovemaking.com/"><bar:first/></root>}
|
231
|
+
new_doc = Nokogiri::XML %Q{<newroot xmlns:bar="http://flavorjon.es/"/>}
|
232
|
+
assert node = @doc.at("//tenderlove:first", tenderlove: "http://tenderlovemaking.com/")
|
233
|
+
new_doc.root.add_child node
|
234
|
+
@doc = new_doc
|
235
|
+
end
|
236
|
+
|
237
|
+
it "serializes the doc with the proper default namespace" do
|
238
|
+
assert_match(/<bar:first\ xmlns:bar="http:\/\/tenderlovemaking.com\/"\/>/, @doc.to_xml)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "and a child node was added to a new doc with the same default namespaces" do
|
243
|
+
before do
|
244
|
+
new_doc = Nokogiri::XML %Q{<newroot xmlns="http://tenderlovemaking.com/"/>}
|
245
|
+
assert node = @doc.at("//tenderlove:first", tenderlove: "http://tenderlovemaking.com/")
|
246
|
+
new_doc.root.add_child node
|
247
|
+
@doc = new_doc
|
248
|
+
end
|
249
|
+
|
250
|
+
it "serializes the doc with the proper default namespace" do
|
251
|
+
assert_match(/<first>/, @doc.to_xml)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "and a child node was added to a new doc without any default namespaces" do
|
256
|
+
before do
|
257
|
+
new_doc = Nokogiri::XML "<newroot/>"
|
258
|
+
assert node = @doc.at("//tenderlove:first", tenderlove: "http://tenderlovemaking.com/")
|
259
|
+
new_doc.root.add_child node
|
260
|
+
@doc = new_doc
|
261
|
+
end
|
262
|
+
|
263
|
+
it "serializes the doc with the proper default namespace" do
|
264
|
+
assert_match(/<first xmlns=\"http:\/\/tenderlovemaking.com\/\">/, @doc.to_xml)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "and a child node became the root of a new doc" do
|
269
|
+
before do
|
270
|
+
new_doc = Nokogiri::XML::Document.new
|
271
|
+
assert node = @doc.at("//tenderlove:first", tenderlove: "http://tenderlovemaking.com/")
|
272
|
+
new_doc.root = node
|
273
|
+
@doc = new_doc
|
274
|
+
end
|
275
|
+
|
276
|
+
it "serializes the doc with the proper default namespace" do
|
277
|
+
assert_match(/<first xmlns=\"http:\/\/tenderlovemaking.com\/\">/, @doc.to_xml)
|
278
|
+
end
|
279
|
+
end
|
227
280
|
end
|
228
281
|
|
229
282
|
describe "given a parent node with a default and non-default namespace" do
|
@@ -249,7 +302,7 @@ module Nokogiri
|
|
249
302
|
@node.add_child(@child)
|
250
303
|
assert reparented = @doc.at('//bar:second', "bar" => "http://tenderlovemaking.com/")
|
251
304
|
assert reparented.namespace_definitions.empty?
|
252
|
-
assert_equal @
|
305
|
+
assert_equal @doc.root.namespace, reparented.namespace
|
253
306
|
assert_equal(
|
254
307
|
{
|
255
308
|
"xmlns" => "http://tenderlovemaking.com/",
|
@@ -282,17 +335,20 @@ module Nokogiri
|
|
282
335
|
end
|
283
336
|
|
284
337
|
describe "and a child with a namespace matching the parent's non-default namespace" do
|
338
|
+
before do
|
339
|
+
@root_ns = @doc.root.namespace_definitions.detect { |x| x.prefix == "foo" }
|
340
|
+
end
|
341
|
+
|
285
342
|
describe "set by #namespace=" do
|
286
343
|
before do
|
287
|
-
@
|
288
|
-
@child.namespace = @ns
|
344
|
+
@child.namespace = @root_ns
|
289
345
|
end
|
290
346
|
|
291
347
|
it "inserts a node that inherits the matching parent namespace" do
|
292
348
|
@node.add_child(@child)
|
293
349
|
assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
|
294
350
|
assert reparented.namespace_definitions.empty?
|
295
|
-
assert_equal @
|
351
|
+
assert_equal @root_ns, reparented.namespace
|
296
352
|
assert_equal(
|
297
353
|
{
|
298
354
|
"xmlns" => "http://tenderlovemaking.com/",
|
@@ -312,7 +368,7 @@ module Nokogiri
|
|
312
368
|
@node.add_child(@child)
|
313
369
|
assert reparented = @doc.at('//bar:second', "bar" => "http://flavorjon.es/")
|
314
370
|
assert reparented.namespace_definitions.empty?
|
315
|
-
assert_equal @
|
371
|
+
assert_equal @root_ns, reparented.namespace
|
316
372
|
assert_equal(
|
317
373
|
{
|
318
374
|
"xmlns" => "http://tenderlovemaking.com/",
|
@@ -550,6 +606,19 @@ module Nokogiri
|
|
550
606
|
end
|
551
607
|
end
|
552
608
|
|
609
|
+
describe "reparenting and preserving a reference to the original ns" do
|
610
|
+
it "should not cause illegal memory access" do
|
611
|
+
# this test will only cause a failure in valgrind. it
|
612
|
+
# drives out the reason why we can't call xmlFreeNs in
|
613
|
+
# relink_namespace and instead have to root the nsdef.
|
614
|
+
doc = Nokogiri::XML '<root xmlns="http://flavorjon.es/"><envelope /></root>'
|
615
|
+
elem = doc.create_element "package", {"xmlns" => "http://flavorjon.es/"}
|
616
|
+
ns = elem.namespace_definitions
|
617
|
+
doc.at_css("envelope").add_child elem
|
618
|
+
ns.inspect
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
553
622
|
describe "reparenting into another document" do
|
554
623
|
it "correctly sets default namespace of a reparented node" do
|
555
624
|
# issue described in #391
|
data/test/xml/test_node_set.rb
CHANGED
@@ -511,6 +511,19 @@ module Nokogiri
|
|
511
511
|
assert_equal 'employee', @xml.search("//wrapper").first.children[0].name
|
512
512
|
end
|
513
513
|
|
514
|
+
def test_wrap_various_node_types
|
515
|
+
xml = '<root><foo>contents</foo></root>'
|
516
|
+
doc = Nokogiri::XML xml
|
517
|
+
nodes = doc.at_css("root").xpath(".//* | .//*/text()") # foo and "contents"
|
518
|
+
nodes.wrap("<wrapper/>")
|
519
|
+
wrappers = doc.css("wrapper")
|
520
|
+
assert_equal "root", wrappers.first.parent.name
|
521
|
+
assert_equal "foo", wrappers.first.children.first.name
|
522
|
+
assert_equal "foo", wrappers.last.parent.name
|
523
|
+
assert wrappers.last.children.first.text?
|
524
|
+
assert_equal "contents", wrappers.last.children.first.text
|
525
|
+
end
|
526
|
+
|
514
527
|
def test_wrap_a_fragment
|
515
528
|
frag = Nokogiri::XML::DocumentFragment.parse <<-EOXML
|
516
529
|
<employees>
|
@@ -804,6 +817,12 @@ module Nokogiri
|
|
804
817
|
assert_equal node_set.document, new_set.document
|
805
818
|
assert new_set.respond_to?(:awesome!)
|
806
819
|
end
|
820
|
+
|
821
|
+
def test_each_should_return_self
|
822
|
+
node_set1 = @xml.css("address")
|
823
|
+
node_set2 = node_set1.each {}
|
824
|
+
assert_equal node_set1, node_set2
|
825
|
+
end
|
807
826
|
end
|
808
827
|
end
|
809
828
|
end
|
data/test/xml/test_text.rb
CHANGED
@@ -55,6 +55,15 @@ module Nokogiri
|
|
55
55
|
node << Text.new('bar', Document.new)
|
56
56
|
}
|
57
57
|
end
|
58
|
+
|
59
|
+
def test_wrap
|
60
|
+
xml = '<root><thing><div class="title">important thing</div></thing></root>'
|
61
|
+
doc = Nokogiri::XML(xml)
|
62
|
+
text = doc.at_css("div").children.first
|
63
|
+
text.wrap("<wrapper/>")
|
64
|
+
assert_equal 'wrapper', text.parent.name
|
65
|
+
assert_equal 'wrapper', doc.at_css("div").children.first.name
|
66
|
+
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nokogiri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2018-10
|
17
|
+
date: 2018-12-10 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: mini_portile2
|
@@ -22,14 +22,14 @@ dependencies:
|
|
22
22
|
requirements:
|
23
23
|
- - "~>"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 2.
|
25
|
+
version: 2.4.0
|
26
26
|
type: :runtime
|
27
27
|
prerelease: false
|
28
28
|
version_requirements: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 2.
|
32
|
+
version: 2.4.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: hoe-bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '2.0'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
60
|
+
version: '2.0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: hoe-gemspec
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,30 +188,36 @@ dependencies:
|
|
188
188
|
name: rdoc
|
189
189
|
requirement: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
|
-
- - "
|
191
|
+
- - ">="
|
192
192
|
- !ruby/object:Gem::Version
|
193
193
|
version: '4.0'
|
194
|
+
- - "<"
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '7'
|
194
197
|
type: :development
|
195
198
|
prerelease: false
|
196
199
|
version_requirements: !ruby/object:Gem::Requirement
|
197
200
|
requirements:
|
198
|
-
- - "
|
201
|
+
- - ">="
|
199
202
|
- !ruby/object:Gem::Version
|
200
203
|
version: '4.0'
|
204
|
+
- - "<"
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '7'
|
201
207
|
- !ruby/object:Gem::Dependency
|
202
208
|
name: hoe
|
203
209
|
requirement: !ruby/object:Gem::Requirement
|
204
210
|
requirements:
|
205
211
|
- - "~>"
|
206
212
|
- !ruby/object:Gem::Version
|
207
|
-
version: '3.
|
213
|
+
version: '3.17'
|
208
214
|
type: :development
|
209
215
|
prerelease: false
|
210
216
|
version_requirements: !ruby/object:Gem::Requirement
|
211
217
|
requirements:
|
212
218
|
- - "~>"
|
213
219
|
- !ruby/object:Gem::Version
|
214
|
-
version: '3.
|
220
|
+
version: '3.17'
|
215
221
|
description: |-
|
216
222
|
Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among
|
217
223
|
Nokogiri's many features is the ability to search documents via XPath
|
@@ -569,12 +575,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
569
575
|
version: 2.1.0
|
570
576
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
571
577
|
requirements:
|
572
|
-
- - "
|
578
|
+
- - ">"
|
573
579
|
- !ruby/object:Gem::Version
|
574
|
-
version:
|
580
|
+
version: 1.3.1
|
575
581
|
requirements: []
|
576
582
|
rubyforge_project:
|
577
|
-
rubygems_version: 2.7.
|
583
|
+
rubygems_version: 2.7.8
|
578
584
|
signing_key:
|
579
585
|
specification_version: 4
|
580
586
|
summary: Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser
|