module Hpricot::Traverse

def self.filter(tok, &blk)

def self.filter(tok, &blk)
  define_method("filter[#{tok.is_a?(String) ? tok : tok.inspect}]", &blk)
end

def after(html = nil, &blk)

Adds elements immediately after this element, contained in the +html+ string.
def after(html = nil, &blk)
  parent.insert_after(make(html, &blk), self)
end

def at(expr)

+expr+ string.
Find the first matching node for the CSS or XPath
def at(expr)
  search(expr).first
end

def before(html = nil, &blk)

Adds elements immediately before this element, contained in the +html+ string.
def before(html = nil, &blk)
  parent.insert_before(make(html, &blk), self)
end

def bogusetag?() BogusETag::Trav === self end

Is this object a stranded end tag?
def bogusetag?() BogusETag::Trav === self end

def children_of_type(tag_name)


#=> [...array of paragraphs...]
ele.children_of_type('p')

Find children of a given +tag_name+.
def children_of_type(tag_name)
  if respond_to? :children
    children.find_all do |x|
      x.respond_to?(:pathname) && x.pathname == tag_name
    end
  end
end

def clean_path(path)

def clean_path(path)
  path.gsub(/^\s+|\s+$/, '')
end

def comment?() Comment::Trav === self end

Is this object a comment?
def comment?() Comment::Trav === self end

def css_path

root of the document containing it.
Builds a unique CSS string for this node, from the
def css_path
  if elem? and has_attribute? 'id'
    "##{get_attribute('id')}"
  else
    sim, i, id = 0, 0, 0
    parent.children.each do |e|
      id = sim if e == self
      sim += 1 if e.pathname == self.pathname
    end
    p = parent.css_path
    p = p ? "#{p} > #{self.pathname}" : self.pathname
    p += ":nth(#{id})" if sim >= 2
    p
  end
end

def doc?() Doc::Trav === self end

Is this object the enclosing HTML or XML document?
def doc?() Doc::Trav === self end

def doctype?() DocType::Trav === self end

Is this object a doctype tag?
def doctype?() DocType::Trav === self end

def elem?() Elem::Trav === self end

Is this object an HTML or XML element?
def elem?() Elem::Trav === self end

def following

Find all nodes which follow the current one.
def following
  sibs = parent.children 
  si = sibs.index(self) + 1 
  return Elements[*sibs[si...sibs.length]] 
end 

def get_subnode(*indexes)

def get_subnode(*indexes)
  n = self
  indexes.each {|index|
    n = n.get_subnode_internal(index)
  }
  n
end

def html(inner = nil, &blk)

Builds an HTML string from the contents of this node.
def html(inner = nil, &blk)
  if inner or blk
    altered!
    case inner
    when Array
      self.children = inner
    else
      self.children = make(inner, &blk)
    end
    reparent self.children
  else
    if respond_to? :children
      children.map { |x| x.output("") }.join
    end
  end
end

def index(name)

def index(name)
  i = 0
  return i if name == "*"
  children.each do |x|
    return i if (x.respond_to?(:name) and name == x.name) or
      (x.text? and name == "text()")
    i += 1
  end
  -1
end

def inner_html=(inner)

the HTML contained in string +inner+.
Inserts new contents into the current node, based on
def inner_html=(inner)
  html(inner || [])
end

def inner_text

HTML elements are removed.
Builds a string from the text contained in this node. All
def inner_text
  if respond_to? :children
    children.map { |x| x.inner_text }.join
  end
end

def make(input = nil, &blk)

the options used to create the container document.
Parses an HTML string, making an HTML fragment based on
def make(input = nil, &blk)
  if parent and parent.respond_to? :make
    parent.make(input, &blk)
  else
    Hpricot.make(input, &blk)
  end
end

def next

This method includes text nodes and comments and such.
Returns the node neighboring this node to the south: just below it.
def next
  sib = parent.children
  sib[sib.index(self) + 1] if parent
end

def node_position

def node_position
  parent.children.index(self)
end

def nodes_at(*pos)

ele.nodes_at(0, 5..6) # the current node and two others
ele.nodes_at(1, 5, 7) # gets three nodes at offsets below the current node
ele.nodes_at(-3..-1, 1..3) # gets three nodes before and three after

This method also accepts ranges and sets of numbers.

nodes_at(1). Or, to get the previous node, use nodes_at(1).
to this node. So, for example, to get the next node, you could use
Puts together an array of neighboring nodes based on their proximity
def nodes_at(*pos)
  sib = parent.children
  i, si = 0, sib.index(self)
  pos.map! do |r|
    if r.is_a?(Range) and r.begin.is_a?(String)
      r = Range.new(parent.index(r.begin)-si, parent.index(r.end)-si, r.exclude_end?)
    end
    r
  end
  p pos
  Elements[*
    sib.select do |x|
      sel =
        case i - si when *pos
          true
        end
      i += 1
      sel
    end
  ]
end

def position

def position
  parent.children_of_type(self.pathname).index(self)
end

def preceding

Find all preceding nodes.
def preceding
  sibs = parent.children
  si = sibs.index(self) 
  return Elements[*sibs[0...si]] 
end 

def previous

This method includes text nodes and comments and such.
Returns to node neighboring this node to the north: just above it.
def previous
  sib = parent.children
  x = sib.index(self) - 1
  sib[x] if sib and x >= 0
end

def procins?() ProcIns::Trav === self end

Is this object an XML processing instruction?
def procins?() ProcIns::Trav === self end

def reparent(nodes)

def reparent(nodes)
  altered!
  [*nodes].each { |e| e.parent = self }
end

def search(expr, &blk)

is used to iterate through the matching set.
containing the matching nodes. If +blk+ is given, it
the CSS or XPath +expr+. Returns an Elements array
Searches this node for all elements matching
def search(expr, &blk)
  if Range === expr
    return Elements.expand(at(expr.begin), at(expr.end), expr.exclude_end?)
  end
  last = nil
  nodes = [self]
  done = []
  expr = expr.to_s
  hist = []
  until expr.empty?
      expr = clean_path(expr)
      expr.gsub!(%r!^//!, '')
      case expr
      when %r!^/?\.\.!
          last = expr = $'
          nodes.map! { |node| node.parent }
      when %r!^[>/]\s*!
          last = expr = $'
          nodes = Elements[*nodes.map { |node| node.children if node.respond_to? :children }.flatten.compact]
      when %r!^\+!
          last = expr = $'
          nodes.map! do |node|
              siblings = node.parent.children
              siblings[siblings.index(node)+1]
          end
          nodes.compact!
      when %r!^~!
          last = expr = $'
          nodes.map! do |node|
              siblings = node.parent.children
              siblings[(siblings.index(node)+1)..-1]
          end
          nodes.flatten!
      when %r!^[|,]!
          last = expr = " #$'"
          nodes.shift if nodes.first == self
          done += nodes
          nodes = [self]
      else
          m = expr.match(%r!^([#.]?)([a-z0-9\\*_-]*)!i).to_a
          after = $'
          mt = after[%r!:[a-z0-9\\*_-]+!i, 0]
          oop = false
          if mt and not (mt == ":not" or Traverse.method_defined? "filter[#{mt}]")
            after = $' 
            m[2] += mt
            expr = after
          end
          if m[1] == '#'
              oid = get_element_by_id(m[2])
              nodes = oid ? [oid] : []
              expr = after
          else
              m[2] = "*" if after =~ /^\(\)/ || m[2] == "" || m[1] == "."
              ret = []
              nodes.each do |node|
                  case m[2]
                  when '*'
                      node.traverse_element { |n| ret << n }
                  else
                      if node.respond_to? :get_elements_by_tag_name
                        ret += [*node.get_elements_by_tag_name(m[2])] - [*(node unless last)]
                      end
                  end
              end
              nodes = ret
          end
          last = nil
      end
      hist << expr
      break if hist[-1] == hist[-2]
      nodes, expr = Elements.filter(nodes, expr)
  end
  nodes = done + nodes.flatten.uniq
  if blk
      nodes.each(&blk)
      self
  else
      Elements[*nodes]
  end
end

def swap(html = nil, &blk)

in the +html+ string.
Replace this element and its contents with the nodes contained
def swap(html = nil, &blk)
  parent.altered!
  parent.replace_child(self, make(html, &blk))
end

def text?() Text::Trav === self end

Is this object an HTML text node?
def text?() Text::Trav === self end

def to_html

as a method on this object.
If you need to write to a stream, try calling output(io)
Builds an HTML string from this node and its contents.
def to_html
  output("")
end

def to_original_html

outputing new tags for elements which have changed.
Attempts to preserve the original HTML of the document, only
def to_original_html
  output("", :preserve => true)
end

def to_plain_text

HTML elements are removed.
Builds a string from the text contained in this node. All
def to_plain_text
  if respond_to? :children
    children.map { |x| x.to_plain_text }.join.strip.gsub(/\n{2,}/, "\n\n")
  end
end

def traverse_element(*names, &block) # :yields: element

:yields: element

{emptyelem <{http://www.w3.org/1999/xhtml}meta name="author" content="Who am I?">}
{emptyelem <{http://www.w3.org/1999/xhtml}meta name="robots" content="index,nofollow">}
# =>
t.traverse_element("{http://www.w3.org/1999/xhtml}meta") {|e| p e}
End




t = Hpricot(<<'End')

Universal names are specified as follows.

{emptyelem }
{emptyelem }
{elem
{elem {emptyelem } } {emptyelem } }
# =>
t.traverse_element("a", "c") {|e| p e}
t = Hpricot('')

A nested element is yielded in depth first order as follows.

If non-empty _names_ are given, it should be list of universal names.
If _names_ are empty, it yields all elements.

It yields elements in depth first order.
+traverse_element+ traverses elements in the tree.
def traverse_element(*names, &block) # :yields: element
  if names.empty?
    traverse_all_element(&block)
  else
    name_set = {}
    names.each {|n| name_set[n] = true }
    traverse_some_element(name_set, &block)
  end
  nil
end

def traverse_text(&block) # :yields: text

:yields: text
+traverse_text+ traverses texts in the tree
def traverse_text(&block) # :yields: text
  traverse_text_internal(&block)
  nil
end

def xmldecl?() XMLDecl::Trav === self end

Is this object an XML declaration?
def xmldecl?() XMLDecl::Trav === self end

def xpath

root of the document containing it.
Builds a unique XPath string for this node, from the
def xpath
  if elem? and has_attribute? 'id'
    "//#{self.name}[@id='#{get_attribute('id')}']"
  else
    sim, id = 0, 0, 0
    parent.children.each do |e|
      id = sim if e == self
      sim += 1 if e.pathname == self.pathname
    end
    p = File.join(parent.xpath, self.pathname)
    p += "[#{id+1}]" if sim >= 2
    p
  end
end