diff --git a/lib/oga/xpath/compiler.rb b/lib/oga/xpath/compiler.rb
index 2fc22cf..ec711b3 100644
--- a/lib/oga/xpath/compiler.rb
+++ b/lib/oga/xpath/compiler.rb
@@ -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
diff --git a/spec/oga/xpath/compiler/operators/pipe_spec.rb b/spec/oga/xpath/compiler/operators/pipe_spec.rb
index 40bbb65..b9ebbed 100644
--- a/spec/oga/xpath/compiler/operators/pipe_spec.rb
+++ b/spec/oga/xpath/compiler/operators/pipe_spec.rb
@@ -3,10 +3,12 @@ require 'spec_helper'
describe Oga::XPath::Compiler do
describe 'pipe operator' do
before do
- @document = parse('')
+ @document = parse('')
- @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