Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/rexml/functions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def Functions::get_namespace( node_set = nil )
else
if node_set.respond_to? :each
result = []
node_set.each do |node|
XPathParser.sort(node_set.to_a).each do |node|
result << yield(node) if node.respond_to?(:namespace)
end
Comment on lines +87 to 89
result
Expand Down Expand Up @@ -146,7 +146,7 @@ def Functions::string( object=@@context[:node] )
else
case object
when Array
string(object[0])
string(XPathParser.sort(object)[0])
when Float
if object.nan?
"NaN"
Expand Down
36 changes: 17 additions & 19 deletions lib/rexml/xpath_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def match(path_stack, node)
result = expr(path_stack, nodeset)
case result
when Array # nodeset
result.uniq
XPathParser.sort(result)
else
[result]
end
Comment on lines 155 to 161
Expand Down Expand Up @@ -198,7 +198,7 @@ def expr( path_stack, nodeset, context=nil )
nodeset = [nodeset.first.root_node]
when :self
nodeset = step(path_stack) do
[nodeset]
[XPathParser.sort(nodeset)]
end
when :child
nodeset = step(path_stack) do
Expand Down Expand Up @@ -234,7 +234,7 @@ def expr( path_stack, nodeset, context=nil )
nodesets
end
when :ancestor
nodeset = step(path_stack, axis_order: :reverse) do
nodeset = step(path_stack) do
nodesets = []
# new_nodes = {}
nodeset.each do |node|
Comment on lines 236 to 240
Expand All @@ -250,7 +250,7 @@ def expr( path_stack, nodeset, context=nil )
nodesets
end
when :ancestor_or_self
nodeset = step(path_stack, axis_order: :reverse) do
nodeset = step(path_stack) do
nodesets = []
# new_nodes = {}
nodeset.each do |node|
Expand Down Expand Up @@ -288,7 +288,7 @@ def expr( path_stack, nodeset, context=nil )
end.compact
end
when :preceding_sibling
nodeset = step(path_stack, axis_order: :reverse) do
nodeset = step(path_stack) do
nodeset.map do |node|
next unless node.respond_to?(:parent)
next if node.parent.nil?
Comment on lines +291 to 294
Expand All @@ -300,7 +300,7 @@ def expr( path_stack, nodeset, context=nil )
end.compact
end
when :preceding
nodeset = step(path_stack, axis_order: :reverse) do
nodeset = step(path_stack) do
nodeset.map do |node|
preceding(node)
end
Expand Down Expand Up @@ -393,7 +393,7 @@ def expr( path_stack, nodeset, context=nil )
# If result is a nodeset, apply following predicates
path_stack.unshift(:node)
nodeset = step(path_stack) do
[result]
[XPathParser.sort(result)]
end
else
return result
Expand All @@ -407,7 +407,7 @@ def expr( path_stack, nodeset, context=nil )
leave(:expr, path_stack, nodeset) if @debug
end

def step(path_stack, any_type: :element, axis_order: :forward)
def step(path_stack, any_type: :element)
nodesets = yield
begin
enter(:step, path_stack, nodesets) if @debug
Expand All @@ -417,18 +417,14 @@ def step(path_stack, any_type: :element, axis_order: :forward)
predicate_expression = path_stack.shift.dclone
nodesets = evaluate_predicate(predicate_expression, nodesets)
end
if nodesets.size == 1
new_nodeset = axis_order == :forward ? nodesets.first : nodesets.first.reverse
else
nodes = Set.new.compare_by_identity
nodesets.each do |nodeset|
nodeset.each do |node|
nodes << node
end

nodes = Set.new.compare_by_identity
nodesets.each do |nodeset|
nodeset.each do |node|
nodes << node
end
new_nodeset = sort(nodes.to_a)
end
new_nodeset
new_nodeset = nodes.to_a
ensure
leave(:step, path_stack, new_nodeset) if @debug
end
Expand Down Expand Up @@ -579,7 +575,9 @@ def leave(tag, *args)
# in and out of function calls. If I knew what the index of the nodes was,
# I wouldn't have to do this. Maybe add a document IDX for each node?
# Problems with mutable documents. Or, rewrite everything.
def sort(array_of_nodes)
def self.sort(array_of_nodes)
return array_of_nodes if array_of_nodes.size <= 1

new_arry = []
array_of_nodes.each { |node|
node_idx = []
Expand Down
7 changes: 7 additions & 0 deletions test/test_jaxen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ def process_value_of(context, variables, namespaces, value_of)
xpath = value_of.attributes["select"]
matched = XPath.match(context, xpath, namespaces, variables, strict: true)

# XPath.match can be a nodeset or a primitive value wrapped in an array.
# We need to unwrap primitive value because Functions doesn't accept array which is not a nodeset.
unless matched.all? { |node| node.is_a?(REXML::Node) }
raise "[BUG] Primitive value should be a single value: #{matched.inspect}" if matched.size != 1
matched = matched.first
end

message = user_message(context, xpath, matched)
assert_equal(expected || "",
REXML::Functions.string(matched),
Expand Down
Loading