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:
parent
40501f9522
commit
6d3c5c2ce9
|
@ -590,16 +590,20 @@ module Oga
|
|||
def on_pipe(ast, input, &block)
|
||||
left, right = *ast
|
||||
|
||||
union = unique_literal(:union)
|
||||
conversion = literal(Conversion)
|
||||
union = unique_literal(:union)
|
||||
|
||||
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
|
||||
end
|
||||
# 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(union)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [AST::Node] ast
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue