nokogiri 1.16.8 → 1.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +11 -21
  3. data/README.md +4 -0
  4. data/dependencies.yml +6 -6
  5. data/ext/nokogiri/extconf.rb +191 -137
  6. data/ext/nokogiri/gumbo.c +69 -53
  7. data/ext/nokogiri/html4_document.c +10 -4
  8. data/ext/nokogiri/html4_element_description.c +18 -18
  9. data/ext/nokogiri/html4_sax_parser.c +40 -0
  10. data/ext/nokogiri/html4_sax_parser_context.c +48 -58
  11. data/ext/nokogiri/html4_sax_push_parser.c +25 -24
  12. data/ext/nokogiri/libxml2_polyfill.c +114 -0
  13. data/ext/nokogiri/nokogiri.c +9 -2
  14. data/ext/nokogiri/nokogiri.h +18 -33
  15. data/ext/nokogiri/xml_attr.c +1 -1
  16. data/ext/nokogiri/xml_cdata.c +2 -10
  17. data/ext/nokogiri/xml_comment.c +3 -8
  18. data/ext/nokogiri/xml_document.c +163 -156
  19. data/ext/nokogiri/xml_document_fragment.c +10 -25
  20. data/ext/nokogiri/xml_dtd.c +1 -1
  21. data/ext/nokogiri/xml_element_content.c +9 -9
  22. data/ext/nokogiri/xml_encoding_handler.c +4 -4
  23. data/ext/nokogiri/xml_namespace.c +6 -6
  24. data/ext/nokogiri/xml_node.c +134 -103
  25. data/ext/nokogiri/xml_node_set.c +46 -44
  26. data/ext/nokogiri/xml_reader.c +54 -58
  27. data/ext/nokogiri/xml_relax_ng.c +35 -56
  28. data/ext/nokogiri/xml_sax_parser.c +156 -88
  29. data/ext/nokogiri/xml_sax_parser_context.c +213 -131
  30. data/ext/nokogiri/xml_sax_push_parser.c +68 -49
  31. data/ext/nokogiri/xml_schema.c +50 -85
  32. data/ext/nokogiri/xml_syntax_error.c +19 -11
  33. data/ext/nokogiri/xml_text.c +2 -4
  34. data/ext/nokogiri/xml_xpath_context.c +2 -2
  35. data/ext/nokogiri/xslt_stylesheet.c +8 -8
  36. data/gumbo-parser/src/error.c +76 -48
  37. data/gumbo-parser/src/error.h +5 -1
  38. data/gumbo-parser/src/nokogiri_gumbo.h +11 -2
  39. data/gumbo-parser/src/parser.c +61 -23
  40. data/gumbo-parser/src/tokenizer.c +6 -6
  41. data/lib/nokogiri/class_resolver.rb +1 -1
  42. data/lib/nokogiri/css/node.rb +6 -2
  43. data/lib/nokogiri/css/parser.rb +6 -4
  44. data/lib/nokogiri/css/parser.y +2 -2
  45. data/lib/nokogiri/css/parser_extras.rb +6 -66
  46. data/lib/nokogiri/css/selector_cache.rb +38 -0
  47. data/lib/nokogiri/css/tokenizer.rb +4 -4
  48. data/lib/nokogiri/css/tokenizer.rex +9 -8
  49. data/lib/nokogiri/css/xpath_visitor.rb +42 -6
  50. data/lib/nokogiri/css.rb +86 -20
  51. data/lib/nokogiri/decorators/slop.rb +3 -5
  52. data/lib/nokogiri/encoding_handler.rb +2 -2
  53. data/lib/nokogiri/html4/document.rb +44 -23
  54. data/lib/nokogiri/html4/document_fragment.rb +124 -12
  55. data/lib/nokogiri/html4/encoding_reader.rb +1 -1
  56. data/lib/nokogiri/html4/sax/parser.rb +23 -38
  57. data/lib/nokogiri/html4/sax/parser_context.rb +4 -9
  58. data/lib/nokogiri/html4.rb +9 -14
  59. data/lib/nokogiri/html5/builder.rb +40 -0
  60. data/lib/nokogiri/html5/document.rb +61 -30
  61. data/lib/nokogiri/html5/document_fragment.rb +130 -20
  62. data/lib/nokogiri/html5/node.rb +4 -4
  63. data/lib/nokogiri/html5.rb +114 -72
  64. data/lib/nokogiri/version/constant.rb +1 -1
  65. data/lib/nokogiri/xml/builder.rb +8 -1
  66. data/lib/nokogiri/xml/document.rb +70 -26
  67. data/lib/nokogiri/xml/document_fragment.rb +84 -13
  68. data/lib/nokogiri/xml/node.rb +82 -11
  69. data/lib/nokogiri/xml/node_set.rb +9 -7
  70. data/lib/nokogiri/xml/parse_options.rb +1 -1
  71. data/lib/nokogiri/xml/pp/node.rb +6 -1
  72. data/lib/nokogiri/xml/reader.rb +46 -13
  73. data/lib/nokogiri/xml/relax_ng.rb +57 -20
  74. data/lib/nokogiri/xml/sax/document.rb +174 -83
  75. data/lib/nokogiri/xml/sax/parser.rb +115 -41
  76. data/lib/nokogiri/xml/sax/parser_context.rb +116 -8
  77. data/lib/nokogiri/xml/sax/push_parser.rb +3 -0
  78. data/lib/nokogiri/xml/sax.rb +48 -0
  79. data/lib/nokogiri/xml/schema.rb +112 -45
  80. data/lib/nokogiri/xml/searchable.rb +6 -8
  81. data/lib/nokogiri/xml/syntax_error.rb +22 -0
  82. data/lib/nokogiri/xml.rb +13 -24
  83. data/lib/nokogiri/xslt.rb +3 -9
  84. data/lib/xsd/xmlparser/nokogiri.rb +3 -4
  85. data/ports/archives/libxml2-2.13.5.tar.xz +0 -0
  86. data/ports/archives/libxslt-1.1.42.tar.xz +0 -0
  87. metadata +10 -7
  88. data/ext/nokogiri/libxml2_backwards_compat.c +0 -121
  89. data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +0 -25
  90. data/ports/archives/libxml2-2.12.9.tar.xz +0 -0
  91. data/ports/archives/libxslt-1.1.39.tar.xz +0 -0
@@ -127,6 +127,42 @@ module Nokogiri
127
127
  # This is intentionally empty, and sets the method signature for subclasses.
128
128
  end
129
129
 
130
+ #
131
+ # :call-seq:
132
+ # dup → Nokogiri::XML::Node
133
+ # dup(level) → Nokogiri::XML::Node
134
+ # dup(level, new_parent_doc) → Nokogiri::XML::Node
135
+ #
136
+ # Duplicate this node.
137
+ #
138
+ # [Parameters]
139
+ # - +level+ (optional Integer). 0 is a shallow copy, 1 (the default) is a deep copy.
140
+ # - +new_parent_doc+ (optional Nokogiri::XML::Document)
141
+ # The new node's parent Document. Defaults to the the Document of the current node.
142
+ # [Returns] The new Nokogiri::XML::Node
143
+ #
144
+ def dup(level = 1, new_parent_doc = document)
145
+ super().initialize_copy_with_args(self, level, new_parent_doc)
146
+ end
147
+
148
+ #
149
+ # :call-seq:
150
+ # clone → Nokogiri::XML::Node
151
+ # clone(level) → Nokogiri::XML::Node
152
+ # clone(level, new_parent_doc) → Nokogiri::XML::Node
153
+ #
154
+ # Clone this node.
155
+ #
156
+ # [Parameters]
157
+ # - +level+ (optional Integer). 0 is a shallow copy, 1 (the default) is a deep copy.
158
+ # - +new_parent_doc+
159
+ # The new node's parent Document. Defaults to the the Document of the current node.
160
+ # [Returns] The new Nokogiri::XML::Node
161
+ #
162
+ def clone(level = 1, new_parent_doc = document)
163
+ super().initialize_copy_with_args(self, level, new_parent_doc)
164
+ end
165
+
130
166
  ###
131
167
  # Decorate this node with the decorators set up in this node's Document
132
168
  def decorate!
@@ -228,7 +264,7 @@ module Nokogiri
228
264
  if new_parent.nil?
229
265
  raise "Failed to parse '#{node_or_tags}' in the context of a '#{context_node.name}' element"
230
266
  end
231
- when XML::Node
267
+ when Node
232
268
  new_parent = node_or_tags.dup
233
269
  else
234
270
  raise ArgumentError, "Requires a String or Node argument, and cannot accept a #{node_or_tags.class}"
@@ -406,8 +442,48 @@ module Nokogiri
406
442
  end
407
443
 
408
444
  ####
409
- # Set the Node's content to a Text node containing +string+. The string gets XML escaped, not
410
- # interpreted as markup.
445
+ # call-seq:
446
+ # content=(input)
447
+ #
448
+ # Set the content of this node to +input+.
449
+ #
450
+ # [Parameters]
451
+ # - +input+ (String) The new content for this node. Input is considered to be raw content, and
452
+ # so will be entity-escaped in the final DOM string.
453
+ #
454
+ # [Example]
455
+ # Note how entities are handled:
456
+ #
457
+ # doc = Nokogiri::HTML::Document.parse(<<~HTML)
458
+ # <html>
459
+ # <body>
460
+ # <div id="first">asdf</div>
461
+ # <div id="second">asdf</div>
462
+ # HTML
463
+ #
464
+ # text_node = doc.at_css("div#first").children.first
465
+ # div_node = doc.at_css("div#second")
466
+ #
467
+ # value = "You &amp; Me"
468
+ #
469
+ # text_node.content = value
470
+ # div_node.content = value
471
+ #
472
+ # doc.css("div").to_html
473
+ # # => "<div id=\"first\">You &amp;amp; Me</div>
474
+ # # <div id=\"second\">You &amp;amp; Me</div>"
475
+ #
476
+ # For content that is already entity-escaped, use CGI::unescapeHTML to decode it:
477
+ #
478
+ # text_node.content = CGI::unescapeHTML(value)
479
+ # div_node.content = CGI::unescapeHTML(value)
480
+ #
481
+ # doc.css("div").to_html
482
+ # # => "<div id=\"first\">You &amp; Me</div>
483
+ # # <div id=\"second\">You &amp; Me</div>"
484
+ #
485
+ # See also: #native_content=
486
+ #
411
487
  def content=(string)
412
488
  self.native_content = encode_special_chars(string.to_s)
413
489
  end
@@ -474,7 +550,6 @@ module Nokogiri
474
550
  alias_method :to_str, :content
475
551
  alias_method :name, :node_name
476
552
  alias_method :type, :node_type
477
- alias_method :clone, :dup
478
553
  alias_method :elements, :element_children
479
554
 
480
555
  # :section: Working With Node Attributes
@@ -1051,9 +1126,11 @@ module Nokogiri
1051
1126
 
1052
1127
  error_count = document.errors.length
1053
1128
  node_set = in_context(contents, options.to_i)
1129
+
1054
1130
  if document.errors.length > error_count
1055
1131
  raise document.errors[error_count] unless options.recover?
1056
1132
 
1133
+ # TODO: remove this block when libxml2 < 2.13 is no longer supported
1057
1134
  if node_set.empty?
1058
1135
  # libxml2 < 2.13 does not obey the +recover+ option after encountering errors during
1059
1136
  # +in_context+ parsing, and so this horrible hack is here to try to emulate recovery
@@ -1080,6 +1157,7 @@ module Nokogiri
1080
1157
  node_set = fragment.children
1081
1158
  end
1082
1159
  end
1160
+
1083
1161
  node_set
1084
1162
  end
1085
1163
 
@@ -1542,19 +1620,12 @@ module Nokogiri
1542
1620
  node_or_tags
1543
1621
  end
1544
1622
 
1545
- USING_LIBXML_WITH_BROKEN_SERIALIZATION = Nokogiri.uses_libxml?("~> 2.6.0").freeze
1546
- private_constant :USING_LIBXML_WITH_BROKEN_SERIALIZATION
1547
-
1548
1623
  def to_format(save_option, options)
1549
- return dump_html if USING_LIBXML_WITH_BROKEN_SERIALIZATION
1550
-
1551
1624
  options[:save_with] = save_option unless options[:save_with]
1552
1625
  serialize(options)
1553
1626
  end
1554
1627
 
1555
1628
  def write_format_to(save_option, io, options)
1556
- return (io << dump_html) if USING_LIBXML_WITH_BROKEN_SERIALIZATION
1557
-
1558
1629
  options[:save_with] ||= save_option
1559
1630
  write_to(io, options)
1560
1631
  end
@@ -4,9 +4,13 @@
4
4
  module Nokogiri
5
5
  module XML
6
6
  ####
7
- # A NodeSet contains a list of Nokogiri::XML::Node objects. Typically
8
- # a NodeSet is return as a result of searching a Document via
9
- # Nokogiri::XML::Searchable#css or Nokogiri::XML::Searchable#xpath
7
+ # A NodeSet is an Enumerable that contains a list of Nokogiri::XML::Node objects.
8
+ #
9
+ # Typically a NodeSet is returned as a result of searching a Document via
10
+ # Nokogiri::XML::Searchable#css or Nokogiri::XML::Searchable#xpath.
11
+ #
12
+ # Note that the `#dup` and `#clone` methods perform shallow copies; these methods do not copy
13
+ # the Nodes contained in the NodeSet (similar to how Array and other Enumerable classes work).
10
14
  class NodeSet
11
15
  include Nokogiri::XML::Searchable
12
16
  include Enumerable
@@ -14,8 +18,6 @@ module Nokogiri
14
18
  # The Document this NodeSet is associated with
15
19
  attr_accessor :document
16
20
 
17
- alias_method :clone, :dup
18
-
19
21
  # Create a NodeSet with +document+ defaulting to +list+
20
22
  def initialize(document, list = [])
21
23
  @document = document
@@ -121,7 +123,7 @@ module Nokogiri
121
123
  return self[args.first]
122
124
  end
123
125
 
124
- super(*args)
126
+ super
125
127
  end
126
128
  alias_method :%, :at
127
129
 
@@ -423,7 +425,7 @@ module Nokogiri
423
425
  end
424
426
 
425
427
  ###
426
- # Return a nicely formated string representation
428
+ # Return a nicely formatted string representation
427
429
  def inspect
428
430
  "[#{map(&:inspect).join(", ")}]"
429
431
  end
@@ -140,7 +140,7 @@ module Nokogiri
140
140
 
141
141
  # Relax any hardcoded limit from the parser. Off by default.
142
142
  #
143
- # ⚠ There may be a performance penalty when this option is set.
143
+ # ⚠ <b>It is UNSAFE to set this option</b> when parsing untrusted documents.
144
144
  HUGE = 1 << 19
145
145
 
146
146
  # Support line numbers up to <code>long int</code> (default is a <code>short int</code>). On
@@ -8,6 +8,11 @@ module Nokogiri
8
8
  COLLECTIONS = [:attribute_nodes, :children]
9
9
 
10
10
  def inspect
11
+ # handle the case where an exception is thrown during object construction
12
+ if respond_to?(:data_ptr?) && !data_ptr?
13
+ return "#<#{self.class}:#{format("0x%x", object_id)} (no data)>"
14
+ end
15
+
11
16
  attributes = inspect_attributes.reject do |x|
12
17
  attribute = send(x)
13
18
  !attribute || (attribute.respond_to?(:empty?) && attribute.empty?)
@@ -21,7 +26,7 @@ module Nokogiri
21
26
  "#{attribute}=#{send(attribute).inspect}"
22
27
  end.join(" ")
23
28
  end
24
- "#<#{self.class.name}:#{format("0x%x", object_id)} #{attributes}>"
29
+ "#<#{self.class}:#{format("0x%x", object_id)} #{attributes}>"
25
30
  end
26
31
 
27
32
  def pretty_print(pp)
@@ -3,32 +3,33 @@
3
3
  module Nokogiri
4
4
  module XML
5
5
  ###
6
- # Nokogiri::XML::Reader parses an XML document similar to the way a cursor would move. The
7
- # Reader is given an XML document, and yields nodes to an each block.
6
+ # The Reader parser allows you to effectively pull parse an \XML document. Once instantiated,
7
+ # call Nokogiri::XML::Reader#each to iterate over each node.
8
8
  #
9
- # The Reader parser might be good for when you need the speed and low memory usage of the SAX
10
- # parser, but do not want to write a Document handler.
9
+ # Nokogiri::XML::Reader parses an \XML document similar to the way a cursor would move. The
10
+ # Reader is given an \XML document, and yields nodes to an each block.
11
+ #
12
+ # The Reader parser might be good for when you need the speed and low memory usage of a \SAX
13
+ # parser, but do not want to write a SAX::Document handler.
11
14
  #
12
15
  # Here is an example of usage:
13
16
  #
14
- # reader = Nokogiri::XML::Reader(<<-eoxml)
17
+ # reader = Nokogiri::XML::Reader.new <<~XML
15
18
  # <x xmlns:tenderlove='http://tenderlovemaking.com/'>
16
19
  # <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
17
20
  # </x>
18
- # eoxml
21
+ # XML
19
22
  #
20
23
  # reader.each do |node|
21
- #
22
24
  # # node is an instance of Nokogiri::XML::Reader
23
25
  # puts node.name
24
- #
25
26
  # end
26
27
  #
27
28
  # ⚠ Nokogiri::XML::Reader#each can only be called once! Once the cursor moves through the entire
28
29
  # document, you must parse the document again. It may be better to capture all information you
29
30
  # need during a single iteration.
30
31
  #
31
- # ⚠ libxml2 does not support error recovery in the Reader parser. The `RECOVER` ParseOption is
32
+ # ⚠ libxml2 does not support error recovery in the Reader parser. The +RECOVER+ ParseOption is
32
33
  # ignored. If a syntax error is encountered during parsing, an exception will be raised.
33
34
  class Reader
34
35
  include Enumerable
@@ -66,23 +67,55 @@ module Nokogiri
66
67
  TYPE_END_ELEMENT = 15
67
68
  # Entity end node type
68
69
  TYPE_END_ENTITY = 16
69
- # XML Declaration node type
70
+ # \XML Declaration node type
70
71
  TYPE_XML_DECLARATION = 17
71
72
 
72
73
  # A list of errors encountered while parsing
73
74
  attr_accessor :errors
74
75
 
75
- # The XML source
76
+ # The \XML source
76
77
  attr_reader :source
77
78
 
78
79
  alias_method :self_closing?, :empty_element?
79
80
 
80
- def initialize(source, url = nil, encoding = nil) # :nodoc:
81
+ # :call-seq:
82
+ # Reader.new(input) { |options| ... } → Reader
83
+ # Reader.new(input, url:, encoding:, options:) { |options| ... } → Reader
84
+ #
85
+ # Create a new Reader to parse an \XML document.
86
+ #
87
+ # [Required Parameters]
88
+ # - +input+ (String | IO): The \XML document to parse.
89
+ #
90
+ # [Optional Parameters]
91
+ # - +url:+ (String) The base URL of the document.
92
+ # - +encoding:+ (String) The name of the encoding of the document.
93
+ # - +options:+ (Integer | ParseOptions) Options to control the parser behavior.
94
+ # Defaults to +ParseOptions::STRICT+.
95
+ #
96
+ # [Yields]
97
+ # If present, the block will be passed a Nokogiri::XML::ParseOptions object to modify before
98
+ # the fragment is parsed. See Nokogiri::XML::ParseOptions for more information.
99
+ def self.new(
100
+ string_or_io,
101
+ url_ = nil, encoding_ = nil, options_ = ParseOptions::STRICT,
102
+ url: url_, encoding: encoding_, options: options_
103
+ )
104
+ options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
105
+ yield options if block_given?
106
+
107
+ if string_or_io.respond_to?(:read)
108
+ return Reader.from_io(string_or_io, url, encoding, options.to_i)
109
+ end
110
+
111
+ Reader.from_memory(string_or_io, url, encoding, options.to_i)
112
+ end
113
+
114
+ private def initialize(source, url = nil, encoding = nil) # :nodoc:
81
115
  @source = source
82
116
  @errors = []
83
117
  @encoding = encoding
84
118
  end
85
- private :initialize
86
119
 
87
120
  # Get the attributes and namespaces of the current node as a Hash.
88
121
  #
@@ -3,36 +3,73 @@
3
3
  module Nokogiri
4
4
  module XML
5
5
  class << self
6
- ###
7
- # Create a new Nokogiri::XML::RelaxNG document from +string_or_io+.
8
- # See Nokogiri::XML::RelaxNG for an example.
9
- def RelaxNG(string_or_io, options = ParseOptions::DEFAULT_SCHEMA)
10
- RelaxNG.new(string_or_io, options)
6
+ # :call-seq:
7
+ # RelaxNG(input) Nokogiri::XML::RelaxNG
8
+ # RelaxNG(input, options:) Nokogiri::XML::RelaxNG
9
+ #
10
+ # Convenience method for Nokogiri::XML::RelaxNG.new
11
+ def RelaxNG(...)
12
+ RelaxNG.new(...)
11
13
  end
12
14
  end
13
15
 
14
- ###
15
- # Nokogiri::XML::RelaxNG is used for validating XML against a
16
- # RelaxNG schema.
16
+ # Nokogiri::XML::RelaxNG is used for validating \XML against a RELAX NG schema definition.
17
17
  #
18
- # == Synopsis
18
+ # 🛡 <b>Do not use this class for untrusted schema documents.</b> RELAX NG input is always
19
+ # treated as *trusted*, meaning that the underlying parsing libraries <b>will access network
20
+ # resources</b>. This is counter to Nokogiri's "untrusted by default" security policy, but is an
21
+ # unfortunate limitation of the underlying libraries.
19
22
  #
20
- # Validate an XML document against a RelaxNG schema. Loop over the errors
21
- # that are returned and print them out:
23
+ # *Example:* Determine whether an \XML document is valid.
22
24
  #
23
- # schema = Nokogiri::XML::RelaxNG(File.open(ADDRESS_SCHEMA_FILE))
24
- # doc = Nokogiri::XML(File.open(ADDRESS_XML_FILE))
25
+ # schema = Nokogiri::XML::RelaxNG.new(File.read(RELAX_NG_FILE))
26
+ # doc = Nokogiri::XML::Document.parse(File.read(XML_FILE))
27
+ # schema.valid?(doc) # Boolean
25
28
  #
26
- # schema.validate(doc).each do |error|
27
- # puts error.message
28
- # end
29
+ # *Example:* Validate an \XML document against a \RelaxNG schema, and capture any errors that are found.
29
30
  #
30
- # The list of errors are Nokogiri::XML::SyntaxError objects.
31
+ # schema = Nokogiri::XML::RelaxNG.new(File.open(RELAX_NG_FILE))
32
+ # doc = Nokogiri::XML::Document.parse(File.open(XML_FILE))
33
+ # errors = schema.validate(doc) # Array<SyntaxError>
34
+ #
35
+ # *Example:* Validate an \XML document using a Document containing a RELAX NG schema definition.
36
+ #
37
+ # schema_doc = Nokogiri::XML::Document.parse(File.read(RELAX_NG_FILE))
38
+ # schema = Nokogiri::XML::RelaxNG.from_document(schema_doc)
39
+ # doc = Nokogiri::XML::Document.parse(File.open(XML_FILE))
40
+ # schema.valid?(doc) # Boolean
31
41
  #
32
- # NOTE: RelaxNG input is always treated as TRUSTED documents, meaning that they will cause the
33
- # underlying parsing libraries to access network resources. This is counter to Nokogiri's
34
- # "untrusted by default" security policy, but is a limitation of the underlying libraries.
35
42
  class RelaxNG < Nokogiri::XML::Schema
43
+ # :call-seq:
44
+ # new(input) → Nokogiri::XML::RelaxNG
45
+ # new(input, options:) → Nokogiri::XML::RelaxNG
46
+ #
47
+ # Parse a RELAX NG schema definition from a String or IO to create a new Nokogiri::XML::RelaxNG.
48
+ #
49
+ # [Parameters]
50
+ # - +input+ (String | IO) RELAX NG schema definition
51
+ # - +options:+ (Nokogiri::XML::ParseOptions)
52
+ # Defaults to Nokogiri::XML::ParseOptions::DEFAULT_SCHEMA ⚠ Unused
53
+ #
54
+ # [Returns] Nokogiri::XML::RelaxNG
55
+ #
56
+ # ⚠ +parse_options+ is currently unused by this method and is present only as a placeholder for
57
+ # future functionality.
58
+ #
59
+ # Also see convenience method Nokogiri::XML::RelaxNG()
60
+ def self.new(input, parse_options_ = ParseOptions::DEFAULT_SCHEMA, options: parse_options_)
61
+ from_document(Nokogiri::XML::Document.parse(input), options)
62
+ end
63
+
64
+ # :call-seq:
65
+ # read_memory(input) → Nokogiri::XML::RelaxNG
66
+ # read_memory(input, options:) → Nokogiri::XML::RelaxNG
67
+ #
68
+ # Convenience method for Nokogiri::XML::RelaxNG.new.
69
+ def self.read_memory(...)
70
+ # TODO deprecate this method
71
+ new(...)
72
+ end
36
73
  end
37
74
  end
38
75
  end