class REXML::XPathParser

def node_test(path_stack, nodesets, any_type: :element)

def node_test(path_stack, nodesets, any_type: :element)
  enter(:node_test, path_stack, nodesets) if @debug
  operator = path_stack.shift
  case operator
  when :qname
    prefix = path_stack.shift
    name = path_stack.shift
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        case raw_node.node_type
        when :element
          if prefix.nil?
            raw_node.name == name
          elsif prefix.empty?
            if strict?
              raw_node.name == name and raw_node.namespace == ""
            else
              # FIXME: This DOUBLES the time XPath searches take
              ns = get_namespace(raw_node, prefix)
              raw_node.name == name and raw_node.namespace == ns
            end
          else
            # FIXME: This DOUBLES the time XPath searches take
            ns = get_namespace(raw_node, prefix)
            raw_node.name == name and raw_node.namespace == ns
          end
        when :attribute
          if prefix.nil?
            raw_node.name == name
          elsif prefix.empty?
            raw_node.name == name and raw_node.namespace == ""
          else
            # FIXME: This DOUBLES the time XPath searches take
            ns = get_namespace(raw_node.element, prefix)
            raw_node.name == name and raw_node.namespace == ns
          end
        else
          false
        end
      end
    end
  when :namespace
    prefix = path_stack.shift
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        case raw_node.node_type
        when :element
          namespaces = @namespaces || raw_node.namespaces
          raw_node.namespace == namespaces[prefix]
        when :attribute
          namespaces = @namespaces || raw_node.element.namespaces
          raw_node.namespace == namespaces[prefix]
        else
          false
        end
      end
    end
  when :any
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        raw_node.node_type == any_type
      end
    end
  when :comment
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        raw_node.node_type == :comment
      end
    end
  when :text
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        raw_node.node_type == :text
      end
    end
  when :processing_instruction
    target = path_stack.shift
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        raw_node = node.raw_node
        (raw_node.node_type == :processing_instruction) and
          (target.empty? or (raw_node.target == target))
      end
    end
  when :node
    new_nodesets = nodesets.collect do |nodeset|
      filter_nodeset(nodeset) do |node|
        true
      end
    end
  else
    message = "[BUG] Unexpected node test: " +
      "<#{operator.inspect}>: <#{path_stack.inspect}>"
    raise message
  end
  new_nodesets
ensure
  leave(:node_test, path_stack, new_nodesets) if @debug
end