Module: Hpricot::Traverse

Module | Hpricot::Traverse
In: | lib/hpricot/traverse.rb lib/hpricot/elements.rb lib/hpricot/modules.rb

### Methods

% / after at before bogusetag? children_of_type clean_path comment? css_path doc? doctype? elem? filter following get_subnode html index innerHTML innerHTML= innerText inner_html inner_html= inner_text make next next_node node_position nodes_at position preceding previous previous_node procins? search swap text? to_html to_original_html to_plain_text to_s traverse_element traverse_text xmldecl? xpath

### Public Class methods

filter(tok, &blk)

[Source]

    # File lib/hpricot/elements.rb, line 371
        def self.filter(tok, &blk)
          define_method("filter[#{tok.is_a?(String) ? tok : tok.inspect}]", &blk)
        end

### Public Instance methods

%(expr)

Alias for at

/(expr, &blk)

Alias for search

after(html = nil, &blk)

Adds elements immediately after this element, contained in the `html` string.

[Source]

    # File lib/hpricot/traverse.rb, line 121
        def after(html = nil, &blk)
          parent.insert_after(make(html, &blk), self)
        end

at(expr)

Find the first matching node for the CSS or XPath `expr` string.

[Source]

    # File lib/hpricot/traverse.rb, line 340
        def at(expr)
          search(expr).first
        end

before(html = nil, &blk)

Adds elements immediately before this element, contained in the `html` string.

[Source]

    # File lib/hpricot/traverse.rb, line 126
        def before(html = nil, &blk)
          parent.insert_before(make(html, &blk), self)
        end

bogusetag?()

Is this object a stranded end tag?

[Source]

    # File lib/hpricot/traverse.rb, line 21
        def bogusetag?() BogusETag::Trav === self end

children_of_type(tag_name)

Find children of a given `tag_name`.

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

[Source]

    # File lib/hpricot/traverse.rb, line 389
        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

clean_path(path)

[Source]

    # File lib/hpricot/traverse.rb, line 202
        def clean_path(path)
          path.gsub(/^\s+|\s+$/, '')
        end

comment?()

Is this object a comment?

[Source]

    # File lib/hpricot/traverse.rb, line 19
        def comment?() Comment::Trav === self end

css_path()

Builds a unique CSS string for this node, from the root of the document containing it.

[Source]

    # File lib/hpricot/traverse.rb, line 225
        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 if parent.children
            p = parent.css_path
            p = p ? "#{p} > #{self.pathname}" : self.pathname
            p += ":nth(#{id})" if sim >= 2
            p
          end
        end

doc?()

Is this object the enclosing HTML or XML document?

[Source]

    # File lib/hpricot/traverse.rb, line 7
        def doc?() Doc::Trav === self end

doctype?()

Is this object a doctype tag?

[Source]

    # File lib/hpricot/traverse.rb, line 15
        def doctype?() DocType::Trav === self end

elem?()

Is this object an HTML or XML element?

[Source]

    # File lib/hpricot/traverse.rb, line 9
        def elem?() Elem::Trav === self end

following()

Find all nodes which follow the current one.

[Source]

    # File lib/hpricot/traverse.rb, line 114
        def following
          sibs = parent.children
          si = sibs.index(self) + 1
          return Elements[*sibs[si...sibs.length]]
        end

get_subnode(*indexes)

[Source]

    # File lib/hpricot/traverse.rb, line 138
        def get_subnode(*indexes)
          n = self
          indexes.each {|index|
            n = n.get_subnode_internal(index)
          }
          n
        end

html(inner = nil, &blk)

Builds an HTML string from the contents of this node.

[Source]

    # File lib/hpricot/traverse.rb, line 168
        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) and children
              children.map { |x| x.output("") }.join
            else
              ""
            end
          end
        end

index(name)

[Source]

    # File lib/hpricot/traverse.rb, line 47
        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 if children
          -1
        end

innerHTML(inner = nil, &blk)

Alias for inner_html

innerHTML=(inner)

Alias for inner_html=

innerText()

Alias for inner_text

inner_html(inner = nil, &blk)

Alias for html

inner_html=(inner)

Inserts new contents into the current node, based on the HTML contained in string `inner`.

[Source]

    # File lib/hpricot/traverse.rb, line 191
        def inner_html=(inner)
          html(inner || [])
        end

inner_text()

Builds a string from the text contained in this node. All HTML elements are removed.

[Source]

    # File lib/hpricot/traverse.rb, line 158
        def inner_text
          if respond_to?(:children) and children
            children.map { |x| x.inner_text }.join
          else
            ""
          end
        end

make(input = nil, &blk)

Parses an HTML string, making an HTML fragment based on the options used to create the container document.

[Source]

    # File lib/hpricot/traverse.rb, line 25
        def make(input = nil, &blk)
          if parent and parent.respond_to? :make
            parent.make(input, &blk)
          else
            Hpricot.make(input, &blk).children
          end
        end

next()

Returns the node neighboring this node to the south: just below it. This method includes text nodes and comments and such.

[Source]

    # File lib/hpricot/traverse.rb, line 91
        def next
          sib = parent.children
          sib[sib.index(self) + 1] if parent
        end

next_node()

Alias for next

node_position()

[Source]

    # File lib/hpricot/traverse.rb, line 241
        def node_position
          parent.children.index(self)
        end

nodes_at(*pos)

Puts together an array of neighboring nodes based on their proximity to this node. So, for example, to get the next node, you could use `nodes_at(1). Or, to get the previous node, use <tt>nodes_at(1)`.

This method also accepts ranges and sets of numbers.

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

[Source]

    # File lib/hpricot/traverse.rb, line 67
        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

position()

[Source]

    # File lib/hpricot/traverse.rb, line 245
        def position
          parent.children_of_type(self.pathname).index(self)
        end

preceding()

Find all preceding nodes.

[Source]

    # File lib/hpricot/traverse.rb, line 107
        def preceding
          sibs = parent.children
          si = sibs.index(self)
          return Elements[*sibs[0...si]]
        end

previous()

Returns to node neighboring this node to the north: just above it. This method includes text nodes and comments and such.

[Source]

    # File lib/hpricot/traverse.rb, line 99
        def previous
          sib = parent.children
          x = sib.index(self) - 1
          sib[x] if sib and x >= 0
        end

previous_node()

Alias for previous

procins?()

Is this object an XML processing instruction?

[Source]

    # File lib/hpricot/traverse.rb, line 17
        def procins?() ProcIns::Trav === self end

search(expr, &blk)

Searches this node for all elements matching the CSS or XPath `expr`. Returns an Elements array containing the matching nodes. If `blk` is given, it is used to iterate through the matching set.

[Source]

    # File lib/hpricot/traverse.rb, line 253
        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

swap(html = nil, &blk)

Replace this element and its contents with the nodes contained in the `html` string.

[Source]

    # File lib/hpricot/traverse.rb, line 133
        def swap(html = nil, &blk)
          parent.altered!
          parent.replace_child(self, make(html, &blk))
        end

text?()

Is this object an HTML text node?

[Source]

    # File lib/hpricot/traverse.rb, line 11
        def text?() Text::Trav === self end

to_html()

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

[Source]

    # File lib/hpricot/traverse.rb, line 36
        def to_html
          output("")
        end

to_original_html()

Attempts to preserve the original HTML of the document, only outputing new tags for elements which have changed.

[Source]

    # File lib/hpricot/traverse.rb, line 43
        def to_original_html
          output("", :preserve => true)
        end

to_plain_text()

Builds a string from the text contained in this node. All HTML elements are removed.

[Source]

    # File lib/hpricot/traverse.rb, line 148
        def to_plain_text
          if respond_to?(:children) and children
            children.map { |x| x.to_plain_text }.join.strip.gsub(/\n{2,}/, "\n\n")
          else
            ""
          end
        end

to_s()

Alias for to_html

traverse_element(*names) {|element| ...}

`traverse_element` traverses elements in the tree. It yields elements in depth first order.

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

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

      t = Hpricot('<a id=0><b><a id=1 /></b><c id=2 /></a>')
      t.traverse_element("a", "c") {|e| p e}
      # =>
      {elem <a id="0"> {elem <b> {emptyelem <a id="1">} </b>} {emptyelem <c id="2">} </a>}
      {emptyelem <a id="1">}
      {emptyelem <c id="2">}

Universal names are specified as follows.

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

[Source]

    # File lib/hpricot/traverse.rb, line 373
        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

traverse_text() {|text| ...}

`traverse_text` traverses texts in the tree

[Source]

    # File lib/hpricot/traverse.rb, line 679
        def traverse_text(&block) # :yields: text
          traverse_text_internal(&block)
          nil
        end

xmldecl?()

Is this object an XML declaration?

[Source]

    # File lib/hpricot/traverse.rb, line 13
        def xmldecl?() XMLDecl::Trav === self end

xpath()

Builds a unique XPath string for this node, from the root of the document containing it.

[Source]

    # File lib/hpricot/traverse.rb, line 208
        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 if parent.children
            p = File.join(parent.xpath, self.pathname)
            p += "[#{id+1}]" if sim >= 2
            p
          end
        end

[Validate]