nokogiri 1.12.5 → 1.13.6
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/Gemfile +2 -0
- data/README.md +9 -7
- data/bin/nokogiri +63 -50
- data/dependencies.yml +13 -64
- data/ext/nokogiri/extconf.rb +64 -44
- data/ext/nokogiri/html4_sax_parser_context.c +2 -3
- data/ext/nokogiri/xml_document.c +35 -35
- data/ext/nokogiri/xml_document_fragment.c +0 -2
- data/ext/nokogiri/xml_dtd.c +2 -2
- data/ext/nokogiri/xml_encoding_handler.c +25 -11
- data/ext/nokogiri/xml_node.c +638 -333
- data/ext/nokogiri/xml_reader.c +37 -11
- data/ext/nokogiri/xml_sax_parser_context.c +10 -3
- data/ext/nokogiri/xml_xpath_context.c +72 -49
- data/ext/nokogiri/xslt_stylesheet.c +107 -9
- data/gumbo-parser/src/parser.c +0 -11
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +9 -8
- data/lib/nokogiri/css/parser.rb +360 -341
- data/lib/nokogiri/css/parser.y +249 -244
- data/lib/nokogiri/css/parser_extras.rb +22 -20
- data/lib/nokogiri/css/syntax_error.rb +1 -0
- data/lib/nokogiri/css/tokenizer.rb +4 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +179 -82
- data/lib/nokogiri/css.rb +38 -6
- data/lib/nokogiri/decorators/slop.rb +8 -7
- data/lib/nokogiri/extension.rb +1 -1
- data/lib/nokogiri/gumbo.rb +1 -0
- data/lib/nokogiri/html.rb +16 -10
- data/lib/nokogiri/html4/builder.rb +1 -0
- data/lib/nokogiri/html4/document.rb +88 -77
- data/lib/nokogiri/html4/document_fragment.rb +11 -7
- data/lib/nokogiri/html4/element_description.rb +1 -0
- data/lib/nokogiri/html4/element_description_defaults.rb +426 -520
- data/lib/nokogiri/html4/entity_lookup.rb +2 -1
- data/lib/nokogiri/html4/sax/parser.rb +5 -2
- data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
- data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
- data/lib/nokogiri/html4.rb +11 -5
- data/lib/nokogiri/html5/document.rb +27 -10
- data/lib/nokogiri/html5/document_fragment.rb +5 -2
- data/lib/nokogiri/html5/node.rb +10 -3
- data/lib/nokogiri/html5.rb +69 -64
- data/lib/nokogiri/jruby/dependencies.rb +10 -9
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version/constant.rb +2 -1
- data/lib/nokogiri/version/info.rb +20 -13
- data/lib/nokogiri/version.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +5 -3
- data/lib/nokogiri/xml/attribute_decl.rb +2 -1
- data/lib/nokogiri/xml/builder.rb +34 -32
- data/lib/nokogiri/xml/cdata.rb +2 -1
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +144 -103
- data/lib/nokogiri/xml/document_fragment.rb +41 -38
- data/lib/nokogiri/xml/dtd.rb +3 -2
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +2 -1
- data/lib/nokogiri/xml/entity_decl.rb +3 -2
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +2 -0
- data/lib/nokogiri/xml/node/save_options.rb +8 -4
- data/lib/nokogiri/xml/node.rb +521 -351
- data/lib/nokogiri/xml/node_set.rb +50 -54
- data/lib/nokogiri/xml/notation.rb +12 -0
- data/lib/nokogiri/xml/parse_options.rb +12 -7
- data/lib/nokogiri/xml/pp/character_data.rb +8 -6
- data/lib/nokogiri/xml/pp/node.rb +24 -26
- data/lib/nokogiri/xml/pp.rb +1 -0
- data/lib/nokogiri/xml/processing_instruction.rb +2 -1
- data/lib/nokogiri/xml/reader.rb +17 -19
- data/lib/nokogiri/xml/relax_ng.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +20 -19
- data/lib/nokogiri/xml/sax/parser.rb +37 -34
- data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
- data/lib/nokogiri/xml/sax.rb +1 -0
- data/lib/nokogiri/xml/schema.rb +7 -6
- data/lib/nokogiri/xml/searchable.rb +93 -62
- data/lib/nokogiri/xml/syntax_error.rb +5 -4
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
- data/lib/nokogiri/xml/xpath.rb +12 -0
- data/lib/nokogiri/xml/xpath_context.rb +2 -3
- data/lib/nokogiri/xml.rb +4 -3
- data/lib/nokogiri/xslt/stylesheet.rb +1 -0
- data/lib/nokogiri/xslt.rb +21 -13
- data/lib/nokogiri.rb +19 -16
- data/lib/xsd/xmlparser/nokogiri.rb +25 -24
- data/patches/libxml2/0004-use-glibc-strlen.patch +3 -3
- data/patches/libxml2/0006-update-automake-files-for-arm64.patch +2443 -1914
- data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +61 -0
- data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
- data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
- data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
- metadata +109 -31
- data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +0 -31
- data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
- data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
@@ -1,18 +1,16 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
4
|
+
require "pathname"
|
5
5
|
|
6
6
|
module Nokogiri
|
7
7
|
module XML
|
8
|
-
|
9
|
-
# Nokogiri::XML::Document
|
10
|
-
#
|
11
|
-
# See Nokogiri::XML::Document.parse() for more information on parsing.
|
8
|
+
# Nokogiri::XML::Document is the main entry point for dealing with XML documents. The Document
|
9
|
+
# is created by parsing an XML document. See Nokogiri::XML::Document.parse for more information
|
10
|
+
# on parsing.
|
12
11
|
#
|
13
12
|
# For searching a Document, see Nokogiri::XML::Searchable#css and
|
14
13
|
# Nokogiri::XML::Searchable#xpath
|
15
|
-
#
|
16
14
|
class Document < Nokogiri::XML::Node
|
17
15
|
# See http://www.w3.org/TR/REC-xml-names/#ns-decl for more details. Note that we're not
|
18
16
|
# attempting to handle unicode characters partly because libxml2 doesn't handle unicode
|
@@ -47,76 +45,86 @@ module Nokogiri
|
|
47
45
|
#
|
48
46
|
# Nokogiri.XML() is a convenience method which will call this method.
|
49
47
|
#
|
50
|
-
def self.parse
|
48
|
+
def self.parse(string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML)
|
51
49
|
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
52
|
-
|
53
50
|
yield options if block_given?
|
54
51
|
|
55
52
|
url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
|
56
53
|
|
57
54
|
if empty_doc?(string_or_io)
|
58
55
|
if options.strict?
|
59
|
-
raise Nokogiri::XML::SyntaxError
|
56
|
+
raise Nokogiri::XML::SyntaxError, "Empty document"
|
60
57
|
else
|
61
58
|
return encoding ? new.tap { |i| i.encoding = encoding } : new
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
65
62
|
doc = if string_or_io.respond_to?(:read)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
if string_or_io.is_a?(Pathname)
|
64
|
+
# resolve the Pathname to the file and open it as an IO object, see #2110
|
65
|
+
string_or_io = string_or_io.expand_path.open
|
66
|
+
url ||= string_or_io.path
|
67
|
+
end
|
71
68
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
read_io(string_or_io, url, encoding, options.to_i)
|
70
|
+
else
|
71
|
+
# read_memory pukes on empty docs
|
72
|
+
read_memory(string_or_io, url, encoding, options.to_i)
|
73
|
+
end
|
77
74
|
|
78
75
|
# do xinclude processing
|
79
76
|
doc.do_xinclude(options) if options.xinclude?
|
80
77
|
|
81
|
-
|
78
|
+
doc
|
82
79
|
end
|
83
80
|
|
84
81
|
##
|
85
|
-
#
|
86
|
-
#
|
82
|
+
# :singleton-method: wrap
|
83
|
+
# :call-seq: wrap(java_document) → Nokogiri::XML::Document
|
84
|
+
#
|
85
|
+
# ⚠ This method is only available when running JRuby.
|
87
86
|
#
|
88
|
-
# Create a
|
87
|
+
# Create a Document using an existing Java DOM document object.
|
89
88
|
#
|
90
|
-
# The returned
|
89
|
+
# The returned Document shares the same underlying data structure as the Java object, so
|
91
90
|
# changes in one are reflected in the other.
|
92
91
|
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
92
|
+
# [Parameters]
|
93
|
+
# - `java_document` (Java::OrgW3cDom::Document)
|
94
|
+
# (The class `Java::OrgW3cDom::Document` is also accessible as `org.w3c.dom.Document`.)
|
95
|
+
#
|
96
|
+
# [Returns] Nokogiri::XML::Document
|
97
|
+
#
|
98
|
+
# See also \#to_java
|
98
99
|
|
99
|
-
|
100
|
-
#
|
100
|
+
# :method: to_java
|
101
|
+
# :call-seq: to_java() → Java::OrgW3cDom::Document
|
102
|
+
#
|
103
|
+
# ⚠ This method is only available when running JRuby.
|
101
104
|
#
|
102
|
-
# Returns the underlying Java DOM document object for
|
105
|
+
# Returns the underlying Java DOM document object for this document.
|
103
106
|
#
|
104
|
-
# The returned Java object shares the same underlying data structure as
|
107
|
+
# The returned Java object shares the same underlying data structure as this document, so
|
105
108
|
# changes in one are reflected in the other.
|
106
109
|
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
|
110
|
+
# [Returns]
|
111
|
+
# Java::OrgW3cDom::Document
|
112
|
+
# (The class `Java::OrgW3cDom::Document` is also accessible as `org.w3c.dom.Document`.)
|
113
|
+
#
|
114
|
+
# See also Document.wrap
|
112
115
|
|
113
|
-
#
|
116
|
+
# The errors found while parsing a document.
|
117
|
+
#
|
118
|
+
# [Returns] Array<Nokogiri::XML::SyntaxError>
|
114
119
|
attr_accessor :errors
|
115
120
|
|
116
|
-
# When true
|
117
|
-
# namespace (if one exists). Defaults to
|
121
|
+
# When `true`, reparented elements without a namespace will inherit their new parent's
|
122
|
+
# namespace (if one exists). Defaults to `false`.
|
123
|
+
#
|
124
|
+
# [Returns] Boolean
|
125
|
+
#
|
126
|
+
# *Example:* Default behavior of namespace inheritance
|
118
127
|
#
|
119
|
-
# @example Default behavior of namespace inheritance
|
120
128
|
# xml = <<~EOF
|
121
129
|
# <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
|
122
130
|
# <foo:parent>
|
@@ -134,7 +142,8 @@ module Nokogiri
|
|
134
142
|
# # </foo:parent>
|
135
143
|
# # </root>
|
136
144
|
#
|
137
|
-
#
|
145
|
+
# *Example:* Setting namespace inheritance to `true`
|
146
|
+
#
|
138
147
|
# xml = <<~EOF
|
139
148
|
# <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
|
140
149
|
# <foo:parent>
|
@@ -153,49 +162,61 @@ module Nokogiri
|
|
153
162
|
# # </foo:parent>
|
154
163
|
# # </root>
|
155
164
|
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
# @since v1.12.4
|
165
|
+
# Since v1.12.4
|
159
166
|
attr_accessor :namespace_inheritance
|
160
167
|
|
161
|
-
def initialize
|
168
|
+
def initialize(*args) # :nodoc:
|
162
169
|
@errors = []
|
163
170
|
@decorators = nil
|
164
171
|
@namespace_inheritance = false
|
165
172
|
end
|
166
173
|
|
167
|
-
|
168
|
-
#
|
169
|
-
#
|
174
|
+
# :call-seq:
|
175
|
+
# create_element(name, *contents_or_attrs, &block) → Nokogiri::XML::Element
|
176
|
+
#
|
177
|
+
# Create a new Element with `name` belonging to this document, optionally setting contents or
|
178
|
+
# attributes.
|
179
|
+
#
|
180
|
+
# This method is _not_ the most user-friendly option if your intention is to add a node to the
|
181
|
+
# document tree. Prefer one of the Nokogiri::XML::Node methods like Node#add_child,
|
182
|
+
# Node#add_next_sibling, Node#replace, etc. which will both create an element (or subtree) and
|
183
|
+
# place it in the document tree.
|
170
184
|
#
|
171
185
|
# Arguments may be passed to initialize the element:
|
172
|
-
#
|
173
|
-
# - a
|
186
|
+
#
|
187
|
+
# - a Hash argument will be used to set attributes
|
188
|
+
# - a non-Hash object that responds to \#to_s will be used to set the new node's contents
|
174
189
|
#
|
175
190
|
# A block may be passed to mutate the node.
|
176
191
|
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
192
|
+
# [Parameters]
|
193
|
+
# - `name` (String)
|
194
|
+
# - `contents_or_attrs` (\#to_s, Hash)
|
195
|
+
# [Yields] `node` (Nokogiri::XML::Element)
|
196
|
+
# [Returns] Nokogiri::XML::Element
|
197
|
+
#
|
198
|
+
# *Example:* An empty element without attributes
|
181
199
|
#
|
182
|
-
# @example An empty element without attributes
|
183
200
|
# doc.create_element("div")
|
184
201
|
# # => <div></div>
|
185
202
|
#
|
186
|
-
#
|
203
|
+
# *Example:* An element with contents
|
204
|
+
#
|
187
205
|
# doc.create_element("div", "contents")
|
188
206
|
# # => <div>contents</div>
|
189
207
|
#
|
190
|
-
#
|
208
|
+
# *Example:* An element with attributes
|
209
|
+
#
|
191
210
|
# doc.create_element("div", {"class" => "container"})
|
192
211
|
# # => <div class='container'></div>
|
193
212
|
#
|
194
|
-
#
|
213
|
+
# *Example:* An element with contents and attributes
|
214
|
+
#
|
195
215
|
# doc.create_element("div", "contents", {"class" => "container"})
|
196
216
|
# # => <div class='container'>contents</div>
|
197
217
|
#
|
198
|
-
#
|
218
|
+
# *Example:* Passing a block to mutate the element
|
219
|
+
#
|
199
220
|
# doc.create_element("div") { |node| node["class"] = "blue" if before_noon? }
|
200
221
|
#
|
201
222
|
def create_element(name, *contents_or_attrs, &block)
|
@@ -216,30 +237,30 @@ module Nokogiri
|
|
216
237
|
elm.content = arg
|
217
238
|
end
|
218
239
|
end
|
219
|
-
if ns = elm.namespace_definitions.find { |n| n.prefix.nil? || (n.prefix ==
|
240
|
+
if (ns = elm.namespace_definitions.find { |n| n.prefix.nil? || (n.prefix == "") })
|
220
241
|
elm.namespace = ns
|
221
242
|
end
|
222
243
|
elm
|
223
244
|
end
|
224
245
|
|
225
246
|
# Create a Text Node with +string+
|
226
|
-
def create_text_node
|
227
|
-
Nokogiri::XML::Text.new
|
247
|
+
def create_text_node(string, &block)
|
248
|
+
Nokogiri::XML::Text.new(string.to_s, self, &block)
|
228
249
|
end
|
229
250
|
|
230
251
|
# Create a CDATA Node containing +string+
|
231
|
-
def create_cdata
|
232
|
-
Nokogiri::XML::CDATA.new
|
252
|
+
def create_cdata(string, &block)
|
253
|
+
Nokogiri::XML::CDATA.new(self, string.to_s, &block)
|
233
254
|
end
|
234
255
|
|
235
256
|
# Create a Comment Node containing +string+
|
236
|
-
def create_comment
|
237
|
-
Nokogiri::XML::Comment.new
|
257
|
+
def create_comment(string, &block)
|
258
|
+
Nokogiri::XML::Comment.new(self, string.to_s, &block)
|
238
259
|
end
|
239
260
|
|
240
261
|
# The name of this document. Always returns "document"
|
241
262
|
def name
|
242
|
-
|
263
|
+
"document"
|
243
264
|
end
|
244
265
|
|
245
266
|
# A reference to +self+
|
@@ -247,46 +268,51 @@ module Nokogiri
|
|
247
268
|
self
|
248
269
|
end
|
249
270
|
|
250
|
-
|
251
|
-
#
|
252
|
-
# return them as a hash.
|
271
|
+
# :call-seq:
|
272
|
+
# collect_namespaces() → Hash<String(Namespace#prefix) ⇒ String(Namespace#href)>
|
253
273
|
#
|
254
|
-
#
|
274
|
+
# Recursively get all namespaces from this node and its subtree and return them as a
|
275
|
+
# hash.
|
255
276
|
#
|
256
|
-
#
|
277
|
+
# ⚠ This method will not handle duplicate namespace prefixes, since the return value is a hash.
|
278
|
+
#
|
279
|
+
# Note that this method does an xpath lookup for nodes with namespaces, and as a result the
|
280
|
+
# order (and which duplicate prefix "wins") may be dependent on the implementation of the
|
281
|
+
# underlying XML library.
|
282
|
+
#
|
283
|
+
# *Example:* Basic usage
|
284
|
+
#
|
285
|
+
# Given this document:
|
286
|
+
#
|
287
|
+
# <root xmlns="default" xmlns:foo="bar">
|
257
288
|
# <bar xmlns:hello="world" />
|
258
289
|
# </root>
|
259
290
|
#
|
260
291
|
# This method will return:
|
261
292
|
#
|
262
|
-
# {
|
293
|
+
# {"xmlns:foo"=>"bar", "xmlns"=>"default", "xmlns:hello"=>"world"}
|
294
|
+
#
|
295
|
+
# *Example:* Duplicate prefixes
|
263
296
|
#
|
264
|
-
#
|
265
|
-
# For example, given this document:
|
297
|
+
# Given this document:
|
266
298
|
#
|
267
299
|
# <root xmlns:foo="bar">
|
268
300
|
# <bar xmlns:foo="baz" />
|
269
301
|
# </root>
|
270
302
|
#
|
271
|
-
# The hash returned will
|
303
|
+
# The hash returned will be something like:
|
272
304
|
#
|
273
|
-
#
|
274
|
-
# in the hash.
|
275
|
-
#
|
276
|
-
# Note that this method does an xpath lookup for nodes with
|
277
|
-
# namespaces, and as a result the order may be dependent on the
|
278
|
-
# implementation of the underlying XML library.
|
305
|
+
# {"xmlns:foo" => "baz"}
|
279
306
|
#
|
280
307
|
def collect_namespaces
|
281
|
-
xpath("//namespace::*").
|
282
|
-
hash[["xmlns",ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
|
283
|
-
hash
|
308
|
+
xpath("//namespace::*").each_with_object({}) do |ns, hash|
|
309
|
+
hash[["xmlns", ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
|
284
310
|
end
|
285
311
|
end
|
286
312
|
|
287
313
|
# Get the list of decorators given +key+
|
288
|
-
def decorators
|
289
|
-
@decorators ||=
|
314
|
+
def decorators(key)
|
315
|
+
@decorators ||= {}
|
290
316
|
@decorators[key] ||= []
|
291
317
|
end
|
292
318
|
|
@@ -295,7 +321,8 @@ module Nokogiri
|
|
295
321
|
# the document or +nil+ when there is no DTD.
|
296
322
|
def validate
|
297
323
|
return nil unless internal_subset
|
298
|
-
|
324
|
+
|
325
|
+
internal_subset.validate(self)
|
299
326
|
end
|
300
327
|
|
301
328
|
##
|
@@ -315,7 +342,7 @@ module Nokogiri
|
|
315
342
|
# ... which does absolutely nothing.
|
316
343
|
#
|
317
344
|
def slop!
|
318
|
-
unless decorators(XML::Node).include?
|
345
|
+
unless decorators(XML::Node).include?(Nokogiri::Decorators::Slop)
|
319
346
|
decorators(XML::Node) << Nokogiri::Decorators::Slop
|
320
347
|
decorate!
|
321
348
|
end
|
@@ -325,16 +352,18 @@ module Nokogiri
|
|
325
352
|
|
326
353
|
##
|
327
354
|
# Apply any decorators to +node+
|
328
|
-
def decorate
|
355
|
+
def decorate(node)
|
329
356
|
return unless @decorators
|
330
|
-
|
357
|
+
|
358
|
+
@decorators.each do |klass, list|
|
331
359
|
next unless node.is_a?(klass)
|
360
|
+
|
332
361
|
list.each { |moodule| node.extend(moodule) }
|
333
|
-
|
362
|
+
end
|
334
363
|
end
|
335
364
|
|
336
|
-
|
337
|
-
|
365
|
+
alias_method :to_xml, :serialize
|
366
|
+
alias_method :clone, :dup
|
338
367
|
|
339
368
|
# Get the hash of namespaces on the root Nokogiri::XML::Node
|
340
369
|
def namespaces
|
@@ -344,35 +373,47 @@ module Nokogiri
|
|
344
373
|
##
|
345
374
|
# Create a Nokogiri::XML::DocumentFragment from +tags+
|
346
375
|
# Returns an empty fragment if +tags+ is nil.
|
347
|
-
def fragment
|
348
|
-
DocumentFragment.new(self, tags,
|
376
|
+
def fragment(tags = nil)
|
377
|
+
DocumentFragment.new(self, tags, root)
|
349
378
|
end
|
350
379
|
|
351
380
|
undef_method :swap, :parent, :namespace, :default_namespace=
|
352
381
|
undef_method :add_namespace_definition, :attributes
|
353
382
|
undef_method :namespace_definitions, :line, :add_namespace
|
354
383
|
|
355
|
-
def add_child
|
356
|
-
raise "A document may not have multiple root nodes." if (root && root.name !=
|
384
|
+
def add_child(node_or_tags)
|
385
|
+
raise "A document may not have multiple root nodes." if (root && root.name != "nokogiri_text_wrapper") && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
|
386
|
+
|
357
387
|
node_or_tags = coerce(node_or_tags)
|
358
388
|
if node_or_tags.is_a?(XML::NodeSet)
|
359
389
|
raise "A document may not have multiple root nodes." if node_or_tags.size > 1
|
390
|
+
|
360
391
|
super(node_or_tags.first)
|
361
392
|
else
|
362
393
|
super
|
363
394
|
end
|
364
395
|
end
|
365
|
-
|
396
|
+
alias_method :<<, :add_child
|
397
|
+
|
398
|
+
# :call-seq:
|
399
|
+
# xpath_doctype() → Nokogiri::CSS::XPathVisitor::DoctypeConfig
|
400
|
+
#
|
401
|
+
# [Returns] The document type which determines CSS-to-XPath translation.
|
402
|
+
#
|
403
|
+
# See XPathVisitor for more information.
|
404
|
+
def xpath_doctype
|
405
|
+
Nokogiri::CSS::XPathVisitor::DoctypeConfig::XML
|
406
|
+
end
|
366
407
|
|
367
408
|
private
|
368
409
|
|
369
|
-
def self.empty_doc?
|
410
|
+
def self.empty_doc?(string_or_io)
|
370
411
|
string_or_io.nil? ||
|
371
412
|
(string_or_io.respond_to?(:empty?) && string_or_io.empty?) ||
|
372
413
|
(string_or_io.respond_to?(:eof?) && string_or_io.eof?)
|
373
414
|
end
|
374
415
|
|
375
|
-
IMPLIED_XPATH_CONTEXTS = [
|
416
|
+
IMPLIED_XPATH_CONTEXTS = ["//"].freeze # :nodoc:
|
376
417
|
|
377
418
|
def inspect_attributes
|
378
419
|
[:name, :children]
|
@@ -1,28 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Nokogiri
|
3
4
|
module XML
|
4
5
|
class DocumentFragment < Nokogiri::XML::Node
|
6
|
+
####
|
7
|
+
# Create a Nokogiri::XML::DocumentFragment from +tags+
|
8
|
+
def self.parse(tags, options = ParseOptions::DEFAULT_XML, &block)
|
9
|
+
new(XML::Document.new, tags, nil, options, &block)
|
10
|
+
end
|
11
|
+
|
5
12
|
##
|
6
13
|
# Create a new DocumentFragment from +tags+.
|
7
14
|
#
|
8
15
|
# If +ctx+ is present, it is used as a context node for the
|
9
16
|
# subtree created, e.g., namespaces will be resolved relative
|
10
17
|
# to +ctx+.
|
11
|
-
def initialize
|
18
|
+
def initialize(document, tags = nil, ctx = nil, options = ParseOptions::DEFAULT_XML)
|
12
19
|
return self unless tags
|
13
20
|
|
21
|
+
options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
|
22
|
+
yield options if block_given?
|
23
|
+
|
14
24
|
children = if ctx
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
# Fix for issue#490
|
26
|
+
if Nokogiri.jruby?
|
27
|
+
# fix for issue #770
|
28
|
+
ctx.parse("<root #{namespace_declarations(ctx)}>#{tags}</root>", options).children
|
29
|
+
else
|
30
|
+
ctx.parse(tags, options)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
wrapper_doc = XML::Document.parse("<root>#{tags}</root>", nil, nil, options)
|
34
|
+
self.errors = wrapper_doc.errors
|
35
|
+
wrapper_doc.xpath("/root/node()")
|
36
|
+
end
|
26
37
|
children.each { |child| child.parent = self }
|
27
38
|
end
|
28
39
|
|
@@ -40,7 +51,7 @@ module Nokogiri
|
|
40
51
|
###
|
41
52
|
# return the name for DocumentFragment
|
42
53
|
def name
|
43
|
-
|
54
|
+
"#document-fragment"
|
44
55
|
end
|
45
56
|
|
46
57
|
###
|
@@ -52,10 +63,10 @@ module Nokogiri
|
|
52
63
|
###
|
53
64
|
# Convert this DocumentFragment to html
|
54
65
|
# See Nokogiri::XML::NodeSet#to_html
|
55
|
-
def to_html
|
66
|
+
def to_html(*args)
|
56
67
|
if Nokogiri.jruby?
|
57
68
|
options = args.first.is_a?(Hash) ? args.shift : {}
|
58
|
-
|
69
|
+
unless options[:save_with]
|
59
70
|
options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_HTML
|
60
71
|
end
|
61
72
|
args.insert(0, options)
|
@@ -66,10 +77,10 @@ module Nokogiri
|
|
66
77
|
###
|
67
78
|
# Convert this DocumentFragment to xhtml
|
68
79
|
# See Nokogiri::XML::NodeSet#to_xhtml
|
69
|
-
def to_xhtml
|
80
|
+
def to_xhtml(*args)
|
70
81
|
if Nokogiri.jruby?
|
71
82
|
options = args.first.is_a?(Hash) ? args.shift : {}
|
72
|
-
|
83
|
+
unless options[:save_with]
|
73
84
|
options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_XHTML
|
74
85
|
end
|
75
86
|
args.insert(0, options)
|
@@ -80,7 +91,7 @@ module Nokogiri
|
|
80
91
|
###
|
81
92
|
# Convert this DocumentFragment to xml
|
82
93
|
# See Nokogiri::XML::NodeSet#to_xml
|
83
|
-
def to_xml
|
94
|
+
def to_xml(*args)
|
84
95
|
children.to_xml(*args)
|
85
96
|
end
|
86
97
|
|
@@ -91,7 +102,7 @@ module Nokogiri
|
|
91
102
|
# selectors. For example:
|
92
103
|
#
|
93
104
|
# For more information see Nokogiri::XML::Searchable#css
|
94
|
-
def css
|
105
|
+
def css(*args)
|
95
106
|
if children.any?
|
96
107
|
children.css(*args) # 'children' is a smell here
|
97
108
|
else
|
@@ -110,34 +121,26 @@ module Nokogiri
|
|
110
121
|
# Search this fragment for +paths+. +paths+ must be one or more XPath or CSS queries.
|
111
122
|
#
|
112
123
|
# For more information see Nokogiri::XML::Searchable#search
|
113
|
-
def search
|
124
|
+
def search(*rules)
|
114
125
|
rules, handler, ns, binds = extract_params(rules)
|
115
126
|
|
116
127
|
rules.inject(NodeSet.new(document)) do |set, rule|
|
117
|
-
set
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
128
|
+
set + if Searchable::LOOKS_LIKE_XPATH.match?(rule)
|
129
|
+
xpath(*[rule, ns, handler, binds].compact)
|
130
|
+
else
|
131
|
+
children.css(*[rule, ns, handler].compact) # 'children' is a smell here
|
132
|
+
end
|
122
133
|
end
|
123
134
|
end
|
124
135
|
|
125
|
-
|
126
|
-
|
127
|
-
class << self
|
128
|
-
####
|
129
|
-
# Create a Nokogiri::XML::DocumentFragment from +tags+
|
130
|
-
def parse tags
|
131
|
-
self.new(XML::Document.new, tags)
|
132
|
-
end
|
133
|
-
end
|
136
|
+
alias_method :serialize, :to_s
|
134
137
|
|
135
138
|
# A list of Nokogiri::XML::SyntaxError found when parsing a document
|
136
139
|
def errors
|
137
140
|
document.errors
|
138
141
|
end
|
139
142
|
|
140
|
-
def errors=
|
143
|
+
def errors=(things) # :nodoc:
|
141
144
|
document.errors = things
|
142
145
|
end
|
143
146
|
|
@@ -148,11 +151,11 @@ module Nokogiri
|
|
148
151
|
private
|
149
152
|
|
150
153
|
# fix for issue 770
|
151
|
-
def namespace_declarations
|
154
|
+
def namespace_declarations(ctx)
|
152
155
|
ctx.namespace_scopes.map do |namespace|
|
153
156
|
prefix = namespace.prefix.nil? ? "" : ":#{namespace.prefix}"
|
154
|
-
%
|
155
|
-
end.join
|
157
|
+
%{xmlns#{prefix}="#{namespace.href}"}
|
158
|
+
end.join(" ")
|
156
159
|
end
|
157
160
|
end
|
158
161
|
end
|
data/lib/nokogiri/xml/dtd.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Nokogiri
|
3
4
|
module XML
|
4
5
|
class DTD < Nokogiri::XML::Node
|
@@ -20,13 +21,13 @@ module Nokogiri
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def html_dtd?
|
23
|
-
name.casecmp(
|
24
|
+
name.casecmp("html").zero?
|
24
25
|
end
|
25
26
|
|
26
27
|
def html5_dtd?
|
27
28
|
html_dtd? &&
|
28
29
|
external_id.nil? &&
|
29
|
-
(system_id.nil? || system_id ==
|
30
|
+
(system_id.nil? || system_id == "about:legacy-compat")
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Nokogiri
|
3
4
|
module XML
|
4
5
|
class ElementDecl < Nokogiri::XML::Node
|
@@ -7,7 +8,7 @@ module Nokogiri
|
|
7
8
|
undef_method :line if method_defined?(:line)
|
8
9
|
|
9
10
|
def inspect
|
10
|
-
"#<#{self.class.name}:#{
|
11
|
+
"#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Nokogiri
|
3
4
|
module XML
|
4
5
|
class EntityDecl < Nokogiri::XML::Node
|
@@ -8,12 +9,12 @@ module Nokogiri
|
|
8
9
|
undef_method :namespace_definitions
|
9
10
|
undef_method :line if method_defined?(:line)
|
10
11
|
|
11
|
-
def self.new
|
12
|
+
def self.new(name, doc, *args)
|
12
13
|
doc.create_entity(name, *args)
|
13
14
|
end
|
14
15
|
|
15
16
|
def inspect
|
16
|
-
"#<#{self.class.name}:#{
|
17
|
+
"#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|