rexml 3.2.5 → 3.2.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rexml might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/NEWS.md +100 -2
- data/README.md +10 -1
- data/doc/rexml/tasks/rdoc/element.rdoc +2 -2
- data/doc/rexml/tutorial.rdoc +1358 -0
- data/lib/rexml/attribute.rb +14 -9
- data/lib/rexml/document.rb +1 -1
- data/lib/rexml/element.rb +3 -3
- data/lib/rexml/entity.rb +25 -15
- data/lib/rexml/formatters/pretty.rb +2 -2
- data/lib/rexml/namespace.rb +8 -4
- data/lib/rexml/parsers/xpathparser.rb +136 -86
- data/lib/rexml/rexml.rb +3 -1
- data/lib/rexml/text.rb +6 -4
- metadata +10 -8
data/lib/rexml/attribute.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require_relative "namespace"
|
3
3
|
require_relative 'text'
|
4
4
|
|
@@ -13,9 +13,6 @@ module REXML
|
|
13
13
|
|
14
14
|
# The element to which this attribute belongs
|
15
15
|
attr_reader :element
|
16
|
-
# The normalized value of this attribute. That is, the attribute with
|
17
|
-
# entities intact.
|
18
|
-
attr_writer :normalized
|
19
16
|
PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
|
20
17
|
|
21
18
|
NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
|
@@ -122,10 +119,13 @@ module REXML
|
|
122
119
|
# b = Attribute.new( "ns:x", "y" )
|
123
120
|
# b.to_string # -> "ns:x='y'"
|
124
121
|
def to_string
|
122
|
+
value = to_s
|
125
123
|
if @element and @element.context and @element.context[:attribute_quote] == :quote
|
126
|
-
|
124
|
+
value = value.gsub('"', '"') if value.include?('"')
|
125
|
+
%Q^#@expanded_name="#{value}"^
|
127
126
|
else
|
128
|
-
|
127
|
+
value = value.gsub("'", ''') if value.include?("'")
|
128
|
+
"#@expanded_name='#{value}'"
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
@@ -141,7 +141,6 @@ module REXML
|
|
141
141
|
return @normalized if @normalized
|
142
142
|
|
143
143
|
@normalized = Text::normalize( @unnormalized, doctype )
|
144
|
-
@unnormalized = nil
|
145
144
|
@normalized
|
146
145
|
end
|
147
146
|
|
@@ -150,10 +149,16 @@ module REXML
|
|
150
149
|
def value
|
151
150
|
return @unnormalized if @unnormalized
|
152
151
|
@unnormalized = Text::unnormalize( @normalized, doctype )
|
153
|
-
@normalized = nil
|
154
152
|
@unnormalized
|
155
153
|
end
|
156
154
|
|
155
|
+
# The normalized value of this attribute. That is, the attribute with
|
156
|
+
# entities intact.
|
157
|
+
def normalized=(new_normalized)
|
158
|
+
@normalized = new_normalized
|
159
|
+
@unnormalized = nil
|
160
|
+
end
|
161
|
+
|
157
162
|
# Returns a copy of this attribute
|
158
163
|
def clone
|
159
164
|
Attribute.new self
|
@@ -190,7 +195,7 @@ module REXML
|
|
190
195
|
end
|
191
196
|
|
192
197
|
def inspect
|
193
|
-
rv = ""
|
198
|
+
rv = +""
|
194
199
|
write( rv )
|
195
200
|
rv
|
196
201
|
end
|
data/lib/rexml/document.rb
CHANGED
@@ -69,7 +69,7 @@ module REXML
|
|
69
69
|
# d.to_s # => "<root><foo>Foo</foo><bar>Bar</bar></root>"
|
70
70
|
#
|
71
71
|
# When argument +document+ is given, it must be an existing
|
72
|
-
# document object, whose context and attributes (but not
|
72
|
+
# document object, whose context and attributes (but not children)
|
73
73
|
# are cloned into the new document:
|
74
74
|
#
|
75
75
|
# d = REXML::Document.new(xml_string)
|
data/lib/rexml/element.rb
CHANGED
@@ -989,7 +989,7 @@ module REXML
|
|
989
989
|
# :call-seq:
|
990
990
|
# has_text? -> true or false
|
991
991
|
#
|
992
|
-
# Returns +true if the element has one or more text noded,
|
992
|
+
# Returns +true+ if the element has one or more text noded,
|
993
993
|
# +false+ otherwise:
|
994
994
|
#
|
995
995
|
# d = REXML::Document.new '<a><b/>text<c/></a>'
|
@@ -1006,7 +1006,7 @@ module REXML
|
|
1006
1006
|
# text(xpath = nil) -> text_string or nil
|
1007
1007
|
#
|
1008
1008
|
# Returns the text string from the first text node child
|
1009
|
-
# in a specified element, if it exists,
|
1009
|
+
# in a specified element, if it exists, +nil+ otherwise.
|
1010
1010
|
#
|
1011
1011
|
# With no argument, returns the text from the first text node in +self+:
|
1012
1012
|
#
|
@@ -1014,7 +1014,7 @@ module REXML
|
|
1014
1014
|
# d.root.text.class # => String
|
1015
1015
|
# d.root.text # => "some text "
|
1016
1016
|
#
|
1017
|
-
# With argument +xpath+, returns text from the
|
1017
|
+
# With argument +xpath+, returns text from the first text node
|
1018
1018
|
# in the element that matches +xpath+:
|
1019
1019
|
#
|
1020
1020
|
# d.root.text(1) # => "this is bold!"
|
data/lib/rexml/entity.rb
CHANGED
@@ -132,24 +132,34 @@ module REXML
|
|
132
132
|
# then:
|
133
133
|
# doctype.entity('yada').value #-> "nanoo bar nanoo"
|
134
134
|
def value
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
135
|
+
@resolved_value ||= resolve_value
|
136
|
+
end
|
137
|
+
|
138
|
+
def parent=(other)
|
139
|
+
@resolved_value = nil
|
140
|
+
super
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
def resolve_value
|
145
|
+
return nil if @value.nil?
|
146
|
+
return @value unless @value.match?(PEREFERENCE_RE)
|
147
|
+
|
148
|
+
matches = @value.scan(PEREFERENCE_RE)
|
149
|
+
rv = @value.clone
|
150
|
+
if @parent
|
151
|
+
sum = 0
|
152
|
+
matches.each do |entity_reference|
|
153
|
+
entity_value = @parent.entity( entity_reference[0] )
|
154
|
+
if sum + entity_value.bytesize > Security.entity_expansion_text_limit
|
155
|
+
raise "entity expansion has grown too large"
|
156
|
+
else
|
157
|
+
sum += entity_value.bytesize
|
148
158
|
end
|
159
|
+
rv.gsub!( /%#{entity_reference.join};/um, entity_value )
|
149
160
|
end
|
150
|
-
return rv
|
151
161
|
end
|
152
|
-
|
162
|
+
rv
|
153
163
|
end
|
154
164
|
end
|
155
165
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require_relative 'default'
|
3
3
|
|
4
4
|
module REXML
|
@@ -58,7 +58,7 @@ module REXML
|
|
58
58
|
skip = false
|
59
59
|
if compact
|
60
60
|
if node.children.inject(true) {|s,c| s & c.kind_of?(Text)}
|
61
|
-
string = ""
|
61
|
+
string = +""
|
62
62
|
old_level = @level
|
63
63
|
@level = 0
|
64
64
|
node.children.each { |child| write( child, string ) }
|
data/lib/rexml/namespace.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'xmltokens'
|
4
4
|
|
@@ -10,13 +10,17 @@ module REXML
|
|
10
10
|
# The expanded name of the object, valid if name is set
|
11
11
|
attr_accessor :prefix
|
12
12
|
include XMLTokens
|
13
|
+
NAME_WITHOUT_NAMESPACE = /\A#{NCNAME_STR}\z/
|
13
14
|
NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
|
14
15
|
|
15
16
|
# Sets the name and the expanded name
|
16
17
|
def name=( name )
|
17
18
|
@expanded_name = name
|
18
|
-
|
19
|
-
|
19
|
+
if name.match?(NAME_WITHOUT_NAMESPACE)
|
20
|
+
@prefix = ""
|
21
|
+
@namespace = ""
|
22
|
+
@name = name
|
23
|
+
elsif name =~ NAMESPLIT
|
20
24
|
if $1
|
21
25
|
@prefix = $1
|
22
26
|
else
|
@@ -24,7 +28,7 @@ module REXML
|
|
24
28
|
@namespace = ""
|
25
29
|
end
|
26
30
|
@name = $2
|
27
|
-
|
31
|
+
elsif name == ""
|
28
32
|
@prefix = nil
|
29
33
|
@namespace = nil
|
30
34
|
@name = nil
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
|
+
|
2
3
|
require_relative '../namespace'
|
3
4
|
require_relative '../xmltokens'
|
4
5
|
|
@@ -38,108 +39,143 @@ module REXML
|
|
38
39
|
parsed
|
39
40
|
end
|
40
41
|
|
41
|
-
def abbreviate(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
def abbreviate(path_or_parsed)
|
43
|
+
if path_or_parsed.kind_of?(String)
|
44
|
+
parsed = parse(path_or_parsed)
|
45
|
+
else
|
46
|
+
parsed = path_or_parsed
|
47
|
+
end
|
48
|
+
components = []
|
49
|
+
component = nil
|
50
|
+
while parsed.size > 0
|
51
|
+
op = parsed.shift
|
47
52
|
case op
|
48
53
|
when :node
|
54
|
+
component << "node()"
|
49
55
|
when :attribute
|
50
|
-
|
51
|
-
|
56
|
+
component = "@"
|
57
|
+
components << component
|
52
58
|
when :child
|
53
|
-
|
59
|
+
component = ""
|
60
|
+
components << component
|
54
61
|
when :descendant_or_self
|
55
|
-
|
62
|
+
next_op = parsed[0]
|
63
|
+
if next_op == :node
|
64
|
+
parsed.shift
|
65
|
+
component = ""
|
66
|
+
components << component
|
67
|
+
else
|
68
|
+
component = "descendant-or-self::"
|
69
|
+
components << component
|
70
|
+
end
|
56
71
|
when :self
|
57
|
-
|
72
|
+
next_op = parsed[0]
|
73
|
+
if next_op == :node
|
74
|
+
parsed.shift
|
75
|
+
components << "."
|
76
|
+
else
|
77
|
+
component = "self::"
|
78
|
+
components << component
|
79
|
+
end
|
58
80
|
when :parent
|
59
|
-
|
81
|
+
next_op = parsed[0]
|
82
|
+
if next_op == :node
|
83
|
+
parsed.shift
|
84
|
+
components << ".."
|
85
|
+
else
|
86
|
+
component = "parent::"
|
87
|
+
components << component
|
88
|
+
end
|
60
89
|
when :any
|
61
|
-
|
90
|
+
component << "*"
|
62
91
|
when :text
|
63
|
-
|
92
|
+
component << "text()"
|
64
93
|
when :following, :following_sibling,
|
65
94
|
:ancestor, :ancestor_or_self, :descendant,
|
66
95
|
:namespace, :preceding, :preceding_sibling
|
67
|
-
|
68
|
-
|
69
|
-
string << "::"
|
96
|
+
component = op.to_s.tr("_", "-") << "::"
|
97
|
+
components << component
|
70
98
|
when :qname
|
71
|
-
prefix =
|
72
|
-
name =
|
73
|
-
|
74
|
-
|
99
|
+
prefix = parsed.shift
|
100
|
+
name = parsed.shift
|
101
|
+
component << prefix+":" if prefix.size > 0
|
102
|
+
component << name
|
75
103
|
when :predicate
|
76
|
-
|
77
|
-
|
78
|
-
|
104
|
+
component << '['
|
105
|
+
component << predicate_to_path(parsed.shift) {|x| abbreviate(x)}
|
106
|
+
component << ']'
|
79
107
|
when :document
|
80
|
-
|
108
|
+
components << ""
|
81
109
|
when :function
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
110
|
+
component << parsed.shift
|
111
|
+
component << "( "
|
112
|
+
component << predicate_to_path(parsed.shift[0]) {|x| abbreviate(x)}
|
113
|
+
component << " )"
|
86
114
|
when :literal
|
87
|
-
|
115
|
+
component << quote_literal(parsed.shift)
|
88
116
|
else
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
string << ")"
|
117
|
+
component << "UNKNOWN("
|
118
|
+
component << op.inspect
|
119
|
+
component << ")"
|
93
120
|
end
|
94
121
|
end
|
95
|
-
|
96
|
-
|
122
|
+
case components
|
123
|
+
when [""]
|
124
|
+
"/"
|
125
|
+
when ["", ""]
|
126
|
+
"//"
|
127
|
+
else
|
128
|
+
components.join("/")
|
129
|
+
end
|
97
130
|
end
|
98
131
|
|
99
|
-
def expand(
|
100
|
-
|
101
|
-
|
132
|
+
def expand(path_or_parsed)
|
133
|
+
if path_or_parsed.kind_of?(String)
|
134
|
+
parsed = parse(path_or_parsed)
|
135
|
+
else
|
136
|
+
parsed = path_or_parsed
|
137
|
+
end
|
138
|
+
path = ""
|
102
139
|
document = false
|
103
|
-
while
|
104
|
-
op =
|
140
|
+
while parsed.size > 0
|
141
|
+
op = parsed.shift
|
105
142
|
case op
|
106
143
|
when :node
|
107
|
-
|
144
|
+
path << "node()"
|
108
145
|
when :attribute, :child, :following, :following_sibling,
|
109
146
|
:ancestor, :ancestor_or_self, :descendant, :descendant_or_self,
|
110
147
|
:namespace, :preceding, :preceding_sibling, :self, :parent
|
111
|
-
|
112
|
-
|
113
|
-
|
148
|
+
path << "/" unless path.size == 0
|
149
|
+
path << op.to_s.tr("_", "-")
|
150
|
+
path << "::"
|
114
151
|
when :any
|
115
|
-
|
152
|
+
path << "*"
|
116
153
|
when :qname
|
117
|
-
prefix =
|
118
|
-
name =
|
119
|
-
|
120
|
-
|
154
|
+
prefix = parsed.shift
|
155
|
+
name = parsed.shift
|
156
|
+
path << prefix+":" if prefix.size > 0
|
157
|
+
path << name
|
121
158
|
when :predicate
|
122
|
-
|
123
|
-
|
124
|
-
|
159
|
+
path << '['
|
160
|
+
path << predicate_to_path( parsed.shift ) { |x| expand(x) }
|
161
|
+
path << ']'
|
125
162
|
when :document
|
126
163
|
document = true
|
127
164
|
else
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
string << ")"
|
165
|
+
path << "UNKNOWN("
|
166
|
+
path << op.inspect
|
167
|
+
path << ")"
|
132
168
|
end
|
133
169
|
end
|
134
|
-
|
135
|
-
|
170
|
+
path = "/"+path if document
|
171
|
+
path
|
136
172
|
end
|
137
173
|
|
138
|
-
def
|
139
|
-
|
140
|
-
case
|
174
|
+
def predicate_to_path(parsed, &block)
|
175
|
+
path = ""
|
176
|
+
case parsed[0]
|
141
177
|
when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union
|
142
|
-
op =
|
178
|
+
op = parsed.shift
|
143
179
|
case op
|
144
180
|
when :eq
|
145
181
|
op = "="
|
@@ -156,36 +192,50 @@ module REXML
|
|
156
192
|
when :union
|
157
193
|
op = "|"
|
158
194
|
end
|
159
|
-
left =
|
160
|
-
right =
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
string << right
|
167
|
-
string << " "
|
195
|
+
left = predicate_to_path( parsed.shift, &block )
|
196
|
+
right = predicate_to_path( parsed.shift, &block )
|
197
|
+
path << left
|
198
|
+
path << " "
|
199
|
+
path << op.to_s
|
200
|
+
path << " "
|
201
|
+
path << right
|
168
202
|
when :function
|
169
|
-
|
170
|
-
name =
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
203
|
+
parsed.shift
|
204
|
+
name = parsed.shift
|
205
|
+
path << name
|
206
|
+
path << "("
|
207
|
+
parsed.shift.each_with_index do |argument, i|
|
208
|
+
path << ", " if i > 0
|
209
|
+
path << predicate_to_path(argument, &block)
|
210
|
+
end
|
211
|
+
path << ")"
|
175
212
|
when :literal
|
176
|
-
|
177
|
-
|
178
|
-
string << path.shift.inspect
|
179
|
-
string << " "
|
213
|
+
parsed.shift
|
214
|
+
path << quote_literal(parsed.shift)
|
180
215
|
else
|
181
|
-
|
182
|
-
string << yield( path )
|
183
|
-
string << " "
|
216
|
+
path << yield( parsed )
|
184
217
|
end
|
185
|
-
return
|
218
|
+
return path.squeeze(" ")
|
186
219
|
end
|
220
|
+
# For backward compatibility
|
221
|
+
alias_method :preciate_to_string, :predicate_to_path
|
187
222
|
|
188
223
|
private
|
224
|
+
def quote_literal( literal )
|
225
|
+
case literal
|
226
|
+
when String
|
227
|
+
# XPath 1.0 does not support escape characters.
|
228
|
+
# Assumes literal does not contain both single and double quotes.
|
229
|
+
if literal.include?("'")
|
230
|
+
"\"#{literal}\""
|
231
|
+
else
|
232
|
+
"'#{literal}'"
|
233
|
+
end
|
234
|
+
else
|
235
|
+
literal.inspect
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
189
239
|
#LocationPath
|
190
240
|
# | RelativeLocationPath
|
191
241
|
# | '/' RelativeLocationPath?
|
data/lib/rexml/rexml.rb
CHANGED
@@ -26,10 +26,12 @@
|
|
26
26
|
# - REXML::Document.
|
27
27
|
# - REXML::Element.
|
28
28
|
#
|
29
|
+
# There's also an {REXML tutorial}[doc/rexml/tutorial_rdoc.html].
|
30
|
+
#
|
29
31
|
module REXML
|
30
32
|
COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>"
|
31
33
|
DATE = "2008/019"
|
32
|
-
VERSION = "3.2.
|
34
|
+
VERSION = "3.2.6"
|
33
35
|
REVISION = ""
|
34
36
|
|
35
37
|
Copyright = COPYRIGHT
|
data/lib/rexml/text.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require_relative 'security'
|
3
3
|
require_relative 'entity'
|
4
4
|
require_relative 'doctype'
|
@@ -131,7 +131,7 @@ module REXML
|
|
131
131
|
def Text.check string, pattern, doctype
|
132
132
|
|
133
133
|
# illegal anywhere
|
134
|
-
if string
|
134
|
+
if !string.match?(VALID_XML_CHARS)
|
135
135
|
if String.method_defined? :encode
|
136
136
|
string.chars.each do |c|
|
137
137
|
case c.ord
|
@@ -371,7 +371,7 @@ module REXML
|
|
371
371
|
copy = input.to_s
|
372
372
|
# Doing it like this rather than in a loop improves the speed
|
373
373
|
#copy = copy.gsub( EREFERENCE, '&' )
|
374
|
-
copy = copy.gsub( "&", "&" )
|
374
|
+
copy = copy.gsub( "&", "&" ) if copy.include?("&")
|
375
375
|
if doctype
|
376
376
|
# Replace all ampersands that aren't part of an entity
|
377
377
|
doctype.entities.each_value do |entity|
|
@@ -382,7 +382,9 @@ module REXML
|
|
382
382
|
else
|
383
383
|
# Replace all ampersands that aren't part of an entity
|
384
384
|
DocType::DEFAULT_ENTITIES.each_value do |entity|
|
385
|
-
|
385
|
+
if copy.include?(entity.value)
|
386
|
+
copy = copy.gsub(entity.value, "&#{entity.name};" )
|
387
|
+
end
|
386
388
|
end
|
387
389
|
end
|
388
390
|
copy
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rexml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kouhei Sutou
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -73,6 +73,7 @@ extra_rdoc_files:
|
|
73
73
|
- doc/rexml/tasks/tocs/master_toc.rdoc
|
74
74
|
- doc/rexml/tasks/tocs/node_toc.rdoc
|
75
75
|
- doc/rexml/tasks/tocs/parent_toc.rdoc
|
76
|
+
- doc/rexml/tutorial.rdoc
|
76
77
|
files:
|
77
78
|
- LICENSE.txt
|
78
79
|
- NEWS.md
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- doc/rexml/tasks/tocs/master_toc.rdoc
|
90
91
|
- doc/rexml/tasks/tocs/node_toc.rdoc
|
91
92
|
- doc/rexml/tasks/tocs/parent_toc.rdoc
|
93
|
+
- doc/rexml/tutorial.rdoc
|
92
94
|
- lib/rexml.rb
|
93
95
|
- lib/rexml/attlistdecl.rb
|
94
96
|
- lib/rexml/attribute.rb
|
@@ -143,7 +145,7 @@ homepage: https://github.com/ruby/rexml
|
|
143
145
|
licenses:
|
144
146
|
- BSD-2-Clause
|
145
147
|
metadata: {}
|
146
|
-
post_install_message:
|
148
|
+
post_install_message:
|
147
149
|
rdoc_options:
|
148
150
|
- "--main"
|
149
151
|
- README.md
|
@@ -153,15 +155,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
155
|
requirements:
|
154
156
|
- - ">="
|
155
157
|
- !ruby/object:Gem::Version
|
156
|
-
version:
|
158
|
+
version: 2.5.0
|
157
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
160
|
requirements:
|
159
161
|
- - ">="
|
160
162
|
- !ruby/object:Gem::Version
|
161
163
|
version: '0'
|
162
164
|
requirements: []
|
163
|
-
rubygems_version: 3.
|
164
|
-
signing_key:
|
165
|
+
rubygems_version: 3.5.0.dev
|
166
|
+
signing_key:
|
165
167
|
specification_version: 4
|
166
168
|
summary: An XML toolkit for Ruby
|
167
169
|
test_files: []
|