XPath support for nested pipe operators

Basically this will process the left-hand side first, assign the result
to a variable and then append this set with the nodes from the
right-hand side.

Fixes #149
This commit is contained in:
Yorick Peterse 2016-02-23 22:24:07 +01:00
parent 40501f9522
commit 6d3c5c2ce9
2 changed files with 44 additions and 12 deletions

View File

@ -591,14 +591,18 @@ module Oga
left, right = *ast
union = unique_literal(:union)
conversion = literal(Conversion)
# Expressions such as "a | b | c"
if left.type == :pipe
union.assign(process(left, input))
.followed_by(process(right, input) { |node| union << node })
.followed_by(union)
# Expressions such as "a | b"
else
union.assign(literal(XML::NodeSet).new)
.followed_by(process(left, input) { |node| union << node })
.followed_by(process(right, input) { |node| union << node })
.followed_by do
# block present means we're in a predicate
block ? conversion.to_boolean(union).if_true(&block) : union
.followed_by(union)
end
end

View File

@ -3,10 +3,12 @@ require 'spec_helper'
describe Oga::XPath::Compiler do
describe 'pipe operator' do
before do
@document = parse('<root><a></a><b></b></root>')
@document = parse('<root><a></a><b></b><c></c></root>')
@a1 = @document.children[0].children[0]
@b1 = @document.children[0].children[1]
@root = @document.children[0]
@a1 = @root.children[0]
@b1 = @root.children[1]
@c1 = @root.children[2]
end
it 'merges two node sets' do
@ -24,5 +26,31 @@ describe Oga::XPath::Compiler do
it 'merges two identical sets' do
evaluate_xpath(@document, 'root/a | root/a').should == node_set(@a1)
end
it 'merges three sets' do
evaluate_xpath(@document, 'root/a | root/b | root/c')
.should == node_set(@a1, @b1, @c1)
end
it 'merges three identical sets' do
evaluate_xpath(@document, 'root/a | root/a | root/a')
.should == node_set(@a1)
end
it 'merges two non-empty sets in a predicate' do
evaluate_xpath(@document, 'root[a | b]').should == node_set(@root)
end
it 'merges three non-empty sets in a predicate' do
evaluate_xpath(@document, 'root[a | b | c]').should == node_set(@root)
end
it 'merges two empty sets in a predicate' do
evaluate_xpath(@document, 'root[x | y]').should == node_set
end
it 'merges three empty sets in a predicate' do
evaluate_xpath(@document, 'root[x | y | z]').should == node_set
end
end
end