nokogiri 1.12.3-x86_64-linux → 1.13.1-x86_64-linux

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/README.md +9 -7
  4. data/bin/nokogiri +63 -50
  5. data/dependencies.yml +5 -6
  6. data/ext/nokogiri/extconf.rb +47 -35
  7. data/ext/nokogiri/include/libxml2/libxml/xmlerror.h +1 -0
  8. data/ext/nokogiri/include/libxslt/xsltconfig.h +1 -1
  9. data/ext/nokogiri/xml_document.c +35 -35
  10. data/ext/nokogiri/xml_document_fragment.c +0 -2
  11. data/ext/nokogiri/xml_dtd.c +2 -2
  12. data/ext/nokogiri/xml_encoding_handler.c +25 -11
  13. data/ext/nokogiri/xml_node.c +645 -333
  14. data/ext/nokogiri/xml_reader.c +37 -11
  15. data/ext/nokogiri/xml_xpath_context.c +72 -49
  16. data/ext/nokogiri/xslt_stylesheet.c +107 -9
  17. data/lib/nokogiri/2.6/nokogiri.so +0 -0
  18. data/lib/nokogiri/2.7/nokogiri.so +0 -0
  19. data/lib/nokogiri/3.0/nokogiri.so +0 -0
  20. data/lib/nokogiri/3.1/nokogiri.so +0 -0
  21. data/lib/nokogiri/class_resolver.rb +67 -0
  22. data/lib/nokogiri/css/node.rb +9 -8
  23. data/lib/nokogiri/css/parser.rb +360 -341
  24. data/lib/nokogiri/css/parser.y +249 -244
  25. data/lib/nokogiri/css/parser_extras.rb +20 -20
  26. data/lib/nokogiri/css/syntax_error.rb +1 -0
  27. data/lib/nokogiri/css/tokenizer.rb +4 -3
  28. data/lib/nokogiri/css/tokenizer.rex +3 -2
  29. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  30. data/lib/nokogiri/css.rb +38 -6
  31. data/lib/nokogiri/decorators/slop.rb +8 -7
  32. data/lib/nokogiri/extension.rb +1 -1
  33. data/lib/nokogiri/gumbo.rb +1 -0
  34. data/lib/nokogiri/html.rb +16 -10
  35. data/lib/nokogiri/html4/builder.rb +1 -0
  36. data/lib/nokogiri/html4/document.rb +84 -75
  37. data/lib/nokogiri/html4/document_fragment.rb +11 -7
  38. data/lib/nokogiri/html4/element_description.rb +1 -0
  39. data/lib/nokogiri/html4/element_description_defaults.rb +426 -520
  40. data/lib/nokogiri/html4/entity_lookup.rb +2 -1
  41. data/lib/nokogiri/html4/sax/parser.rb +2 -1
  42. data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
  43. data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
  44. data/lib/nokogiri/html4.rb +11 -5
  45. data/lib/nokogiri/html5/document.rb +24 -10
  46. data/lib/nokogiri/html5/document_fragment.rb +5 -2
  47. data/lib/nokogiri/html5/node.rb +6 -3
  48. data/lib/nokogiri/html5.rb +68 -64
  49. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  50. data/lib/nokogiri/syntax_error.rb +1 -0
  51. data/lib/nokogiri/version/constant.rb +2 -1
  52. data/lib/nokogiri/version/info.rb +19 -13
  53. data/lib/nokogiri/version.rb +1 -0
  54. data/lib/nokogiri/xml/attr.rb +5 -3
  55. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  56. data/lib/nokogiri/xml/builder.rb +69 -31
  57. data/lib/nokogiri/xml/cdata.rb +2 -1
  58. data/lib/nokogiri/xml/character_data.rb +1 -0
  59. data/lib/nokogiri/xml/document.rb +178 -96
  60. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  61. data/lib/nokogiri/xml/dtd.rb +3 -2
  62. data/lib/nokogiri/xml/element_content.rb +1 -0
  63. data/lib/nokogiri/xml/element_decl.rb +2 -1
  64. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  65. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  66. data/lib/nokogiri/xml/namespace.rb +2 -0
  67. data/lib/nokogiri/xml/node/save_options.rb +7 -4
  68. data/lib/nokogiri/xml/node.rb +512 -348
  69. data/lib/nokogiri/xml/node_set.rb +46 -54
  70. data/lib/nokogiri/xml/notation.rb +12 -0
  71. data/lib/nokogiri/xml/parse_options.rb +11 -7
  72. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  73. data/lib/nokogiri/xml/pp/node.rb +24 -26
  74. data/lib/nokogiri/xml/pp.rb +1 -0
  75. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  76. data/lib/nokogiri/xml/reader.rb +17 -19
  77. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  78. data/lib/nokogiri/xml/sax/document.rb +20 -19
  79. data/lib/nokogiri/xml/sax/parser.rb +36 -34
  80. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  81. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  82. data/lib/nokogiri/xml/sax.rb +1 -0
  83. data/lib/nokogiri/xml/schema.rb +7 -6
  84. data/lib/nokogiri/xml/searchable.rb +93 -62
  85. data/lib/nokogiri/xml/syntax_error.rb +4 -4
  86. data/lib/nokogiri/xml/text.rb +1 -0
  87. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  88. data/lib/nokogiri/xml/xpath.rb +12 -0
  89. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  90. data/lib/nokogiri/xml.rb +3 -3
  91. data/lib/nokogiri/xslt/stylesheet.rb +1 -0
  92. data/lib/nokogiri/xslt.rb +21 -13
  93. data/lib/nokogiri.rb +19 -16
  94. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  95. metadata +124 -52
  96. data/lib/nokogiri/2.5/nokogiri.so +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,109 +45,178 @@ 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
- def initialize *args # :nodoc:
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
127
+ #
128
+ # xml = <<~EOF
129
+ # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
130
+ # <foo:parent>
131
+ # </foo:parent>
132
+ # </root>
133
+ # EOF
134
+ # doc = Nokogiri::XML(xml)
135
+ # parent = doc.at_xpath("//foo:parent", "foo" => "http://nokogiri.org/default_ns/test/foo")
136
+ # parent.add_child("<child></child>")
137
+ # doc.to_xml
138
+ # # => <?xml version="1.0"?>
139
+ # # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
140
+ # # <foo:parent>
141
+ # # <child/>
142
+ # # </foo:parent>
143
+ # # </root>
144
+ #
145
+ # *Example:* Setting namespace inheritance to `true`
146
+ #
147
+ # xml = <<~EOF
148
+ # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
149
+ # <foo:parent>
150
+ # </foo:parent>
151
+ # </root>
152
+ # EOF
153
+ # doc = Nokogiri::XML(xml)
154
+ # doc.namespace_inheritance = true
155
+ # parent = doc.at_xpath("//foo:parent", "foo" => "http://nokogiri.org/default_ns/test/foo")
156
+ # parent.add_child("<child></child>")
157
+ # doc.to_xml
158
+ # # => <?xml version="1.0"?>
159
+ # # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
160
+ # # <foo:parent>
161
+ # # <foo:child/>
162
+ # # </foo:parent>
163
+ # # </root>
164
+ #
165
+ # Since v1.12.4
166
+ attr_accessor :namespace_inheritance
167
+
168
+ def initialize(*args) # :nodoc:
117
169
  @errors = []
118
170
  @decorators = nil
171
+ @namespace_inheritance = false
119
172
  end
120
173
 
121
- ##
122
- # Create a new +Element+ with +name+ sharing GC lifecycle with the document, optionally
123
- # 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.
124
184
  #
125
185
  # Arguments may be passed to initialize the element:
126
- # - a +Hash+ argument will be used to set attributes
127
- # - 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
128
189
  #
129
190
  # A block may be passed to mutate the node.
130
191
  #
131
- # @param name [String]
132
- # @param contents_or_attrs [#to_s,Hash]
133
- # @yieldparam node [Nokogiri::XML::Element]
134
- # @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
135
199
  #
136
- # @example An empty element without attributes
137
200
  # doc.create_element("div")
138
201
  # # => <div></div>
139
202
  #
140
- # @example An element with contents
203
+ # *Example:* An element with contents
204
+ #
141
205
  # doc.create_element("div", "contents")
142
206
  # # => <div>contents</div>
143
207
  #
144
- # @example An element with attributes
208
+ # *Example:* An element with attributes
209
+ #
145
210
  # doc.create_element("div", {"class" => "container"})
146
211
  # # => <div class='container'></div>
147
212
  #
148
- # @example An element with contents and attributes
213
+ # *Example:* An element with contents and attributes
214
+ #
149
215
  # doc.create_element("div", "contents", {"class" => "container"})
150
216
  # # => <div class='container'>contents</div>
151
217
  #
152
- # @example Passing a block to mutate the element
218
+ # *Example:* Passing a block to mutate the element
219
+ #
153
220
  # doc.create_element("div") { |node| node["class"] = "blue" if before_noon? }
154
221
  #
155
222
  def create_element(name, *contents_or_attrs, &block)
@@ -170,30 +237,30 @@ module Nokogiri
170
237
  elm.content = arg
171
238
  end
172
239
  end
173
- 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 == "") })
174
241
  elm.namespace = ns
175
242
  end
176
243
  elm
177
244
  end
178
245
 
179
246
  # Create a Text Node with +string+
180
- def create_text_node string, &block
181
- 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)
182
249
  end
183
250
 
184
251
  # Create a CDATA Node containing +string+
185
- def create_cdata string, &block
186
- 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)
187
254
  end
188
255
 
189
256
  # Create a Comment Node containing +string+
190
- def create_comment string, &block
191
- 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)
192
259
  end
193
260
 
194
261
  # The name of this document. Always returns "document"
195
262
  def name
196
- 'document'
263
+ "document"
197
264
  end
198
265
 
199
266
  # A reference to +self+
@@ -201,46 +268,51 @@ module Nokogiri
201
268
  self
202
269
  end
203
270
 
204
- ##
205
- # Recursively get all namespaces from this node and its subtree and
206
- # return them as a hash.
271
+ # :call-seq:
272
+ # collect_namespaces() Hash<String(Namespace#prefix) String(Namespace#href)>
207
273
  #
208
- # For example, given this document:
274
+ # Recursively get all namespaces from this node and its subtree and return them as a
275
+ # hash.
209
276
  #
210
- # <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">
211
288
  # <bar xmlns:hello="world" />
212
289
  # </root>
213
290
  #
214
291
  # This method will return:
215
292
  #
216
- # { 'xmlns:foo' => 'bar', 'xmlns:hello' => 'world' }
293
+ # {"xmlns:foo"=>"bar", "xmlns"=>"default", "xmlns:hello"=>"world"}
294
+ #
295
+ # *Example:* Duplicate prefixes
217
296
  #
218
- # WARNING: this method will clobber duplicate names in the keys.
219
- # For example, given this document:
297
+ # Given this document:
220
298
  #
221
299
  # <root xmlns:foo="bar">
222
300
  # <bar xmlns:foo="baz" />
223
301
  # </root>
224
302
  #
225
- # The hash returned will look like this: { 'xmlns:foo' => 'bar' }
303
+ # The hash returned will be something like:
226
304
  #
227
- # Non-prefixed default namespaces (as in "xmlns=") are not included
228
- # in the hash.
229
- #
230
- # Note that this method does an xpath lookup for nodes with
231
- # namespaces, and as a result the order may be dependent on the
232
- # implementation of the underlying XML library.
305
+ # {"xmlns:foo" => "baz"}
233
306
  #
234
307
  def collect_namespaces
235
- xpath("//namespace::*").inject({}) do |hash, ns|
236
- hash[["xmlns",ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
237
- hash
308
+ xpath("//namespace::*").each_with_object({}) do |ns, hash|
309
+ hash[["xmlns", ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
238
310
  end
239
311
  end
240
312
 
241
313
  # Get the list of decorators given +key+
242
- def decorators key
243
- @decorators ||= Hash.new
314
+ def decorators(key)
315
+ @decorators ||= {}
244
316
  @decorators[key] ||= []
245
317
  end
246
318
 
@@ -249,7 +321,7 @@ module Nokogiri
249
321
  # the document or +nil+ when there is no DTD.
250
322
  def validate
251
323
  return nil unless internal_subset
252
- internal_subset.validate self
324
+ internal_subset.validate(self)
253
325
  end
254
326
 
255
327
  ##
@@ -269,7 +341,7 @@ module Nokogiri
269
341
  # ... which does absolutely nothing.
270
342
  #
271
343
  def slop!
272
- unless decorators(XML::Node).include? Nokogiri::Decorators::Slop
344
+ unless decorators(XML::Node).include?(Nokogiri::Decorators::Slop)
273
345
  decorators(XML::Node) << Nokogiri::Decorators::Slop
274
346
  decorate!
275
347
  end
@@ -279,16 +351,16 @@ module Nokogiri
279
351
 
280
352
  ##
281
353
  # Apply any decorators to +node+
282
- def decorate node
354
+ def decorate(node)
283
355
  return unless @decorators
284
- @decorators.each { |klass,list|
356
+ @decorators.each do |klass, list|
285
357
  next unless node.is_a?(klass)
286
358
  list.each { |moodule| node.extend(moodule) }
287
- }
359
+ end
288
360
  end
289
361
 
290
- alias :to_xml :serialize
291
- alias :clone :dup
362
+ alias_method :to_xml, :serialize
363
+ alias_method :clone, :dup
292
364
 
293
365
  # Get the hash of namespaces on the root Nokogiri::XML::Node
294
366
  def namespaces
@@ -298,16 +370,16 @@ module Nokogiri
298
370
  ##
299
371
  # Create a Nokogiri::XML::DocumentFragment from +tags+
300
372
  # Returns an empty fragment if +tags+ is nil.
301
- def fragment tags = nil
302
- DocumentFragment.new(self, tags, self.root)
373
+ def fragment(tags = nil)
374
+ DocumentFragment.new(self, tags, root)
303
375
  end
304
376
 
305
377
  undef_method :swap, :parent, :namespace, :default_namespace=
306
378
  undef_method :add_namespace_definition, :attributes
307
379
  undef_method :namespace_definitions, :line, :add_namespace
308
380
 
309
- def add_child node_or_tags
310
- 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?)
381
+ def add_child(node_or_tags)
382
+ 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?)
311
383
  node_or_tags = coerce(node_or_tags)
312
384
  if node_or_tags.is_a?(XML::NodeSet)
313
385
  raise "A document may not have multiple root nodes." if node_or_tags.size > 1
@@ -316,17 +388,27 @@ module Nokogiri
316
388
  super
317
389
  end
318
390
  end
319
- alias :<< :add_child
391
+ alias_method :<<, :add_child
392
+
393
+ # :call-seq:
394
+ # xpath_doctype() → Nokogiri::CSS::XPathVisitor::DoctypeConfig
395
+ #
396
+ # [Returns] The document type which determines CSS-to-XPath translation.
397
+ #
398
+ # See XPathVisitor for more information.
399
+ def xpath_doctype
400
+ Nokogiri::CSS::XPathVisitor::DoctypeConfig::XML
401
+ end
320
402
 
321
403
  private
322
404
 
323
- def self.empty_doc? string_or_io
405
+ def self.empty_doc?(string_or_io)
324
406
  string_or_io.nil? ||
325
407
  (string_or_io.respond_to?(:empty?) && string_or_io.empty?) ||
326
408
  (string_or_io.respond_to?(:eof?) && string_or_io.eof?)
327
409
  end
328
410
 
329
- IMPLIED_XPATH_CONTEXTS = [ '//'.freeze ].freeze # :nodoc:
411
+ IMPLIED_XPATH_CONTEXTS = ["//"].freeze # :nodoc:
330
412
 
331
413
  def inspect_attributes
332
414
  [: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