Skip to content

Commit 06be5cf

Browse files
authored
xpath: Fix wrong position with nested path (#122)
## Why? Fixed incorrect calculation of position in node set. Fix GH-25 Reported by jcavalieri. Thanks!!!
1 parent 030bfb4 commit 06be5cf

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

lib/rexml/xpath_parser.rb

+7-3
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ def filter_nodeset(nodeset)
590590

591591
def evaluate_predicate(expression, nodesets)
592592
enter(:predicate, expression, nodesets) if @debug
593+
new_nodeset_count = 0
593594
new_nodesets = nodesets.collect do |nodeset|
594595
new_nodeset = []
595596
subcontext = { :size => nodeset.size }
@@ -606,17 +607,20 @@ def evaluate_predicate(expression, nodesets)
606607
result = result[0] if result.kind_of? Array and result.length == 1
607608
if result.kind_of? Numeric
608609
if result == node.position
609-
new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
610+
new_nodeset_count += 1
611+
new_nodeset << XPathNode.new(node, position: new_nodeset_count)
610612
end
611613
elsif result.instance_of? Array
612614
if result.size > 0 and result.inject(false) {|k,s| s or k}
613615
if result.size > 0
614-
new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
616+
new_nodeset_count += 1
617+
new_nodeset << XPathNode.new(node, position: new_nodeset_count)
615618
end
616619
end
617620
else
618621
if result
619-
new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
622+
new_nodeset_count += 1
623+
new_nodeset << XPathNode.new(node, position: new_nodeset_count)
620624
end
621625
end
622626
end

test/xpath/test_base.rb

+40
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,46 @@ def test_following
451451
# puts results
452452
#end
453453

454+
def test_nested_predicates
455+
doc = Document.new <<-EOF
456+
<div>
457+
<div>
458+
<test>ab</test>
459+
<test>cd</test>
460+
</div>
461+
<div>
462+
<test>ef</test>
463+
<test>gh</test>
464+
</div>
465+
<div>
466+
<test>hi</test>
467+
</div>
468+
</div>
469+
EOF
470+
471+
matches = XPath.match(doc, '(/div/div/test[0])').map(&:text)
472+
assert_equal [], matches
473+
matches = XPath.match(doc, '(/div/div/test[1])').map(&:text)
474+
assert_equal ["ab", "ef", "hi"], matches
475+
matches = XPath.match(doc, '(/div/div/test[2])').map(&:text)
476+
assert_equal ["cd", "gh"], matches
477+
matches = XPath.match(doc, '(/div/div/test[3])').map(&:text)
478+
assert_equal [], matches
479+
480+
matches = XPath.match(doc, '(/div/div/test[1])[1]').map(&:text)
481+
assert_equal ["ab"], matches
482+
matches = XPath.match(doc, '(/div/div/test[1])[2]').map(&:text)
483+
assert_equal ["ef"], matches
484+
matches = XPath.match(doc, '(/div/div/test[1])[3]').map(&:text)
485+
assert_equal ["hi"], matches
486+
matches = XPath.match(doc, '(/div/div/test[2])[1]').map(&:text)
487+
assert_equal ["cd"], matches
488+
matches = XPath.match(doc, '(/div/div/test[2])[2]').map(&:text)
489+
assert_equal ["gh"], matches
490+
matches = XPath.match(doc, '(/div/div/test[2])[3]').map(&:text)
491+
assert_equal [], matches
492+
end
493+
454494
# Contributed by Mike Stok
455495
def test_starts_with
456496
source = <<-EOF

0 commit comments

Comments
 (0)