nokogiri 1.14.5 → 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.
- checksums.yaml +4 -4
- data/Gemfile +9 -8
- data/dependencies.yml +6 -6
- data/ext/nokogiri/extconf.rb +66 -22
- data/ext/nokogiri/html4_document.c +1 -2
- data/ext/nokogiri/html4_element_description.c +19 -14
- data/ext/nokogiri/html4_sax_parser_context.c +10 -16
- data/ext/nokogiri/html4_sax_push_parser.c +2 -2
- data/ext/nokogiri/nokogiri.c +46 -24
- data/ext/nokogiri/nokogiri.h +13 -2
- data/ext/nokogiri/xml_attr.c +1 -1
- data/ext/nokogiri/xml_cdata.c +10 -2
- data/ext/nokogiri/xml_comment.c +1 -1
- data/ext/nokogiri/xml_document.c +102 -22
- data/ext/nokogiri/xml_document_fragment.c +1 -1
- data/ext/nokogiri/xml_dtd.c +1 -1
- data/ext/nokogiri/xml_element_content.c +32 -29
- data/ext/nokogiri/xml_element_decl.c +5 -5
- data/ext/nokogiri/xml_encoding_handler.c +12 -4
- data/ext/nokogiri/xml_entity_reference.c +1 -1
- data/ext/nokogiri/xml_namespace.c +11 -12
- data/ext/nokogiri/xml_node.c +7 -7
- data/ext/nokogiri/xml_node_set.c +125 -105
- data/ext/nokogiri/xml_processing_instruction.c +1 -1
- data/ext/nokogiri/xml_reader.c +37 -28
- data/ext/nokogiri/xml_relax_ng.c +65 -78
- data/ext/nokogiri/xml_sax_parser.c +24 -5
- data/ext/nokogiri/xml_sax_parser_context.c +46 -25
- data/ext/nokogiri/xml_sax_push_parser.c +29 -8
- data/ext/nokogiri/xml_schema.c +90 -116
- data/ext/nokogiri/xml_text.c +10 -2
- data/ext/nokogiri/xml_xpath_context.c +156 -83
- data/ext/nokogiri/xslt_stylesheet.c +103 -50
- data/gumbo-parser/src/error.c +8 -4
- data/gumbo-parser/src/foreign_attrs.c +13 -14
- data/gumbo-parser/src/foreign_attrs.gperf +1 -1
- data/gumbo-parser/src/parser.c +13 -0
- data/lib/nokogiri/css/xpath_visitor.rb +2 -2
- data/lib/nokogiri/extension.rb +1 -1
- data/lib/nokogiri/html4/document_fragment.rb +1 -1
- data/lib/nokogiri/html4/element_description_defaults.rb +1821 -353
- data/lib/nokogiri/html5/document_fragment.rb +1 -1
- data/lib/nokogiri/html5/node.rb +5 -0
- data/lib/nokogiri/html5.rb +5 -2
- data/lib/nokogiri/jruby/nokogiri_jars.rb +3 -3
- data/lib/nokogiri/version/constant.rb +1 -1
- data/lib/nokogiri/xml/attribute_decl.rb +4 -2
- data/lib/nokogiri/xml/document_fragment.rb +1 -1
- data/lib/nokogiri/xml/element_content.rb +10 -2
- data/lib/nokogiri/xml/element_decl.rb +4 -2
- data/lib/nokogiri/xml/entity_decl.rb +4 -2
- data/lib/nokogiri/xml/node/save_options.rb +8 -0
- data/lib/nokogiri/xml/node.rb +22 -13
- data/lib/nokogiri/xml/pp/node.rb +23 -12
- data/lib/nokogiri/xml/sax/document.rb +1 -1
- data/lib/nokogiri/xml/searchable.rb +18 -10
- data/lib/nokogiri/xslt.rb +73 -3
- data/lib/nokogiri.rb +12 -4
- data/lib/xsd/xmlparser/nokogiri.rb +1 -1
- data/patches/libxml2/0010-update-config.guess-and-config.sub-for-libxml2.patch +224 -0
- data/patches/libxml2/0011-rip-out-libxml2-s-libc_single_threaded-support.patch +30 -0
- data/patches/libxslt/0001-update-config.guess-and-config.sub-for-libxslt.patch +224 -0
- data/ports/archives/libxml2-2.11.3.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.38.tar.xz +0 -0
- metadata +9 -7
- data/patches/libxslt/0001-update-automake-files-for-arm64.patch +0 -3037
- data/ports/archives/libxml2-2.10.4.tar.xz +0 -0
- 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
|
data/lib/nokogiri/html5/node.rb
CHANGED
@@ -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.
|
data/lib/nokogiri/html5.rb
CHANGED
@@ -248,8 +248,11 @@ module Nokogiri
|
|
248
248
|
# * :basic_auth => [username, password]
|
249
249
|
def get(uri, options = {})
|
250
250
|
# TODO: deprecate
|
251
|
-
warn(
|
252
|
-
|
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
|
|
@@ -6,10 +6,10 @@ rescue LoadError
|
|
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
|
+
require 'org/nokogiri/nekodtd/0.1.11.noko1/nekodtd-0.1.11.noko1.jar'
|
9
10
|
require 'net/sf/saxon/Saxon-HE/9.6.0-4/Saxon-HE-9.6.0-4.jar'
|
10
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 'org/nokogiri/nekodtd/0.1.11.noko2/nekodtd-0.1.11.noko2.jar'
|
13
13
|
require 'isorelax/isorelax/20030108/isorelax-20030108.jar'
|
14
14
|
end
|
15
15
|
|
@@ -18,10 +18,10 @@ if defined? Jars
|
|
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
|
+
require_jar 'org.nokogiri', 'nekodtd', '0.1.11.noko1'
|
21
22
|
require_jar 'net.sf.saxon', 'Saxon-HE', '9.6.0-4'
|
22
23
|
require_jar 'xalan', 'xalan', '2.7.3'
|
23
24
|
require_jar 'xml-apis', 'xml-apis', '1.4.01'
|
24
|
-
require_jar 'org.nokogiri', 'nekodtd', '0.1.11.noko2'
|
25
25
|
require_jar 'isorelax', 'isorelax', '20030108'
|
26
26
|
end
|
27
27
|
|
@@ -32,7 +32,7 @@ module Nokogiri
|
|
32
32
|
"net.sf.saxon:Saxon-HE" => "9.6.0-4",
|
33
33
|
"net.sourceforge.htmlunit:neko-htmlunit" => "2.63.0",
|
34
34
|
"nu.validator:jing" => "20200702VNU",
|
35
|
-
"org.nokogiri:nekodtd" => "0.1.11.
|
35
|
+
"org.nokogiri:nekodtd" => "0.1.11.noko1",
|
36
36
|
"xalan:serializer" => "2.7.3",
|
37
37
|
"xalan:xalan" => "2.7.3",
|
38
38
|
"xerces:xercesImpl" => "2.12.2",
|
@@ -12,8 +12,10 @@ module Nokogiri
|
|
12
12
|
undef_method :namespace_definitions
|
13
13
|
undef_method :line if method_defined?(:line)
|
14
14
|
|
15
|
-
|
16
|
-
|
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
|
-
#
|
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
|
-
|
11
|
-
|
10
|
+
private
|
11
|
+
|
12
|
+
def inspect_attributes
|
13
|
+
[:to_s]
|
12
14
|
end
|
13
15
|
end
|
14
16
|
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
|
data/lib/nokogiri/xml/node.rb
CHANGED
@@ -1269,11 +1269,11 @@ module Nokogiri
|
|
1269
1269
|
#
|
1270
1270
|
# These two statements are equivalent:
|
1271
1271
|
#
|
1272
|
-
#
|
1272
|
+
# node.serialize(encoding: 'UTF-8', save_with: FORMAT | AS_XML)
|
1273
1273
|
#
|
1274
1274
|
# or
|
1275
1275
|
#
|
1276
|
-
# node.serialize(:
|
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(:
|
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(:
|
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
|
-
#
|
1333
|
-
#
|
1332
|
+
# :call-seq:
|
1333
|
+
# write_to(io, *options)
|
1334
|
+
#
|
1335
|
+
# Serialize this node or document to +io+.
|
1334
1336
|
#
|
1335
|
-
#
|
1336
|
-
#
|
1337
|
-
#
|
1338
|
-
#
|
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, :
|
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, :
|
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
|
|
data/lib/nokogiri/xml/pp/node.rb
CHANGED
@@ -13,9 +13,14 @@ module Nokogiri
|
|
13
13
|
!attribute || (attribute.respond_to?(:empty?) && attribute.empty?)
|
14
14
|
rescue NoMethodError
|
15
15
|
true
|
16
|
-
end
|
17
|
-
|
18
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
40
|
-
#
|
41
|
-
#
|
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
|
164
|
-
#
|
165
|
-
#
|
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, {
|
247
|
-
|
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
|
-
#
|
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
|
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(
|
49
|
-
|
48
|
+
Nokogiri.HTML4(
|
49
|
+
string,
|
50
|
+
url,
|
51
|
+
encoding,
|
52
|
+
options || XML::ParseOptions::DEFAULT_HTML,
|
53
|
+
)
|
50
54
|
else
|
51
|
-
Nokogiri.XML(
|
52
|
-
|
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(":")
|