rexml 3.4.0 → 3.4.4
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 +169 -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 +21 -5
- 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 +167 -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 +23 -4
- 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/instruction.rb
CHANGED
@@ -49,7 +49,7 @@ module REXML
|
|
49
49
|
# See the rexml/formatters package
|
50
50
|
#
|
51
51
|
def write writer, indent=-1, transitive=false, ie_hack=false
|
52
|
-
Kernel.warn( "#{self.class.name}
|
52
|
+
Kernel.warn( "#{self.class.name}#write is deprecated", uplevel: 1)
|
53
53
|
indent(writer, indent)
|
54
54
|
writer << START
|
55
55
|
writer << @target
|
data/lib/rexml/namespace.rb
CHANGED
@@ -42,11 +42,11 @@ module REXML
|
|
42
42
|
# Compares names optionally WITH namespaces
|
43
43
|
def has_name?( other, ns=nil )
|
44
44
|
if ns
|
45
|
-
|
45
|
+
namespace() == ns and name() == other
|
46
46
|
elsif other.include? ":"
|
47
|
-
|
47
|
+
fully_expanded_name == other
|
48
48
|
else
|
49
|
-
|
49
|
+
name == other
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -57,7 +57,7 @@ module REXML
|
|
57
57
|
def fully_expanded_name
|
58
58
|
ns = prefix
|
59
59
|
return "#{ns}:#@name" if ns.size > 0
|
60
|
-
|
60
|
+
@name
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
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
|
@@ -264,6 +266,11 @@ module REXML
|
|
264
266
|
path = "/" + @tags.join("/")
|
265
267
|
raise ParseException.new("Missing end tag for '#{path}'", @source)
|
266
268
|
end
|
269
|
+
|
270
|
+
unless @document_status == :in_element
|
271
|
+
raise ParseException.new("Malformed XML: No root element", @source)
|
272
|
+
end
|
273
|
+
|
267
274
|
return [ :end_document ]
|
268
275
|
end
|
269
276
|
return @stack.shift if @stack.size > 0
|
@@ -277,17 +284,10 @@ module REXML
|
|
277
284
|
return process_instruction
|
278
285
|
elsif @source.match?("<!", true)
|
279
286
|
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] ]
|
287
|
+
return [ :comment, process_comment ]
|
288
288
|
elsif @source.match?("DOCTYPE", true)
|
289
289
|
base_error_message = "Malformed DOCTYPE"
|
290
|
-
unless @source.
|
290
|
+
unless @source.skip_spaces
|
291
291
|
if @source.match?(">")
|
292
292
|
message = "#{base_error_message}: name is missing"
|
293
293
|
else
|
@@ -297,10 +297,11 @@ module REXML
|
|
297
297
|
raise REXML::ParseException.new(message, @source)
|
298
298
|
end
|
299
299
|
name = parse_name(base_error_message)
|
300
|
-
|
300
|
+
@source.skip_spaces
|
301
|
+
if @source.match?("[", true)
|
301
302
|
id = [nil, nil, nil]
|
302
303
|
@document_status = :in_doctype
|
303
|
-
elsif @source.match?(
|
304
|
+
elsif @source.match?(">", true)
|
304
305
|
id = [nil, nil, nil]
|
305
306
|
@document_status = :after_doctype
|
306
307
|
@source.ensure_buffer
|
@@ -312,9 +313,10 @@ module REXML
|
|
312
313
|
# For backward compatibility
|
313
314
|
id[1], id[2] = id[2], nil
|
314
315
|
end
|
315
|
-
|
316
|
+
@source.skip_spaces
|
317
|
+
if @source.match?("[", true)
|
316
318
|
@document_status = :in_doctype
|
317
|
-
elsif @source.match?(
|
319
|
+
elsif @source.match?(">", true)
|
318
320
|
@document_status = :after_doctype
|
319
321
|
@source.ensure_buffer
|
320
322
|
else
|
@@ -324,7 +326,7 @@ module REXML
|
|
324
326
|
end
|
325
327
|
args = [:start_doctype, name, *id]
|
326
328
|
if @document_status == :after_doctype
|
327
|
-
@source.
|
329
|
+
@source.skip_spaces
|
328
330
|
@stack << [ :end_doctype ]
|
329
331
|
end
|
330
332
|
return args
|
@@ -335,7 +337,7 @@ module REXML
|
|
335
337
|
end
|
336
338
|
end
|
337
339
|
if @document_status == :in_doctype
|
338
|
-
@source.
|
340
|
+
@source.skip_spaces
|
339
341
|
start_position = @source.position
|
340
342
|
if @source.match?("<!", true)
|
341
343
|
if @source.match?("ELEMENT", true)
|
@@ -378,7 +380,7 @@ module REXML
|
|
378
380
|
md = @source.match(Private::ATTLISTDECL_END, true)
|
379
381
|
raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
|
380
382
|
element = md[1]
|
381
|
-
contents = md[0]
|
383
|
+
contents = "<!ATTLIST" + md[0]
|
382
384
|
|
383
385
|
pairs = {}
|
384
386
|
values = md[0].strip.scan( ATTDEF_RE )
|
@@ -396,7 +398,7 @@ module REXML
|
|
396
398
|
return [ :attlistdecl, element, pairs, contents ]
|
397
399
|
elsif @source.match?("NOTATION", true)
|
398
400
|
base_error_message = "Malformed notation declaration"
|
399
|
-
unless @source.
|
401
|
+
unless @source.skip_spaces
|
400
402
|
if @source.match?(">")
|
401
403
|
message = "#{base_error_message}: name is missing"
|
402
404
|
else
|
@@ -409,30 +411,28 @@ module REXML
|
|
409
411
|
id = parse_id(base_error_message,
|
410
412
|
accept_external_id: true,
|
411
413
|
accept_public_id: true)
|
412
|
-
|
414
|
+
@source.skip_spaces
|
415
|
+
unless @source.match?(">", true)
|
413
416
|
message = "#{base_error_message}: garbage before end >"
|
414
417
|
raise REXML::ParseException.new(message, @source)
|
415
418
|
end
|
416
419
|
return [:notationdecl, name, *id]
|
417
|
-
elsif
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
end
|
422
|
-
return [ :comment, md[1] ] if md
|
420
|
+
elsif @source.match?("--", true)
|
421
|
+
return [ :comment, process_comment ]
|
422
|
+
else
|
423
|
+
raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor ELEMENT,ENTITY,ATTLIST,NOTATION", @source)
|
423
424
|
end
|
424
425
|
elsif match = @source.match(/(%.*?;)\s*/um, true)
|
425
426
|
return [ :externalentity, match[1] ]
|
426
427
|
elsif @source.match?(/\]\s*>/um, true)
|
427
428
|
@document_status = :after_doctype
|
428
429
|
return [ :end_doctype ]
|
429
|
-
|
430
|
-
if @document_status == :in_doctype
|
430
|
+
else
|
431
431
|
raise ParseException.new("Malformed DOCTYPE: invalid declaration", @source)
|
432
432
|
end
|
433
433
|
end
|
434
434
|
if @document_status == :after_doctype
|
435
|
-
@source.
|
435
|
+
@source.skip_spaces
|
436
436
|
end
|
437
437
|
begin
|
438
438
|
start_position = @source.position
|
@@ -457,23 +457,19 @@ module REXML
|
|
457
457
|
end
|
458
458
|
return [ :end_element, last_tag ]
|
459
459
|
elsif @source.match?("!", true)
|
460
|
-
md = @source.match(/([^>]*>)/um)
|
461
460
|
#STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
if
|
467
|
-
|
461
|
+
if @source.match?("--", true)
|
462
|
+
return [ :comment, process_comment ]
|
463
|
+
elsif @source.match?("[CDATA[", true)
|
464
|
+
text = @source.read_until("]]>")
|
465
|
+
if text.chomp!("]]>")
|
466
|
+
return [ :cdata, text ]
|
467
|
+
else
|
468
|
+
raise REXML::ParseException.new("Malformed CDATA: Missing end ']]>'", @source)
|
468
469
|
end
|
469
|
-
|
470
|
-
return [ :comment, md[1] ]
|
471
470
|
else
|
472
|
-
|
473
|
-
return [ :cdata, md[1] ] if md
|
471
|
+
raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor CDATA", @source)
|
474
472
|
end
|
475
|
-
raise REXML::ParseException.new( "Declarations can only occur "+
|
476
|
-
"in the doctype declaration.", @source)
|
477
473
|
elsif @source.match?("?", true)
|
478
474
|
return process_instruction
|
479
475
|
else
|
@@ -533,7 +529,8 @@ module REXML
|
|
533
529
|
raise REXML::ParseException.new( "Exception parsing",
|
534
530
|
@source, self, (error ? error : $!) )
|
535
531
|
end
|
536
|
-
|
532
|
+
# NOTE: The end of the method never runs, because it is unreachable.
|
533
|
+
# All branches of code above have explicit unconditional return or raise statements.
|
537
534
|
end
|
538
535
|
private :pull_event
|
539
536
|
|
@@ -652,6 +649,10 @@ module REXML
|
|
652
649
|
true
|
653
650
|
end
|
654
651
|
|
652
|
+
def normalize_xml_declaration_encoding(xml_declaration_encoding)
|
653
|
+
/\AUTF-16(?:BE|LE)\z/i.match?(xml_declaration_encoding) ? "UTF-16" : nil
|
654
|
+
end
|
655
|
+
|
655
656
|
def parse_name(base_error_message)
|
656
657
|
md = @source.match(Private::NAME_PATTERN, true)
|
657
658
|
unless md
|
@@ -731,39 +732,137 @@ module REXML
|
|
731
732
|
end
|
732
733
|
end
|
733
734
|
|
735
|
+
def process_comment
|
736
|
+
text = @source.read_until("-->")
|
737
|
+
unless text.chomp!("-->")
|
738
|
+
raise REXML::ParseException.new("Unclosed comment: Missing end '-->'", @source)
|
739
|
+
end
|
740
|
+
|
741
|
+
if text.include? "--" or text.end_with?("-")
|
742
|
+
raise REXML::ParseException.new("Malformed comment", @source)
|
743
|
+
end
|
744
|
+
text
|
745
|
+
end
|
746
|
+
|
734
747
|
def process_instruction
|
735
748
|
name = parse_name("Malformed XML: Invalid processing instruction node")
|
736
|
-
if
|
737
|
-
|
738
|
-
|
739
|
-
|
749
|
+
if name == "xml"
|
750
|
+
xml_declaration
|
751
|
+
else # PITarget
|
752
|
+
if @source.skip_spaces # e.g. <?name content?>
|
753
|
+
start_position = @source.position
|
754
|
+
content = @source.read_until("?>")
|
755
|
+
unless content.chomp!("?>")
|
756
|
+
@source.position = start_position
|
757
|
+
raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
|
758
|
+
end
|
759
|
+
else # e.g. <?name?>
|
760
|
+
content = nil
|
761
|
+
unless @source.match?("?>", true)
|
762
|
+
raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
|
763
|
+
end
|
740
764
|
end
|
741
|
-
|
742
|
-
|
743
|
-
|
765
|
+
[:processing_instruction, name, content]
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
def xml_declaration
|
770
|
+
unless @version.nil?
|
771
|
+
raise ParseException.new("Malformed XML: XML declaration is duplicated", @source)
|
772
|
+
end
|
773
|
+
if @document_status
|
774
|
+
raise ParseException.new("Malformed XML: XML declaration is not at the start", @source)
|
775
|
+
end
|
776
|
+
unless @source.skip_spaces
|
777
|
+
raise ParseException.new("Malformed XML: XML declaration misses spaces before version", @source)
|
778
|
+
end
|
779
|
+
unless @source.match?("version", true)
|
780
|
+
raise ParseException.new("Malformed XML: XML declaration misses version", @source)
|
781
|
+
end
|
782
|
+
@version = parse_attribute_value_with_equal("xml")
|
783
|
+
unless @source.skip_spaces
|
744
784
|
unless @source.match?("?>", true)
|
745
|
-
raise ParseException.new("Malformed XML: Unclosed
|
785
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
746
786
|
end
|
787
|
+
encoding = normalize_xml_declaration_encoding(@source.encoding)
|
788
|
+
return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.0"?>
|
747
789
|
end
|
748
|
-
|
749
|
-
|
750
|
-
|
790
|
+
|
791
|
+
if @source.match?("encoding", true)
|
792
|
+
encoding = parse_attribute_value_with_equal("xml")
|
793
|
+
unless @source.skip_spaces
|
794
|
+
unless @source.match?("?>", true)
|
795
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
796
|
+
end
|
797
|
+
if need_source_encoding_update?(encoding)
|
798
|
+
@source.encoding = encoding
|
799
|
+
end
|
800
|
+
encoding ||= normalize_xml_declaration_encoding(@source.encoding)
|
801
|
+
return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.1" encoding="UTF-8"?>
|
751
802
|
end
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
803
|
+
end
|
804
|
+
|
805
|
+
if @source.match?("standalone", true)
|
806
|
+
standalone = parse_attribute_value_with_equal("xml")
|
807
|
+
case standalone
|
808
|
+
when "yes", "no"
|
809
|
+
else
|
810
|
+
raise ParseException.new("Malformed XML: XML declaration standalone is not yes or no : <#{standalone}>", @source)
|
758
811
|
end
|
759
|
-
|
760
|
-
|
812
|
+
end
|
813
|
+
@source.skip_spaces
|
814
|
+
unless @source.match?("?>", true)
|
815
|
+
raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
|
816
|
+
end
|
817
|
+
|
818
|
+
if need_source_encoding_update?(encoding)
|
819
|
+
@source.encoding = encoding
|
820
|
+
end
|
821
|
+
encoding ||= normalize_xml_declaration_encoding(@source.encoding)
|
822
|
+
|
823
|
+
# e.g. <?xml version="1.0" ?>
|
824
|
+
# <?xml version="1.1" encoding="UTF-8" ?>
|
825
|
+
# <?xml version="1.1" standalone="yes"?>
|
826
|
+
# <?xml version="1.1" encoding="UTF-8" standalone="yes" ?>
|
827
|
+
[ :xmldecl, @version, encoding, standalone ]
|
828
|
+
end
|
829
|
+
|
830
|
+
if StringScanner::Version < "3.1.1"
|
831
|
+
def scan_quote
|
832
|
+
@source.match(/(['"])/, true)&.[](1)
|
833
|
+
end
|
834
|
+
else
|
835
|
+
def scan_quote
|
836
|
+
case @source.peek_byte
|
837
|
+
when 34 # '"'.ord
|
838
|
+
@source.scan_byte
|
839
|
+
'"'
|
840
|
+
when 39 # "'".ord
|
841
|
+
@source.scan_byte
|
842
|
+
"'"
|
843
|
+
else
|
844
|
+
nil
|
761
845
|
end
|
762
|
-
standalone = STANDALONE.match(content)
|
763
|
-
standalone = standalone[1] unless standalone.nil?
|
764
|
-
return [ :xmldecl, version, encoding, standalone ]
|
765
846
|
end
|
766
|
-
|
847
|
+
end
|
848
|
+
|
849
|
+
def parse_attribute_value_with_equal(name)
|
850
|
+
unless @source.match?(Private::EQUAL_PATTERN, true)
|
851
|
+
message = "Missing attribute equal: <#{name}>"
|
852
|
+
raise REXML::ParseException.new(message, @source)
|
853
|
+
end
|
854
|
+
unless quote = scan_quote
|
855
|
+
message = "Missing attribute value start quote: <#{name}>"
|
856
|
+
raise REXML::ParseException.new(message, @source)
|
857
|
+
end
|
858
|
+
start_position = @source.position
|
859
|
+
value = @source.read_until(quote)
|
860
|
+
unless value.chomp!(quote)
|
861
|
+
@source.position = start_position
|
862
|
+
message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
|
863
|
+
raise REXML::ParseException.new(message, @source)
|
864
|
+
end
|
865
|
+
value
|
767
866
|
end
|
768
867
|
|
769
868
|
def parse_attributes(prefixes)
|
@@ -780,24 +879,8 @@ module REXML
|
|
780
879
|
name = match[1]
|
781
880
|
prefix = match[2]
|
782
881
|
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)
|
882
|
+
value = parse_attribute_value_with_equal(name)
|
883
|
+
@source.skip_spaces
|
801
884
|
if prefix == "xmlns"
|
802
885
|
if local_part == "xml"
|
803
886
|
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
|