123456789_123456789_123456789_123456789_123456789_

Class: REXML::Formatters::Pretty

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Default
Instance Chain:
self, Default
Inherits: REXML::Formatters::Default
Defined in: lib/rexml/formatters/pretty.rb

Overview

Pretty-prints an XML document. This destroys whitespace in text nodes and will insert carriage returns and indentations.

TODO: Add an option to print attributes on new lines

Class Method Summary

Default - Inherited

.new

Prints out the XML document with no formatting – except if id_hack is set.

Instance Attribute Summary

  • #compact rw

    If compact is set to true, then the formatter will attempt to use as little space as possible.

  • #width rw

    The width of a page.

Instance Method Summary

Constructor Details

.new(indentation = 2, ie_hack = false) ⇒ Pretty

Create a new pretty printer.

output

An object implementing '<<(String)', to which the output will be written.

indentation

An integer greater than 0. The indentation of each level will be this number of spaces. If this is < 1, the behavior of this object is undefined. Defaults to 2.

ie_hack

If true, the printer will insert whitespace before closing empty tags, thereby allowing Internet Explorer's XML parser to function. Defaults to false.

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 29

def initialize( indentation=2, ie_hack=false )
  @indentation = indentation
  @level = 0
  @ie_hack = ie_hack
  @width = 80
  @compact = false
end

Instance Attribute Details

#compact (rw)

If compact is set to true, then the formatter will attempt to use as little space as possible

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 13

attr_accessor :compact

#width (rw)

The width of a page. Used for formatting text

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 15

attr_accessor :width

Instance Method Details

#indent_text(string, level = 1, style = "\t", indentfirstline = true) (private)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 123

def indent_text(string, level=1, style="\t", indentfirstline=true)
  return string if level < 0
  string.gsub(/\n/, "\n#{style*level}")
end

#wrap(string, width) (private)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 128

def wrap(string, width)
  parts = []
  while string.length > width and place = string.rindex(' ', width)
    parts << string[0...place]
    string = string[place+1..-1]
  end
  parts << string
  parts.join("\n")
end

#write_cdata(node, output) (protected)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 101

def write_cdata( node, output)
  output << ' ' * @level
  super
end

#write_comment(node, output) (protected)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 96

def write_comment( node, output)
  output << ' ' * @level
  super
end

#write_document(node, output) (protected)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 106

def write_document( node, output )
  # Ok, this is a bit odd.  All XML documents have an XML declaration,
  # but it may not write itself if the user didn't specifically add it,
  # either through the API or in the input document.  If it doesn't write
  # itself, then we don't need a carriage return... which makes this
  # logic more complex.
  node.children.each { |child|
    next if child == node.children[-1] and child.instance_of?(Text)
    unless child == node.children[0] or child.instance_of?(Text) or
      (child == node.children[1] and !node.children[0].writethis)
      output << "\n"
    end
    write( child, output )
  }
end

#write_element(node, output) (protected)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 38

def write_element(node, output)
  output << ' '*@level
  output << "<#{node.expanded_name}"

  node.attributes.each_attribute do |attr|
    output << " "
    attr.write( output )
  end unless node.attributes.empty?

  if node.children.empty?
    if @ie_hack
      output << " "
    end
    output << "/"
  else
    output << ">"
    # If compact and all children are text, and if the formatted output
    # is less than the specified width, then try to print everything on
    # one line
    skip = false
    if compact
      if node.children.inject(true) {|s,c| s & c.kind_of?(Text)}
        string = ""
        old_level = @level
        @level = 0
        node.children.each { |child| write( child, string ) }
        @level = old_level
        if string.length < @width
          output << string
          skip = true
        end
      end
    end
    unless skip
      output << "\n"
      @level += @indentation
      node.children.each { |child|
        next if child.kind_of?(Text) and child.to_s.strip.length == 0
        write( child, output )
        output << "\n"
      }
      @level -= @indentation
      output << ' '*@level
    end
    output << "</#{node.expanded_name}"
  end
  output << ">"
end

#write_text(node, output) (protected)

[ GitHub ]

  
# File 'lib/rexml/formatters/pretty.rb', line 87

def write_text( node, output )
  s = node.to_s()
  s.gsub!(/\s/,' ')
  s.squeeze!(" ")
  s = wrap(s, @width - @level)
  s = indent_text(s, @level, " ", true)
  output << (' '*@level + s)
end