nokogiri 1.12.5 → 1.13.9

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +9 -7
  4. data/bin/nokogiri +63 -50
  5. data/dependencies.yml +13 -64
  6. data/ext/nokogiri/extconf.rb +81 -46
  7. data/ext/nokogiri/gumbo.c +1 -1
  8. data/ext/nokogiri/html4_sax_parser_context.c +2 -3
  9. data/ext/nokogiri/nokogiri.h +9 -0
  10. data/ext/nokogiri/xml_attr.c +2 -2
  11. data/ext/nokogiri/xml_attribute_decl.c +3 -3
  12. data/ext/nokogiri/xml_cdata.c +1 -1
  13. data/ext/nokogiri/xml_document.c +41 -37
  14. data/ext/nokogiri/xml_document_fragment.c +0 -2
  15. data/ext/nokogiri/xml_dtd.c +10 -10
  16. data/ext/nokogiri/xml_element_decl.c +3 -3
  17. data/ext/nokogiri/xml_encoding_handler.c +25 -11
  18. data/ext/nokogiri/xml_entity_decl.c +5 -5
  19. data/ext/nokogiri/xml_namespace.c +41 -5
  20. data/ext/nokogiri/xml_node.c +708 -382
  21. data/ext/nokogiri/xml_node_set.c +4 -4
  22. data/ext/nokogiri/xml_reader.c +88 -11
  23. data/ext/nokogiri/xml_sax_parser_context.c +10 -3
  24. data/ext/nokogiri/xml_schema.c +3 -3
  25. data/ext/nokogiri/xml_text.c +1 -1
  26. data/ext/nokogiri/xml_xpath_context.c +76 -50
  27. data/ext/nokogiri/xslt_stylesheet.c +107 -9
  28. data/gumbo-parser/src/parser.c +0 -11
  29. data/lib/nokogiri/class_resolver.rb +67 -0
  30. data/lib/nokogiri/css/node.rb +9 -8
  31. data/lib/nokogiri/css/parser.rb +360 -341
  32. data/lib/nokogiri/css/parser.y +249 -244
  33. data/lib/nokogiri/css/parser_extras.rb +22 -20
  34. data/lib/nokogiri/css/syntax_error.rb +1 -0
  35. data/lib/nokogiri/css/tokenizer.rb +4 -3
  36. data/lib/nokogiri/css/tokenizer.rex +3 -2
  37. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  38. data/lib/nokogiri/css.rb +38 -6
  39. data/lib/nokogiri/decorators/slop.rb +8 -7
  40. data/lib/nokogiri/extension.rb +1 -1
  41. data/lib/nokogiri/gumbo.rb +1 -0
  42. data/lib/nokogiri/html.rb +16 -10
  43. data/lib/nokogiri/html4/builder.rb +1 -0
  44. data/lib/nokogiri/html4/document.rb +88 -77
  45. data/lib/nokogiri/html4/document_fragment.rb +11 -7
  46. data/lib/nokogiri/html4/element_description.rb +1 -0
  47. data/lib/nokogiri/html4/element_description_defaults.rb +426 -520
  48. data/lib/nokogiri/html4/entity_lookup.rb +2 -1
  49. data/lib/nokogiri/html4/sax/parser.rb +5 -2
  50. data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
  51. data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
  52. data/lib/nokogiri/html4.rb +11 -5
  53. data/lib/nokogiri/html5/document.rb +27 -10
  54. data/lib/nokogiri/html5/document_fragment.rb +5 -2
  55. data/lib/nokogiri/html5/node.rb +10 -3
  56. data/lib/nokogiri/html5.rb +69 -64
  57. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  58. data/lib/nokogiri/syntax_error.rb +1 -0
  59. data/lib/nokogiri/version/constant.rb +2 -1
  60. data/lib/nokogiri/version/info.rb +20 -13
  61. data/lib/nokogiri/version.rb +1 -0
  62. data/lib/nokogiri/xml/attr.rb +5 -3
  63. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  64. data/lib/nokogiri/xml/builder.rb +34 -32
  65. data/lib/nokogiri/xml/cdata.rb +2 -1
  66. data/lib/nokogiri/xml/character_data.rb +1 -0
  67. data/lib/nokogiri/xml/document.rb +144 -103
  68. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  69. data/lib/nokogiri/xml/dtd.rb +3 -2
  70. data/lib/nokogiri/xml/element_content.rb +1 -0
  71. data/lib/nokogiri/xml/element_decl.rb +2 -1
  72. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  73. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  74. data/lib/nokogiri/xml/namespace.rb +2 -0
  75. data/lib/nokogiri/xml/node/save_options.rb +8 -4
  76. data/lib/nokogiri/xml/node.rb +521 -351
  77. data/lib/nokogiri/xml/node_set.rb +50 -54
  78. data/lib/nokogiri/xml/notation.rb +12 -0
  79. data/lib/nokogiri/xml/parse_options.rb +12 -7
  80. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  81. data/lib/nokogiri/xml/pp/node.rb +24 -26
  82. data/lib/nokogiri/xml/pp.rb +1 -0
  83. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  84. data/lib/nokogiri/xml/reader.rb +20 -24
  85. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  86. data/lib/nokogiri/xml/sax/document.rb +20 -19
  87. data/lib/nokogiri/xml/sax/parser.rb +37 -34
  88. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  89. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  90. data/lib/nokogiri/xml/sax.rb +1 -0
  91. data/lib/nokogiri/xml/schema.rb +7 -6
  92. data/lib/nokogiri/xml/searchable.rb +93 -62
  93. data/lib/nokogiri/xml/syntax_error.rb +5 -4
  94. data/lib/nokogiri/xml/text.rb +1 -0
  95. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  96. data/lib/nokogiri/xml/xpath.rb +12 -0
  97. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  98. data/lib/nokogiri/xml.rb +4 -3
  99. data/lib/nokogiri/xslt/stylesheet.rb +1 -0
  100. data/lib/nokogiri/xslt.rb +21 -13
  101. data/lib/nokogiri.rb +19 -16
  102. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  103. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  104. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
  105. data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
  106. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
  107. metadata +103 -34
  108. data/patches/libxml2/0004-use-glibc-strlen.patch +0 -53
  109. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +0 -2511
  110. data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +0 -31
  111. data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
  112. data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
  113. 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 'pathname'
4
+ require "pathname"
5
5
 
6
6
  module Nokogiri
7
7
  module XML
8
- ##
9
- # Nokogiri::XML::Document is the main entry point for dealing with
10
- # XML documents. The Document is created by parsing an XML document.
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 string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML
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.new("Empty document")
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
- if string_or_io.is_a?(Pathname)
67
- # resolve the Pathname to the file and open it as an IO object, see #2110
68
- string_or_io = string_or_io.expand_path.open
69
- url ||= string_or_io.path
70
- end
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
- read_io(string_or_io, url, encoding, options.to_i)
73
- else
74
- # read_memory pukes on empty docs
75
- read_memory(string_or_io, url, encoding, options.to_i)
76
- end
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
- return doc
78
+ doc
82
79
  end
83
80
 
84
81
  ##
85
- # @!method wrap(java_document)
86
- # @!scope class
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 {Document} using an existing Java DOM document object.
87
+ # Create a Document using an existing Java DOM document object.
89
88
  #
90
- # The returned {Document} shares the same underlying data structure as the Java object, so
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
- # @param java_document [Java::OrgW3cDom::Document]
94
- # @return [Nokogiri::XML::Document]
95
- # @note This method is only available when running JRuby.
96
- # @note The class +Java::OrgW3cDom::Document+ is also accessible as +org.w3c.dom.Document+.
97
- # @see #to_java
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
- # @!method to_java()
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 the {Document}.
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 the {Document}, so
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
- # @return [Java::OrgW3cDom::Document]
108
- # @note This method is only available when running JRuby.
109
- # @note The class +Java::OrgW3cDom::Document+ is also accessible as +org.w3c.dom.Document+.
110
- # @see .wrap
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
- # A list of Nokogiri::XML::SyntaxError found when parsing a document
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, reparented elements without a namespace will inherit their new parent's
117
- # namespace (if one exists). Defaults to +false+.
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
- # @example Setting namespace inheritance to +true+
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
- # @return [Boolean]
157
- #
158
- # @since v1.12.4
165
+ # Since v1.12.4
159
166
  attr_accessor :namespace_inheritance
160
167
 
161
- def initialize *args # :nodoc:
168
+ def initialize(*args) # :nodoc:
162
169
  @errors = []
163
170
  @decorators = nil
164
171
  @namespace_inheritance = false
165
172
  end
166
173
 
167
- ##
168
- # Create a new +Element+ with +name+ sharing GC lifecycle with the document, optionally
169
- # setting contents or attributes.
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
- # - a +Hash+ argument will be used to set attributes
173
- # - a non-Hash object that responds to +#to_s+ will be used to set the new node's contents
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
- # @param name [String]
178
- # @param contents_or_attrs [#to_s,Hash]
179
- # @yieldparam node [Nokogiri::XML::Element]
180
- # @return [Nokogiri::XML::Element]
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
- # @example An element with contents
203
+ # *Example:* An element with contents
204
+ #
187
205
  # doc.create_element("div", "contents")
188
206
  # # => <div>contents</div>
189
207
  #
190
- # @example An element with attributes
208
+ # *Example:* An element with attributes
209
+ #
191
210
  # doc.create_element("div", {"class" => "container"})
192
211
  # # => <div class='container'></div>
193
212
  #
194
- # @example An element with contents and attributes
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
- # @example Passing a block to mutate the element
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 string, &block
227
- Nokogiri::XML::Text.new string.to_s, self, &block
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 string, &block
232
- Nokogiri::XML::CDATA.new self, string.to_s, &block
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 string, &block
237
- Nokogiri::XML::Comment.new self, string.to_s, &block
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
- 'document'
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
- # Recursively get all namespaces from this node and its subtree and
252
- # return them as a hash.
271
+ # :call-seq:
272
+ # collect_namespaces() Hash<String(Namespace#prefix) String(Namespace#href)>
253
273
  #
254
- # For example, given this document:
274
+ # Recursively get all namespaces from this node and its subtree and return them as a
275
+ # hash.
255
276
  #
256
- # <root xmlns:foo="bar">
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
- # { 'xmlns:foo' => 'bar', 'xmlns:hello' => 'world' }
293
+ # {"xmlns:foo"=>"bar", "xmlns"=>"default", "xmlns:hello"=>"world"}
294
+ #
295
+ # *Example:* Duplicate prefixes
263
296
  #
264
- # WARNING: this method will clobber duplicate names in the keys.
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 look like this: { 'xmlns:foo' => 'bar' }
303
+ # The hash returned will be something like:
272
304
  #
273
- # Non-prefixed default namespaces (as in "xmlns=") are not included
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::*").inject({}) do |hash, ns|
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 key
289
- @decorators ||= Hash.new
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
- internal_subset.validate self
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? Nokogiri::Decorators::Slop
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 node
355
+ def decorate(node)
329
356
  return unless @decorators
330
- @decorators.each { |klass,list|
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
- alias :to_xml :serialize
337
- alias :clone :dup
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 tags = nil
348
- DocumentFragment.new(self, tags, self.root)
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 node_or_tags
356
- 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?)
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
- alias :<< :add_child
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? string_or_io
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 = [ '//'.freeze ].freeze # :nodoc:
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 document, tags = nil, ctx = nil
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
- # Fix for issue#490
16
- if Nokogiri.jruby?
17
- # fix for issue #770
18
- ctx.parse("<root #{namespace_declarations(ctx)}>#{tags}</root>").children
19
- else
20
- ctx.parse(tags)
21
- end
22
- else
23
- XML::Document.parse("<root>#{tags}</root>") \
24
- .xpath("/root/node()")
25
- end
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
- '#document-fragment'
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 *args
66
+ def to_html(*args)
56
67
  if Nokogiri.jruby?
57
68
  options = args.first.is_a?(Hash) ? args.shift : {}
58
- if !options[:save_with]
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 *args
80
+ def to_xhtml(*args)
70
81
  if Nokogiri.jruby?
71
82
  options = args.first.is_a?(Hash) ? args.shift : {}
72
- if !options[:save_with]
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 *args
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 *args
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 *rules
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 += if rule =~ Searchable::LOOKS_LIKE_XPATH
118
- xpath(*([rule, ns, handler, binds].compact))
119
- else
120
- children.css(*([rule, ns, handler].compact)) # 'children' is a smell here
121
- end
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
- alias :serialize :to_s
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= things # :nodoc:
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 ctx
154
+ def namespace_declarations(ctx)
152
155
  ctx.namespace_scopes.map do |namespace|
153
156
  prefix = namespace.prefix.nil? ? "" : ":#{namespace.prefix}"
154
- %Q{xmlns#{prefix}="#{namespace.href}"}
155
- end.join ' '
157
+ %{xmlns#{prefix}="#{namespace.href}"}
158
+ end.join(" ")
156
159
  end
157
160
  end
158
161
  end
@@ -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('html').zero?
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 == 'about:legacy-compat')
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
  ###
@@ -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}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
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 name, doc, *args
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}:#{sprintf("0x%x", object_id)} #{to_s.inspect}>"
17
+ "#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
17
18
  end
18
19
  end
19
20
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  class EntityReference < Nokogiri::XML::Node