1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/rexml/formatters/pretty.rb
ser 61fec2d310 r1278@bean: ser | 2007-06-07 00:53:06 -0400
Fixed a double-encoding bug.  This was a regression, related
  to ticket:48.
  r1292@bean:  ser | 2007-07-25 08:19:36 -0400
   r1279@bean:  ser | 2007-06-09 23:19:02 -0400
   Fixes ticket:89 -- encoding CP-1252 was broken.  ISO-8859-15 had the same
   problem.
   
   Also in this patch is a fix to merge.rb (unused, but it should at least
   contain no errors), and a unit test for ticket:88.
  
  r1293@bean:  ser | 2007-07-25 08:19:37 -0400
   r1281@bean:  ser | 2007-07-24 11:08:48 -0400
   Addresses ticket:85
   
   This is a major rewrite of the XML formatting code.  The XML writers have all
   been extracted out of the classes and put into their own class containers.
   This makes writing parsers easier, and cleaner.
   
   There are three formatters, which correspond to the previous three XML writing
   modes:
   
     REXML::Formatters::Default    
         Prints the XML document exactly as it was parsed
     REXML::Formatters::Pretty     
         Pretty prints the XML document, destroying whitespace in the document
     REXML::Formatters::Transitive 
         Pretty prints the XML document, preserving whitespace
   
   All of the write() functions have been deprecated (some are still used, but
   these will also go away) except the write() function on Document, which is left
   for convenience.  To pretty print an XML document the canonical way:
   
     formatter = REXML::Formatters::Pretty.new( 5 ) # indent by 5 spaces
     formatter.write( document, output )
   
  r1296@bean:  ser | 2007-07-25 08:19:40 -0400
   r1287@bean:  ser | 2007-07-24 20:12:25 -0400
   Applied patch from Jeff Barczewski.  Note that this changes what the values of
   the name and IDs are from the previous behavior -- the values no longer include
   the quotes.  This is the correct behavior, so I'm leaving it in, but it is not
   backwards compatible.  Also fixes the serializer so that it outputs the doctype
   in a correct format (needed as a result of this change).
  
  r1297@bean:  ser | 2007-07-25 08:38:38 -0400
  Version update
  r1298@bean:  ser | 2007-07-25 08:40:30 -0400
   r1291@bean (orig r12517):  ryan | 2007-06-11 20:38:57 -0400
   Fixed typo in code. Fixes bug #10420
  
 
 r1304@bean:  ser | 2007-07-27 22:34:18 -0400
 Whitespace changes only


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@12852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-28 02:46:08 +00:00

134 lines
4.2 KiB
Ruby

require 'rexml/formatters/default'
module REXML
module Formatters
# 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 Pretty < Default
# If compact is set to true, then the formatter will attempt to use as
# little space as possible
attr_accessor :compact
# The width of a page. Used for formatting text
attr_accessor :width
# 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 feeble XML parser to
# function. Defaults to false.
def initialize( indentation=2, ie_hack=false )
@indentation = indentation
@level = 0
@ie_hack = ie_hack
@width = 80
end
protected
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 = ""
node.children.each { |child| write( child, string, 0 ) }
if string.length + @level < @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
def write_text( node, output )
s = node.to_s()
s.gsub!(/\s/,' ')
s.squeeze!(" ")
s = wrap(s, 80-@level)
s = indent_text(s, @level, " ", true)
output << (' '*@level + s)
end
def write_comment( node, output)
output << ' ' * @level
super
end
def write_cdata( node, output)
output << ' ' * @level
super
end
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
private
def indent_text(string, level=1, style="\t", indentfirstline=true)
return string if level < 0
string.gsub(/\n/, "\n#{style*level}")
end
def wrap(string, width)
# Recursivly wrap string at width.
return string if string.length <= width
place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
return string[0,place] + "\n" + wrap(string[place+1..-1], width)
end
end
end
end