nokogiri 1.14.3 → 1.15.0

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +9 -8
  3. data/dependencies.yml +6 -6
  4. data/ext/nokogiri/extconf.rb +66 -22
  5. data/ext/nokogiri/html4_document.c +1 -2
  6. data/ext/nokogiri/html4_element_description.c +19 -14
  7. data/ext/nokogiri/html4_sax_parser_context.c +10 -16
  8. data/ext/nokogiri/html4_sax_push_parser.c +2 -2
  9. data/ext/nokogiri/nokogiri.c +46 -24
  10. data/ext/nokogiri/nokogiri.h +13 -2
  11. data/ext/nokogiri/xml_attr.c +1 -1
  12. data/ext/nokogiri/xml_cdata.c +10 -2
  13. data/ext/nokogiri/xml_comment.c +1 -1
  14. data/ext/nokogiri/xml_document.c +102 -22
  15. data/ext/nokogiri/xml_document_fragment.c +1 -1
  16. data/ext/nokogiri/xml_dtd.c +1 -1
  17. data/ext/nokogiri/xml_element_content.c +32 -29
  18. data/ext/nokogiri/xml_element_decl.c +5 -5
  19. data/ext/nokogiri/xml_encoding_handler.c +12 -4
  20. data/ext/nokogiri/xml_entity_reference.c +1 -1
  21. data/ext/nokogiri/xml_namespace.c +11 -12
  22. data/ext/nokogiri/xml_node.c +7 -7
  23. data/ext/nokogiri/xml_node_set.c +125 -105
  24. data/ext/nokogiri/xml_processing_instruction.c +1 -1
  25. data/ext/nokogiri/xml_reader.c +37 -28
  26. data/ext/nokogiri/xml_relax_ng.c +65 -78
  27. data/ext/nokogiri/xml_sax_parser.c +24 -5
  28. data/ext/nokogiri/xml_sax_parser_context.c +46 -25
  29. data/ext/nokogiri/xml_sax_push_parser.c +29 -8
  30. data/ext/nokogiri/xml_schema.c +90 -116
  31. data/ext/nokogiri/xml_text.c +10 -2
  32. data/ext/nokogiri/xml_xpath_context.c +156 -83
  33. data/ext/nokogiri/xslt_stylesheet.c +103 -50
  34. data/gumbo-parser/src/error.c +8 -4
  35. data/gumbo-parser/src/foreign_attrs.c +13 -14
  36. data/gumbo-parser/src/foreign_attrs.gperf +1 -1
  37. data/gumbo-parser/src/parser.c +13 -0
  38. data/lib/nokogiri/css/xpath_visitor.rb +2 -2
  39. data/lib/nokogiri/extension.rb +1 -1
  40. data/lib/nokogiri/html4/document_fragment.rb +1 -1
  41. data/lib/nokogiri/html4/element_description_defaults.rb +1821 -353
  42. data/lib/nokogiri/html5/document_fragment.rb +1 -1
  43. data/lib/nokogiri/html5/node.rb +5 -0
  44. data/lib/nokogiri/html5.rb +5 -2
  45. data/lib/nokogiri/jruby/nokogiri_jars.rb +6 -6
  46. data/lib/nokogiri/version/constant.rb +1 -1
  47. data/lib/nokogiri/xml/attribute_decl.rb +4 -2
  48. data/lib/nokogiri/xml/document_fragment.rb +1 -1
  49. data/lib/nokogiri/xml/element_content.rb +10 -2
  50. data/lib/nokogiri/xml/element_decl.rb +4 -2
  51. data/lib/nokogiri/xml/entity_decl.rb +4 -2
  52. data/lib/nokogiri/xml/node/save_options.rb +8 -0
  53. data/lib/nokogiri/xml/node.rb +22 -13
  54. data/lib/nokogiri/xml/pp/node.rb +23 -12
  55. data/lib/nokogiri/xml/sax/document.rb +1 -1
  56. data/lib/nokogiri/xml/searchable.rb +18 -10
  57. data/lib/nokogiri/xslt.rb +73 -3
  58. data/lib/nokogiri.rb +12 -4
  59. data/lib/xsd/xmlparser/nokogiri.rb +1 -1
  60. data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
  61. data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
  62. data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
  63. data/ports/archives/libxml2-2.11.3.tar.xz +0 -0
  64. data/ports/archives/libxslt-1.1.38.tar.xz +0 -0
  65. metadata +9 -7
  66. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +0 -3037
  67. data/ports/archives/libxml2-2.10.4.tar.xz +0 -0
  68. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
@@ -36,7 +36,7 @@ module Nokogiri
36
36
  attr_reader :quirks_mode
37
37
 
38
38
  # Create a document fragment.
39
- def initialize(doc, tags = nil, ctx = nil, options = {})
39
+ def initialize(doc, tags = nil, ctx = nil, options = {}) # rubocop:disable Lint/MissingSuper
40
40
  self.document = doc
41
41
  self.errors = []
42
42
  return self unless tags
@@ -17,6 +17,9 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+ #
21
+ # TODO: this whole file should go away. maybe make it a decorator?
22
+ #
20
23
  require_relative "../xml/node"
21
24
 
22
25
  module Nokogiri
@@ -50,6 +53,8 @@ module Nokogiri
50
53
  config = XML::Node::SaveOptions.new(save_options.to_i)
51
54
  yield config if block_given?
52
55
 
56
+ encoding = encoding.is_a?(Encoding) ? encoding.name : encoding
57
+
53
58
  config_options = config.options
54
59
  if config_options & (XML::Node::SaveOptions::AS_XML | XML::Node::SaveOptions::AS_XHTML) != 0
55
60
  # Use Nokogiri's serializing code.
@@ -248,8 +248,11 @@ module Nokogiri
248
248
  # * :basic_auth => [username, password]
249
249
  def get(uri, options = {})
250
250
  # TODO: deprecate
251
- warn("Nokogiri::HTML5.get is deprecated and will be removed in a future version of Nokogiri.",
252
- uplevel: 1, category: :deprecated)
251
+ warn(
252
+ "Nokogiri::HTML5.get is deprecated and will be removed in a future version of Nokogiri.",
253
+ uplevel: 1,
254
+ category: :deprecated,
255
+ )
253
256
  get_impl(uri, options)
254
257
  end
255
258
 
@@ -2,26 +2,26 @@
2
2
  begin
3
3
  require 'jar_dependencies'
4
4
  rescue LoadError
5
- require 'xalan/xalan/2.7.2/xalan-2.7.2.jar'
5
+ require 'xalan/serializer/2.7.3/serializer-2.7.3.jar'
6
6
  require 'net/sourceforge/htmlunit/neko-htmlunit/2.63.0/neko-htmlunit-2.63.0.jar'
7
7
  require 'nu/validator/jing/20200702VNU/jing-20200702VNU.jar'
8
8
  require 'xerces/xercesImpl/2.12.2/xercesImpl-2.12.2.jar'
9
9
  require 'org/nokogiri/nekodtd/0.1.11.noko1/nekodtd-0.1.11.noko1.jar'
10
10
  require 'net/sf/saxon/Saxon-HE/9.6.0-4/Saxon-HE-9.6.0-4.jar'
11
+ require 'xalan/xalan/2.7.3/xalan-2.7.3.jar'
11
12
  require 'xml-apis/xml-apis/1.4.01/xml-apis-1.4.01.jar'
12
- require 'xalan/serializer/2.7.2/serializer-2.7.2.jar'
13
13
  require 'isorelax/isorelax/20030108/isorelax-20030108.jar'
14
14
  end
15
15
 
16
16
  if defined? Jars
17
- require_jar 'xalan', 'xalan', '2.7.2'
17
+ require_jar 'xalan', 'serializer', '2.7.3'
18
18
  require_jar 'net.sourceforge.htmlunit', 'neko-htmlunit', '2.63.0'
19
19
  require_jar 'nu.validator', 'jing', '20200702VNU'
20
20
  require_jar 'xerces', 'xercesImpl', '2.12.2'
21
21
  require_jar 'org.nokogiri', 'nekodtd', '0.1.11.noko1'
22
22
  require_jar 'net.sf.saxon', 'Saxon-HE', '9.6.0-4'
23
+ require_jar 'xalan', 'xalan', '2.7.3'
23
24
  require_jar 'xml-apis', 'xml-apis', '1.4.01'
24
- require_jar 'xalan', 'serializer', '2.7.2'
25
25
  require_jar 'isorelax', 'isorelax', '20030108'
26
26
  end
27
27
 
@@ -33,8 +33,8 @@ module Nokogiri
33
33
  "net.sourceforge.htmlunit:neko-htmlunit" => "2.63.0",
34
34
  "nu.validator:jing" => "20200702VNU",
35
35
  "org.nokogiri:nekodtd" => "0.1.11.noko1",
36
- "xalan:serializer" => "2.7.2",
37
- "xalan:xalan" => "2.7.2",
36
+ "xalan:serializer" => "2.7.3",
37
+ "xalan:xalan" => "2.7.3",
38
38
  "xerces:xercesImpl" => "2.12.2",
39
39
  "xml-apis:xml-apis" => "1.4.01",
40
40
  }.freeze
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nokogiri
4
4
  # The version of Nokogiri you are using
5
- VERSION = "1.14.3"
5
+ VERSION = "1.15.0"
6
6
  end
@@ -12,8 +12,10 @@ module Nokogiri
12
12
  undef_method :namespace_definitions
13
13
  undef_method :line if method_defined?(:line)
14
14
 
15
- def inspect
16
- "#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
15
+ private
16
+
17
+ def inspect_attributes
18
+ [:to_s]
17
19
  end
18
20
  end
19
21
  end
@@ -16,7 +16,7 @@ module Nokogiri
16
16
  # If +ctx+ is present, it is used as a context node for the
17
17
  # subtree created, e.g., namespaces will be resolved relative
18
18
  # to +ctx+.
19
- def initialize(document, tags = nil, ctx = nil, options = ParseOptions::DEFAULT_XML)
19
+ def initialize(document, tags = nil, ctx = nil, options = ParseOptions::DEFAULT_XML) # rubocop:disable Lint/MissingSuper
20
20
  return self unless tags
21
21
 
22
22
  options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
@@ -11,9 +11,11 @@ module Nokogiri
11
11
  # ]>
12
12
  # </root>
13
13
  #
14
- # ElementContent represents the tree inside the <!ELEMENT> tag shown above
15
- # that lists the possible content for the div1 tag.
14
+ # ElementContent represents the binary tree inside the <!ELEMENT> tag shown above that lists the
15
+ # possible content for the div1 tag.
16
16
  class ElementContent
17
+ include Nokogiri::XML::PP::Node
18
+
17
19
  # Possible definitions of type
18
20
  PCDATA = 1
19
21
  ELEMENT = 2
@@ -33,6 +35,12 @@ module Nokogiri
33
35
  def children
34
36
  [c1, c2].compact
35
37
  end
38
+
39
+ private
40
+
41
+ def inspect_attributes
42
+ [:prefix, :name, :type, :occur, :children]
43
+ end
36
44
  end
37
45
  end
38
46
  end
@@ -7,8 +7,10 @@ module Nokogiri
7
7
  undef_method :namespace_definitions
8
8
  undef_method :line if method_defined?(:line)
9
9
 
10
- def inspect
11
- "#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
10
+ private
11
+
12
+ def inspect_attributes
13
+ [:to_s]
12
14
  end
13
15
  end
14
16
  end
@@ -13,8 +13,10 @@ module Nokogiri
13
13
  doc.create_entity(name, *args)
14
14
  end
15
15
 
16
- def inspect
17
- "#<#{self.class.name}:#{format("0x%x", object_id)} #{to_s.inspect}>"
16
+ private
17
+
18
+ def inspect_attributes
19
+ [:to_s]
18
20
  end
19
21
  end
20
22
  end
@@ -62,6 +62,14 @@ module Nokogiri
62
62
  end
63
63
 
64
64
  alias_method :to_i, :options
65
+
66
+ def inspect
67
+ options = []
68
+ self.class.constants.each do |k|
69
+ options << k.downcase if send(:"#{k.downcase}?")
70
+ end
71
+ super.sub(/>$/, " " + options.join(", ") + ">")
72
+ end
65
73
  end
66
74
  end
67
75
  end
@@ -1269,11 +1269,11 @@ module Nokogiri
1269
1269
  #
1270
1270
  # These two statements are equivalent:
1271
1271
  #
1272
- # node.serialize(:encoding => 'UTF-8', :save_with => FORMAT | AS_XML)
1272
+ # node.serialize(encoding: 'UTF-8', save_with: FORMAT | AS_XML)
1273
1273
  #
1274
1274
  # or
1275
1275
  #
1276
- # node.serialize(:encoding => 'UTF-8') do |config|
1276
+ # node.serialize(encoding: 'UTF-8') do |config|
1277
1277
  # config.format.as_xml
1278
1278
  # end
1279
1279
  #
@@ -1310,7 +1310,7 @@ module Nokogiri
1310
1310
  ###
1311
1311
  # Serialize this Node to XML using +options+
1312
1312
  #
1313
- # doc.to_xml(:indent => 5, :encoding => 'UTF-8')
1313
+ # doc.to_xml(indent: 5, encoding: 'UTF-8')
1314
1314
  #
1315
1315
  # See Node#write_to for a list of +options+
1316
1316
  def to_xml(options = {})
@@ -1321,7 +1321,7 @@ module Nokogiri
1321
1321
  ###
1322
1322
  # Serialize this Node to XHTML using +options+
1323
1323
  #
1324
- # doc.to_xhtml(:indent => 5, :encoding => 'UTF-8')
1324
+ # doc.to_xhtml(indent: 5, encoding: 'UTF-8')
1325
1325
  #
1326
1326
  # See Node#write_to for a list of +options+
1327
1327
  def to_xhtml(options = {})
@@ -1329,25 +1329,32 @@ module Nokogiri
1329
1329
  end
1330
1330
 
1331
1331
  ###
1332
- # Write Node to +io+ with +options+. +options+ modify the output of
1333
- # this method. Valid options are:
1332
+ # :call-seq:
1333
+ # write_to(io, *options)
1334
+ #
1335
+ # Serialize this node or document to +io+.
1334
1336
  #
1335
- # * +:encoding+ for changing the encoding
1336
- # * +:indent_text+ the indentation text, defaults to one space
1337
- # * +:indent+ the number of +:indent_text+ to use, defaults to 2
1338
- # * +:save_with+ a combination of SaveOptions constants.
1337
+ # [Parameters]
1338
+ # - +io+ (IO) An IO-like object to which the serialized content will be written.
1339
+ # - +options+ (Hash) See below
1340
+ #
1341
+ # [Options]
1342
+ # * +:encoding+ (String or Encoding) specify the encoding of the output (defaults to document encoding)
1343
+ # * +:indent_text+ (String) the indentation text (defaults to <code>" "</code>)
1344
+ # * +:indent+ (Integer) the number of +:indent_text+ to use (defaults to +2+)
1345
+ # * +:save_with+ (Integer) a combination of SaveOptions constants
1339
1346
  #
1340
1347
  # To save with UTF-8 indented twice:
1341
1348
  #
1342
- # node.write_to(io, :encoding => 'UTF-8', :indent => 2)
1349
+ # node.write_to(io, encoding: 'UTF-8', indent: 2)
1343
1350
  #
1344
1351
  # To save indented with two dashes:
1345
1352
  #
1346
- # node.write_to(io, :indent_text => '-', :indent => 2)
1353
+ # node.write_to(io, indent_text: '-', indent: 2)
1347
1354
  #
1348
1355
  def write_to(io, *options)
1349
1356
  options = options.first.is_a?(Hash) ? options.shift : {}
1350
- encoding = options[:encoding] || options[0]
1357
+ encoding = options[:encoding] || options[0] || document.encoding
1351
1358
  if Nokogiri.jruby?
1352
1359
  save_options = options[:save_with] || options[1]
1353
1360
  indent_times = options[:indent] || 0
@@ -1365,6 +1372,8 @@ module Nokogiri
1365
1372
  config = SaveOptions.new(save_options.to_i)
1366
1373
  yield config if block_given?
1367
1374
 
1375
+ encoding = encoding.is_a?(Encoding) ? encoding.name : encoding
1376
+
1368
1377
  native_write_to(io, encoding, indentation, config.options)
1369
1378
  end
1370
1379
 
@@ -13,9 +13,14 @@ module Nokogiri
13
13
  !attribute || (attribute.respond_to?(:empty?) && attribute.empty?)
14
14
  rescue NoMethodError
15
15
  true
16
- end.map do |attribute|
17
- "#{attribute.to_s.sub(/_\w+/, "s")}=#{send(attribute).inspect}"
18
- end.join(" ")
16
+ end
17
+ attributes = if inspect_attributes.length == 1
18
+ send(attributes.first).inspect
19
+ else
20
+ attributes.map do |attribute|
21
+ "#{attribute}=#{send(attribute).inspect}"
22
+ end.join(" ")
23
+ end
19
24
  "#<#{self.class.name}:#{format("0x%x", object_id)} #{attributes}>"
20
25
  end
21
26
 
@@ -23,6 +28,7 @@ module Nokogiri
23
28
  nice_name = self.class.name.split("::").last
24
29
  pp.group(2, "#(#{nice_name}:#{format("0x%x", object_id)} {", "})") do
25
30
  pp.breakable
31
+
26
32
  attrs = inspect_attributes.filter_map do |t|
27
33
  [t, send(t)] if respond_to?(t)
28
34
  end.find_all do |x|
@@ -35,19 +41,24 @@ module Nokogiri
35
41
  end
36
42
  end
37
43
 
38
- pp.seplist(attrs) do |v|
39
- if COLLECTIONS.include?(v.first)
40
- pp.group(2, "#{v.first.to_s.sub(/_\w+$/, "s")} = [", "]") do
41
- pp.breakable
42
- pp.seplist(v.last) do |item|
43
- pp.pp(item)
44
+ if inspect_attributes.length == 1
45
+ pp.pp(attrs.first.last)
46
+ else
47
+ pp.seplist(attrs) do |v|
48
+ if COLLECTIONS.include?(v.first)
49
+ pp.group(2, "#{v.first} = [", "]") do
50
+ pp.breakable
51
+ pp.seplist(v.last) do |item|
52
+ pp.pp(item)
53
+ end
44
54
  end
55
+ else
56
+ pp.text("#{v.first} = ")
57
+ pp.pp(v.last)
45
58
  end
46
- else
47
- pp.text("#{v.first} = ")
48
- pp.pp(v.last)
49
59
  end
50
60
  end
61
+
51
62
  pp.breakable
52
63
  end
53
64
  end
@@ -100,7 +100,7 @@ module Nokogiri
100
100
  # +prefix+ is the namespace prefix for the element
101
101
  # +uri+ is the associated namespace URI
102
102
  # +ns+ is a hash of namespace prefix:urls associated with the element
103
- def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
103
+ def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = []) # rubocop:disable Metrics/ParameterLists
104
104
  ###
105
105
  # Deal with SAX v1 interface
106
106
  name = [prefix, name].compact.join(":")
@@ -36,16 +36,19 @@ module Nokogiri
36
36
  # node.search('.//address[@domestic=$value]', nil, {:value => 'Yes'})
37
37
  #
38
38
  # 💡 Custom XPath functions and CSS pseudo-selectors may also be defined. To define custom
39
- # functions create a class and implement the function you want to define. The first argument
40
- # to the method will be the current matching NodeSet. Any other arguments are ones that you
41
- # pass in. Note that this class may appear anywhere in the argument list. For example:
39
+ # functions create a class and implement the function you want to define, which will be in the
40
+ # `nokogiri` namespace in XPath queries.
41
+ #
42
+ # The first argument to the method will be the current matching NodeSet. Any other arguments
43
+ # are ones that you pass in. Note that this class may appear anywhere in the argument
44
+ # list. For example:
42
45
  #
43
46
  # handler = Class.new {
44
47
  # def regex node_set, regex
45
48
  # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
46
49
  # end
47
50
  # }.new
48
- # node.search('.//title[regex(., "\w+")]', 'div.employee:regex("[0-9]+")', handler)
51
+ # node.search('.//title[nokogiri:regex(., "\w+")]', 'div.employee:regex("[0-9]+")', handler)
49
52
  #
50
53
  # See Searchable#xpath and Searchable#css for further usage help.
51
54
  def search(*args)
@@ -160,16 +163,18 @@ module Nokogiri
160
163
  # node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})
161
164
  #
162
165
  # 💡 Custom XPath functions may also be defined. To define custom functions create a class and
163
- # implement the function you want to define. The first argument to the method will be the
164
- # current matching NodeSet. Any other arguments are ones that you pass in. Note that this
165
- # class may appear anywhere in the argument list. For example:
166
+ # implement the function you want to define, which will be in the `nokogiri` namespace.
167
+ #
168
+ # The first argument to the method will be the current matching NodeSet. Any other arguments
169
+ # are ones that you pass in. Note that this class may appear anywhere in the argument
170
+ # list. For example:
166
171
  #
167
172
  # handler = Class.new {
168
173
  # def regex(node_set, regex)
169
174
  # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
170
175
  # end
171
176
  # }.new
172
- # node.xpath('.//title[regex(., "\w+")]', handler)
177
+ # node.xpath('.//title[nokogiri:regex(., "\w+")]', handler)
173
178
  #
174
179
  def xpath(*args)
175
180
  paths, handler, ns, binds = extract_params(args)
@@ -243,8 +248,11 @@ module Nokogiri
243
248
  doctype: document.xpath_doctype,
244
249
  )
245
250
  self.class::IMPLIED_XPATH_CONTEXTS.map do |implied_xpath_context|
246
- CSS.xpath_for(rule.to_s, { prefix: implied_xpath_context, ns: ns,
247
- visitor: visitor, })
251
+ CSS.xpath_for(rule.to_s, {
252
+ prefix: implied_xpath_context,
253
+ ns: ns,
254
+ visitor: visitor,
255
+ })
248
256
  end.join(" | ")
249
257
  end
250
258
 
data/lib/nokogiri/xslt.rb CHANGED
@@ -20,8 +20,59 @@ module Nokogiri
20
20
  # Stylesheet object.
21
21
  module XSLT
22
22
  class << self
23
- ###
24
- # Parse the stylesheet in +string+, register any +modules+
23
+ # :call-seq:
24
+ # parse(xsl) Nokogiri::XSLT::Stylesheet
25
+ # parse(xsl, modules) → Nokogiri::XSLT::Stylesheet
26
+ #
27
+ # Parse the stylesheet in +xsl+, registering optional +modules+ as custom class handlers.
28
+ #
29
+ # [Parameters]
30
+ # - +xsl+ (String) XSL content to be parsed into a stylesheet
31
+ # - +modules+ (Hash<String ⇒ Class>) A hash of URI-to-handler relations for linking a
32
+ # namespace to a custom function handler.
33
+ #
34
+ # ⚠ The XSLT handler classes are registered *globally*.
35
+ #
36
+ # Also see Nokogiri::XSLT.register
37
+ #
38
+ # *Example*
39
+ #
40
+ # xml = Nokogiri.XML(<<~XML)
41
+ # <nodes>
42
+ # <node>Foo</node>
43
+ # <node>Bar</node>
44
+ # </nodes>
45
+ # XML
46
+ #
47
+ # handler = Class.new do
48
+ # def reverse(node)
49
+ # node.text.reverse
50
+ # end
51
+ # end
52
+ #
53
+ # xsl = <<~XSL
54
+ # <xsl:stylesheet version="1.0"
55
+ # xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
56
+ # xmlns:myfuncs="http://nokogiri.org/xslt/myfuncs"
57
+ # extension-element-prefixes="myfuncs">
58
+ # <xsl:template match="/">
59
+ # <reversed>
60
+ # <xsl:for-each select="nodes/node">
61
+ # <reverse><xsl:copy-of select="myfuncs:reverse(.)"/></reverse>
62
+ # </xsl:for-each>
63
+ # </reversed>
64
+ # </xsl:template>
65
+ # </xsl:stylesheet>
66
+ # XSL
67
+ #
68
+ # xsl = Nokogiri.XSLT(xsl, "http://nokogiri.org/xslt/myfuncs" => handler)
69
+ # xsl.transform(xml).to_xml
70
+ # # => "<?xml version=\"1.0\"?>\n" +
71
+ # # "<reversed>\n" +
72
+ # # " <reverse>ooF</reverse>\n" +
73
+ # # " <reverse>raB</reverse>\n" +
74
+ # # "</reversed>\n"
75
+ #
25
76
  def parse(string, modules = {})
26
77
  modules.each do |url, klass|
27
78
  XSLT.register(url, klass)
@@ -49,7 +100,7 @@ module Nokogiri
49
100
  def quote_params(params)
50
101
  params.flatten.each_slice(2).with_object([]) do |kv, quoted_params|
51
102
  key, value = kv.map(&:to_s)
52
- value = if /'/.match?(value)
103
+ value = if value.include?("'")
53
104
  "concat('#{value.gsub(/'/, %q{', "'", '})}')"
54
105
  else
55
106
  "'#{value}'"
@@ -58,6 +109,25 @@ module Nokogiri
58
109
  quoted_params << value
59
110
  end
60
111
  end
112
+
113
+ # call-seq:
114
+ # register(uri, custom_handler_class)
115
+ #
116
+ # Register a class that implements custom XSLT transformation functions.
117
+ #
118
+ # ⚠ The XSLT handler classes are registered *globally*.
119
+ #
120
+ # [Parameters}
121
+ # - +uri+ (String) The namespace for the custom handlers
122
+ # - +custom_handler_class+ (Class) A class with ruby methods that can be called during
123
+ # transformation
124
+ #
125
+ # See Nokogiri::XSLT.parse for usage.
126
+ #
127
+ def register(uri, custom_handler_class)
128
+ # NOTE: this is implemented in the C extension, see ext/nokogiri/xslt_stylesheet.c
129
+ raise NotImplementedError, "Nokogiri::XSLT.register is not implemented on JRuby"
130
+ end if Nokogiri.jruby?
61
131
  end
62
132
  end
63
133
  end
data/lib/nokogiri.rb CHANGED
@@ -45,11 +45,19 @@ module Nokogiri
45
45
  # Expect an HTML indicator to appear within the first 512
46
46
  # characters of a document. (<?xml ?> + <?xml-stylesheet ?>
47
47
  # shouldn't be that long)
48
- Nokogiri.HTML4(string, url, encoding,
49
- options || XML::ParseOptions::DEFAULT_HTML)
48
+ Nokogiri.HTML4(
49
+ string,
50
+ url,
51
+ encoding,
52
+ options || XML::ParseOptions::DEFAULT_HTML,
53
+ )
50
54
  else
51
- Nokogiri.XML(string, url, encoding,
52
- options || XML::ParseOptions::DEFAULT_XML)
55
+ Nokogiri.XML(
56
+ string,
57
+ url,
58
+ encoding,
59
+ options || XML::ParseOptions::DEFAULT_XML,
60
+ )
53
61
  end.tap do |doc|
54
62
  yield doc if block_given?
55
63
  end
@@ -71,7 +71,7 @@ module XSD
71
71
  # +prefix+ is the namespace prefix for the element
72
72
  # +uri+ is the associated namespace URI
73
73
  # +ns+ is a hash of namespace prefix:urls associated with the element
74
- def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
74
+ def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = []) # rubocop:disable Metrics/ParameterLists
75
75
  ###
76
76
  # Deal with SAX v1 interface
77
77
  name = [prefix, name].compact.join(":")