rexml 3.4.0 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +127 -1
- data/lib/rexml/attribute.rb +7 -8
- data/lib/rexml/cdata.rb +1 -1
- data/lib/rexml/child.rb +2 -3
- data/lib/rexml/comment.rb +1 -1
- data/lib/rexml/doctype.rb +3 -8
- data/lib/rexml/document.rb +18 -4
- data/lib/rexml/element.rb +53 -59
- data/lib/rexml/encoding.rb +3 -6
- data/lib/rexml/functions.rb +3 -3
- data/lib/rexml/instruction.rb +1 -1
- data/lib/rexml/namespace.rb +4 -4
- data/lib/rexml/node.rb +2 -2
- data/lib/rexml/parsers/baseparser.rb +162 -84
- data/lib/rexml/parsers/xpathparser.rb +4 -4
- data/lib/rexml/quickpath.rb +19 -18
- data/lib/rexml/rexml.rb +1 -1
- data/lib/rexml/security.rb +2 -2
- data/lib/rexml/source.rb +22 -3
- data/lib/rexml/text.rb +14 -17
- data/lib/rexml/validation/relaxng.rb +27 -26
- data/lib/rexml/validation/validation.rb +8 -8
- data/lib/rexml/xpath.rb +2 -13
- data/lib/rexml/xpath_parser.rb +44 -42
- metadata +4 -7
data/lib/rexml/node.rb
CHANGED
@@ -26,7 +26,7 @@ module REXML
|
|
26
26
|
# REXML::Formatters package for changing the output style.
|
27
27
|
def to_s indent=nil
|
28
28
|
unless indent.nil?
|
29
|
-
Kernel.warn( "#{self.class.name}
|
29
|
+
Kernel.warn( "#{self.class.name}#to_s(indent) parameter is deprecated", uplevel: 1)
|
30
30
|
f = REXML::Formatters::Pretty.new( indent )
|
31
31
|
f.write( self, rv = "" )
|
32
32
|
else
|
@@ -68,7 +68,7 @@ module REXML
|
|
68
68
|
each_recursive {|node|
|
69
69
|
return node if block.call(node)
|
70
70
|
}
|
71
|
-
|
71
|
+
nil
|
72
72
|
end
|
73
73
|
|
74
74
|
# Returns the position that +self+ holds in its parent's array, indexed
|
@@ -144,6 +144,7 @@ module REXML
|
|
144
144
|
PEREFERENCE_PATTERN = /#{PEREFERENCE}/um
|
145
145
|
TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um
|
146
146
|
CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um
|
147
|
+
EQUAL_PATTERN = /\s*=\s*/um
|
147
148
|
ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um
|
148
149
|
NAME_PATTERN = /#{NAME}/um
|
149
150
|
GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
|
@@ -168,6 +169,7 @@ module REXML
|
|
168
169
|
@entity_expansion_limit = Security.entity_expansion_limit
|
169
170
|
@entity_expansion_text_limit = Security.entity_expansion_text_limit
|
170
171
|
@source.ensure_buffer
|
172
|
+
@version = nil
|
171
173
|
end
|
172
174
|
|
173
175
|
def add_listener( listener )
|
@@ -206,12 +208,12 @@ module REXML
|
|
206
208
|
|
207
209
|
# Returns true if there are no more events
|
208
210
|
def empty?
|
209
|
-
|
211
|
+
(@source.empty? and @stack.empty?)
|
210
212
|
end
|
211
213
|
|
212
214
|
# Returns true if there are more events. Synonymous with !empty?
|
213
215
|
def has_next?
|
214
|
-
|
216
|
+
!(@source.empty? and @stack.empty?)
|
215
217
|
end
|
216
218
|
|
217
219
|
# Push an event back on the head of the stream. This method
|
@@ -277,17 +279,10 @@ module REXML
|
|
277
279
|
return process_instruction
|
278
280
|
elsif @source.match?("<!", true)
|
279
281
|
if @source.match?("--", true)
|
280
|
-
|
281
|
-
if md.nil?
|
282
|
-
raise REXML::ParseException.new("Unclosed comment", @source)
|
283
|
-
end
|
284
|
-
if /--|-\z/.match?(md[1])
|
285
|
-
raise REXML::ParseException.new("Malformed comment", @source)
|
286
|
-
end
|
287
|
-
return [ :comment, md[1] ]
|
282
|
+
return [ :comment, process_comment ]
|
288
283
|
elsif @source.match?("DOCTYPE", true)
|
289
284
|
base_error_message = "Malformed DOCTYPE"
|
290
|
-
unless @source.
|
285
|
+
unless @source.skip_spaces
|
291
286
|
if @source.match?(">")
|
292
287
|
message = "#{base_error_message}: name is missing"
|
293
288
|
else
|
@@ -297,10 +292,11 @@ module REXML
|
|
297
292
|
raise REXML::ParseException.new(message, @source)
|
298
293
|
end
|
299
294
|
name = parse_name(base_error_message)
|
300
|
-
|
295
|
+
@source.skip_spaces
|
296
|
+
if @source.match?("[", true)
|
301
297
|
id = [nil, nil, nil]
|
302
298
|
@document_status = :in_doctype
|
303
|
-
elsif @source.match?(
|
299
|
+
elsif @source.match?(">", true)
|
304
300
|
id = [nil, nil, nil]
|
305
301
|
@document_status = :after_doctype
|
306
302
|
@source.ensure_buffer
|
@@ -312,9 +308,10 @@ module REXML
|
|
312
308
|
# For backward compatibility
|
313
309
|
id[1], id[2] = id[2], nil
|
314
310
|
end
|
315
|
-
|
311
|
+
@source.skip_spaces
|
312
|
+
if @source.match?("[", true)
|
316
313
|
@document_status = :in_doctype
|
317
|
-
elsif @source.match?(
|
314
|
+
elsif @source.match?(">", true)
|
318
315
|
@document_status = :after_doctype
|
319
316
|
@source.ensure_buffer
|
320
317
|
else
|
@@ -324,7 +321,7 @@ module REXML
|
|
324
321
|
end
|
325
322
|
args = [:start_doctype, name, *id]
|
326
323
|
if @document_status == :after_doctype
|
327
|
-
@source.
|
324
|
+
@source.skip_spaces
|
328
325
|
@stack << [ :end_doctype ]
|
329
326
|
end
|
330
327
|
return args
|
@@ -335,7 +332,7 @@ module REXML
|
|
335
332
|
end
|
336
333
|
end
|
337
334
|
if @document_status == :in_doctype
|
338
|
-
@source.
|
335
|
+
@source.skip_spaces
|
339
336
|
start_position = @source.position
|
340
337
|
if @source.match?("<!", true)
|
341
338
|
if @source.match?("ELEMENT", true)
|
@@ -378,7 +375,7 @@ module REXML
|
|
378
375
|
md = @source.match(Private::ATTLISTDECL_END, true)
|
379
376
|
raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
|
380
377
|
element = md[1]
|
381
|
-
contents = md[0]
|
378
|
+
contents = "<!ATTLIST" + md[0]
|
382
379
|
|
383
380
|
pairs = {}
|
384
381
|
values = md[0].strip.scan( ATTDEF_RE )
|
@@ -396,7 +393,7 @@ module REXML
|
|
396
393
|
return [ :attlistdecl, element, pairs, contents ]
|
397
394
|
elsif @source.match?("NOTATION", true)
|
398
395
|
base_error_message = "Malformed notation declaration"
|
399
|
-
unless @source.
|
396
|
+
unless @source.skip_spaces
|
400
397
|
if @source.match?(">")
|
401
398
|
message = "#{base_error_message}: name is missing"
|
402
399
|
else
|
@@ -409,30 +406,28 @@ module REXML
|
|
409
406
|
id = parse_id(base_error_message,
|
410
407
|
accept_external_id: true,
|
411
408
|
accept_public_id: true)
|
412
|
-
|
409
|
+
@source.skip_spaces
|
410
|
+
unless @source.match?(">", true)
|
413
411
|
message = "#{base_error_message}: garbage before end >"
|
414
412
|
raise REXML::ParseException.new(message, @source)
|
415
413
|
end
|
416
414
|
return [:notationdecl, name, *id]
|
417
|
-
elsif
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
end
|
422
|
-
return [ :comment, md[1] ] if md
|
415
|
+
elsif @source.match?("--", true)
|
416
|
+
return [ :comment, process_comment ]
|
417
|
+
else
|
418
|
+
raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor ELEMENT,ENTITY,ATTLIST,NOTATION", @source)
|
423
419
|
end
|
424
420
|
elsif match = @source.match(/(%.*?;)\s*/um, true)
|
425
421
|
return [ :externalentity, match[1] ]
|
426
422
|
elsif @source.match?(/\]\s*>/um, true)
|
427
423
|
@document_status = :after_doctype
|
428
424
|
return [ :end_doctype ]
|
429
|
-
|
430
|
-
if @document_status == :in_doctype
|
425
|
+
else
|
431
426
|
raise ParseException.new("Malformed DOCTYPE: invalid declaration", @source)
|
432
427
|
end
|
433
428
|
end
|
434
429
|
if @document_status == :after_doctype
|
435
|
-
@source.
|
430
|
+
@source.skip_spaces
|
436
431
|
end
|
437
432
|
begin
|
438
433
|
start_position = @source.position
|
@@ -457,23 +452,19 @@ module REXML
|
|
457
452
|
end
|
458
453
|
return [ :end_element, last_tag ]
|
459
454
|
elsif @source.match?("!", true)
|
460
|
-
md = @source.match(/([^>]*>)/um)
|
461
455
|
#STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
if
|
467
|
-
|
456
|
+
if @source.match?("--", true)
|
457
|
+
return [ :comment, process_comment ]
|
458
|
+
elsif @source.match?("[CDATA[", true)
|
459
|
+
text = @source.read_until("]]>")
|
460
|
+
if text.chomp!("]]>")
|
461
|
+
return [ :cdata, text ]
|
462
|
+
else
|
463
|
+
raise REXML::ParseException.new("Malformed CDATA: Missing end ']]>'", @source)
|
468
464
|
end
|
469
|
-
|
470
|
-
return [ :comment, md[1] ]
|
471
465
|
else
|
472
|
-
|
473
|
-
return [ :cdata, md[1] ] if md
|
466
|
+
raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor CDATA", @source)
|
474
467
|
end
|
475
|
-
raise REXML::ParseException.new( "Declarations can only occur "+
|
476
|
-
"in the doctype declaration.", @source)
|
477
468
|
elsif @source.match?("?", true)
|
478
469
|
return process_instruction
|
479
470
|
else
|
@@ -533,7 +524,8 @@ module REXML
|
|
533
524
|
raise REXML::ParseException.new( "Exception parsing",
|
534
525
|
@source, self, (error ? error : $!) )
|
535
526
|
end
|
536
|
-
|
527
|
+
# NOTE: The end of the method never runs, because it is unreachable.
|
528
|
+
# All branches of code above have explicit unconditional return or raise statements.
|
537
529
|
end
|
538
530
|
private :pull_event
|
539
531
|
|
@@ -652,6 +644,10 @@ module REXML
|
|
652
644
|
true
|
653
645
|
end
|
654
646
|
|
647
|
+
def normalize_xml_declaration_encoding(xml_declaration_encoding)
|
648
|
+
/\AUTF-16(?:BE|LE)\z/i.match?(xml_declaration_encoding) ? "UTF-16" : nil
|
649
|
+
end
|
650
|
+
|
655
651
|
def parse_name(base_error_message)
|
656
652
|
md = @source.match(Private::NAME_PATTERN, true)
|
657
653
|
unless md
|
@@ -731,39 +727,137 @@ module REXML
|
|
731
727
|
end
|
732
728
|
end
|
733
729
|
|
730
|
+
def process_comment
|
731
|
+
text = @source.read_until("-->")
|
732
|
+
unless text.chomp!("-->")
|
733
|
+
raise REXML::ParseException.new("Unclosed comment: Missing end '-->'", @source)
|
734
|
+
end
|
735
|
+
|
736
|
+
if text.include? "--" or text.end_with?("-")
|
737
|
+
raise REXML::ParseException.new("Malformed comment", @source)
|
738
|
+
end
|
739
|
+
text
|
740
|
+
end
|
741
|
+
|
734
742
|
def process_instruction
|
735
743
|
name = parse_name("Malformed XML: Invalid processing instruction node")
|
736
|
-
if
|
737
|
-
|
738
|
-
|
739
|
-
|
744
|
+
if name == "xml"
|
745
|
+
xml_declaration
|
746
|
+
else # PITarget
|
747
|
+
if @source.skip_spaces # e.g. <?name content?>
|
748
|
+
start_position = @source.position
|
749
|
+
content = @source.read_until("?>")
|
750
|
+
unless content.chomp!("?>")
|
751
|
+
@source.position = start_position
|
752
|
+
raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
|
753
|
+
end
|
754
|
+
else # e.g. <?name?>
|
755
|
+
content = nil
|
756
|
+
unless @source.match?("?>", true)
|
757
|
+
raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
|
758
|
+
end
|
740
759
|
end
|
741
|
-
|
742
|
-
|
743
|
-
|
760
|
+
[:processing_instruction, name, content]
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
def xml_declaration
|
765
|
+
unless @version.nil?
|
766
|
+
raise ParseException.new("Malformed XML: XML declaration is duplicated", @source)
|
767
|
+
end
|
768
|
+
if @document_status
|
769
|
+
raise ParseException.new("Malformed XML: XML declaration is not at the start", @source)
|
770
|
+
end
|
771
|
+
unless @source.skip_spaces
|
772
|
+
raise ParseException.new("Malformed XML: XML declaration misses spaces before version", @source)
|
773
|
+
end
|
774
|
+
unless @source.match?("version", true)
|
775
|
+
raise ParseException.new("Malformed XML: XML declaration misses version", @source)
|
776
|
+
end
|
777
|
+
@version = parse_attribute_value_with_equal("xml")
|
778
|
+
unless @source.skip_spaces
|
744
779
|
unless @source.match?("?>", true)
|
745
|
-
raise ParseException.new("Malformed XML: Unclosed
|
780
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
746
781
|
end
|
782
|
+
encoding = normalize_xml_declaration_encoding(@source.encoding)
|
783
|
+
return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.0"?>
|
747
784
|
end
|
748
|
-
|
749
|
-
|
750
|
-
|
785
|
+
|
786
|
+
if @source.match?("encoding", true)
|
787
|
+
encoding = parse_attribute_value_with_equal("xml")
|
788
|
+
unless @source.skip_spaces
|
789
|
+
unless @source.match?("?>", true)
|
790
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
791
|
+
end
|
792
|
+
if need_source_encoding_update?(encoding)
|
793
|
+
@source.encoding = encoding
|
794
|
+
end
|
795
|
+
encoding ||= normalize_xml_declaration_encoding(@source.encoding)
|
796
|
+
return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.1" encoding="UTF-8"?>
|
751
797
|
end
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
798
|
+
end
|
799
|
+
|
800
|
+
if @source.match?("standalone", true)
|
801
|
+
standalone = parse_attribute_value_with_equal("xml")
|
802
|
+
case standalone
|
803
|
+
when "yes", "no"
|
804
|
+
else
|
805
|
+
raise ParseException.new("Malformed XML: XML declaration standalone is not yes or no : <#{standalone}>", @source)
|
758
806
|
end
|
759
|
-
|
760
|
-
|
807
|
+
end
|
808
|
+
@source.skip_spaces
|
809
|
+
unless @source.match?("?>", true)
|
810
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
811
|
+
end
|
812
|
+
|
813
|
+
if need_source_encoding_update?(encoding)
|
814
|
+
@source.encoding = encoding
|
815
|
+
end
|
816
|
+
encoding ||= normalize_xml_declaration_encoding(@source.encoding)
|
817
|
+
|
818
|
+
# e.g. <?xml version="1.0" ?>
|
819
|
+
# <?xml version="1.1" encoding="UTF-8" ?>
|
820
|
+
# <?xml version="1.1" standalone="yes"?>
|
821
|
+
# <?xml version="1.1" encoding="UTF-8" standalone="yes" ?>
|
822
|
+
[ :xmldecl, @version, encoding, standalone ]
|
823
|
+
end
|
824
|
+
|
825
|
+
if StringScanner::Version < "3.1.1"
|
826
|
+
def scan_quote
|
827
|
+
@source.match(/(['"])/, true)&.[](1)
|
828
|
+
end
|
829
|
+
else
|
830
|
+
def scan_quote
|
831
|
+
case @source.peek_byte
|
832
|
+
when 34 # '"'.ord
|
833
|
+
@source.scan_byte
|
834
|
+
'"'
|
835
|
+
when 39 # "'".ord
|
836
|
+
@source.scan_byte
|
837
|
+
"'"
|
838
|
+
else
|
839
|
+
nil
|
761
840
|
end
|
762
|
-
standalone = STANDALONE.match(content)
|
763
|
-
standalone = standalone[1] unless standalone.nil?
|
764
|
-
return [ :xmldecl, version, encoding, standalone ]
|
765
841
|
end
|
766
|
-
|
842
|
+
end
|
843
|
+
|
844
|
+
def parse_attribute_value_with_equal(name)
|
845
|
+
unless @source.match?(Private::EQUAL_PATTERN, true)
|
846
|
+
message = "Missing attribute equal: <#{name}>"
|
847
|
+
raise REXML::ParseException.new(message, @source)
|
848
|
+
end
|
849
|
+
unless quote = scan_quote
|
850
|
+
message = "Missing attribute value start quote: <#{name}>"
|
851
|
+
raise REXML::ParseException.new(message, @source)
|
852
|
+
end
|
853
|
+
start_position = @source.position
|
854
|
+
value = @source.read_until(quote)
|
855
|
+
unless value.chomp!(quote)
|
856
|
+
@source.position = start_position
|
857
|
+
message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
|
858
|
+
raise REXML::ParseException.new(message, @source)
|
859
|
+
end
|
860
|
+
value
|
767
861
|
end
|
768
862
|
|
769
863
|
def parse_attributes(prefixes)
|
@@ -780,24 +874,8 @@ module REXML
|
|
780
874
|
name = match[1]
|
781
875
|
prefix = match[2]
|
782
876
|
local_part = match[3]
|
783
|
-
|
784
|
-
|
785
|
-
message = "Missing attribute equal: <#{name}>"
|
786
|
-
raise REXML::ParseException.new(message, @source)
|
787
|
-
end
|
788
|
-
unless match = @source.match(/(['"])/, true)
|
789
|
-
message = "Missing attribute value start quote: <#{name}>"
|
790
|
-
raise REXML::ParseException.new(message, @source)
|
791
|
-
end
|
792
|
-
quote = match[1]
|
793
|
-
start_position = @source.position
|
794
|
-
value = @source.read_until(quote)
|
795
|
-
unless value.chomp!(quote)
|
796
|
-
@source.position = start_position
|
797
|
-
message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
|
798
|
-
raise REXML::ParseException.new(message, @source)
|
799
|
-
end
|
800
|
-
@source.match?(/\s*/um, true)
|
877
|
+
value = parse_attribute_value_with_equal(name)
|
878
|
+
@source.skip_spaces
|
801
879
|
if prefix == "xmlns"
|
802
880
|
if local_part == "xml"
|
803
881
|
if value != Private::XML_PREFIXED_NAMESPACE
|
@@ -215,7 +215,7 @@ module REXML
|
|
215
215
|
else
|
216
216
|
path << yield( parsed )
|
217
217
|
end
|
218
|
-
|
218
|
+
path.squeeze(" ")
|
219
219
|
end
|
220
220
|
# For backward compatibility
|
221
221
|
alias_method :preciate_to_string, :predicate_to_path
|
@@ -252,7 +252,7 @@ module REXML
|
|
252
252
|
path = path[1..-1]
|
253
253
|
end
|
254
254
|
end
|
255
|
-
|
255
|
+
RelativeLocationPath( path, parsed ) if path.size > 0
|
256
256
|
end
|
257
257
|
|
258
258
|
#RelativeLocationPath
|
@@ -388,7 +388,7 @@ module REXML
|
|
388
388
|
else
|
389
389
|
path = original_path
|
390
390
|
end
|
391
|
-
|
391
|
+
path
|
392
392
|
end
|
393
393
|
|
394
394
|
# Filters the supplied nodeset on the predicate(s)
|
@@ -600,7 +600,7 @@ module REXML
|
|
600
600
|
end
|
601
601
|
rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/
|
602
602
|
parsed.concat(n)
|
603
|
-
|
603
|
+
rest
|
604
604
|
end
|
605
605
|
|
606
606
|
#| FilterExpr Predicate
|
data/lib/rexml/quickpath.rb
CHANGED
@@ -41,7 +41,7 @@ module REXML
|
|
41
41
|
else
|
42
42
|
results = filter([element], path)
|
43
43
|
end
|
44
|
-
|
44
|
+
results
|
45
45
|
end
|
46
46
|
|
47
47
|
# Given an array of nodes it filters the array based on the path. The
|
@@ -51,18 +51,18 @@ module REXML
|
|
51
51
|
return elements if path.nil? or path == '' or elements.size == 0
|
52
52
|
case path
|
53
53
|
when /^\/\//u # Descendant
|
54
|
-
|
54
|
+
axe( elements, "descendant-or-self", $' )
|
55
55
|
when /^\/?\b(\w[-\w]*)\b::/u # Axe
|
56
|
-
|
56
|
+
axe( elements, $1, $' )
|
57
57
|
when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
|
58
58
|
rest = $'
|
59
59
|
results = []
|
60
60
|
elements.each do |element|
|
61
61
|
results |= filter( element.to_a, rest )
|
62
62
|
end
|
63
|
-
|
63
|
+
results
|
64
64
|
when /^\/?(\w[-\w]*)\(/u # / Function
|
65
|
-
|
65
|
+
function( elements, $1, $' )
|
66
66
|
when Namespace::NAMESPLIT # Element name
|
67
67
|
name = $2
|
68
68
|
ns = $1
|
@@ -73,21 +73,21 @@ module REXML
|
|
73
73
|
(element.name == name and
|
74
74
|
element.namespace == Functions.namespace_context[ns])))
|
75
75
|
end
|
76
|
-
|
76
|
+
filter( elements, rest )
|
77
77
|
when /^\/\[/u
|
78
78
|
matches = []
|
79
79
|
elements.each do |element|
|
80
80
|
matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
|
81
81
|
end
|
82
|
-
|
82
|
+
matches
|
83
83
|
when /^\[/u # Predicate
|
84
|
-
|
84
|
+
predicate( elements, path )
|
85
85
|
when /^\/?\.\.\./u # Ancestor
|
86
|
-
|
86
|
+
axe( elements, "ancestor", $' )
|
87
87
|
when /^\/?\.\./u # Parent
|
88
|
-
|
88
|
+
filter( elements.collect{|e|e.parent}, $' )
|
89
89
|
when /^\/?\./u # Self
|
90
|
-
|
90
|
+
filter( elements, $' )
|
91
91
|
when /^\*/u # Any
|
92
92
|
results = []
|
93
93
|
elements.each do |element|
|
@@ -98,9 +98,10 @@ module REXML
|
|
98
98
|
# results |= filter( children, $' )
|
99
99
|
#end
|
100
100
|
end
|
101
|
-
|
101
|
+
results
|
102
|
+
else
|
103
|
+
[]
|
102
104
|
end
|
103
|
-
return []
|
104
105
|
end
|
105
106
|
|
106
107
|
def QuickPath::axe( elements, axe_name, rest )
|
@@ -138,7 +139,7 @@ module REXML
|
|
138
139
|
matches = filter(elements.collect{|element|
|
139
140
|
element.previous_sibling}.uniq, rest )
|
140
141
|
end
|
141
|
-
|
142
|
+
matches.uniq
|
142
143
|
end
|
143
144
|
|
144
145
|
OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)'
|
@@ -200,15 +201,15 @@ module REXML
|
|
200
201
|
results << element
|
201
202
|
end
|
202
203
|
end
|
203
|
-
|
204
|
+
filter( results, rest )
|
204
205
|
end
|
205
206
|
|
206
207
|
def QuickPath::attribute( name )
|
207
|
-
|
208
|
+
Functions.node.attributes[name] if Functions.node.kind_of? Element
|
208
209
|
end
|
209
210
|
|
210
211
|
def QuickPath::name()
|
211
|
-
|
212
|
+
Functions.node.name if Functions.node.kind_of? Element
|
212
213
|
end
|
213
214
|
|
214
215
|
def QuickPath::method_missing( id, *args )
|
@@ -234,7 +235,7 @@ module REXML
|
|
234
235
|
results << element if Functions.pair[0] == res
|
235
236
|
end
|
236
237
|
end
|
237
|
-
|
238
|
+
results
|
238
239
|
end
|
239
240
|
|
240
241
|
def QuickPath::parse_args( element, string )
|
data/lib/rexml/rexml.rb
CHANGED
data/lib/rexml/security.rb
CHANGED
@@ -10,7 +10,7 @@ module REXML
|
|
10
10
|
|
11
11
|
# Get the entity expansion limit. By default the limit is set to 10000.
|
12
12
|
def self.entity_expansion_limit
|
13
|
-
|
13
|
+
@@entity_expansion_limit
|
14
14
|
end
|
15
15
|
|
16
16
|
@@entity_expansion_text_limit = 10_240
|
@@ -22,7 +22,7 @@ module REXML
|
|
22
22
|
|
23
23
|
# Get the entity expansion limit. By default the limit is set to 10240.
|
24
24
|
def self.entity_expansion_text_limit
|
25
|
-
|
25
|
+
@@entity_expansion_text_limit
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/rexml/source.rb
CHANGED
@@ -65,11 +65,18 @@ module REXML
|
|
65
65
|
attr_reader :encoding
|
66
66
|
|
67
67
|
module Private
|
68
|
+
SPACES_PATTERN = /\s+/um
|
68
69
|
SCANNER_RESET_SIZE = 100000
|
69
70
|
PRE_DEFINED_TERM_PATTERNS = {}
|
70
|
-
pre_defined_terms = ["'", '"', "<"]
|
71
|
-
|
72
|
-
|
71
|
+
pre_defined_terms = ["'", '"', "<", "]]>", "?>"]
|
72
|
+
if StringScanner::Version < "3.1.1"
|
73
|
+
pre_defined_terms.each do |term|
|
74
|
+
PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/
|
75
|
+
end
|
76
|
+
else
|
77
|
+
pre_defined_terms.each do |term|
|
78
|
+
PRE_DEFINED_TERM_PATTERNS[term] = term
|
79
|
+
end
|
73
80
|
end
|
74
81
|
end
|
75
82
|
private_constant :Private
|
@@ -144,6 +151,10 @@ module REXML
|
|
144
151
|
end
|
145
152
|
end
|
146
153
|
|
154
|
+
def skip_spaces
|
155
|
+
@scanner.skip(Private::SPACES_PATTERN) ? true : false
|
156
|
+
end
|
157
|
+
|
147
158
|
def position
|
148
159
|
@scanner.pos
|
149
160
|
end
|
@@ -152,6 +163,14 @@ module REXML
|
|
152
163
|
@scanner.pos = pos
|
153
164
|
end
|
154
165
|
|
166
|
+
def peek_byte
|
167
|
+
@scanner.peek_byte
|
168
|
+
end
|
169
|
+
|
170
|
+
def scan_byte
|
171
|
+
@scanner.scan_byte
|
172
|
+
end
|
173
|
+
|
155
174
|
# @return true if the Source is exhausted
|
156
175
|
def empty?
|
157
176
|
@scanner.eos?
|