mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/rexml: Merge fixes since 1.8.6 made solely on the ruby_1_8_6
branch. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@16067 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
40e7794993
commit
2f1fa7e402
28 changed files with 1785 additions and 1373 deletions
109
lib/rexml/formatters/default.rb
Normal file
109
lib/rexml/formatters/default.rb
Normal file
|
@ -0,0 +1,109 @@
|
|||
module REXML
|
||||
module Formatters
|
||||
class Default
|
||||
# Prints out the XML document with no formatting -- except if id_hack is
|
||||
# set.
|
||||
#
|
||||
# ie_hack::
|
||||
# If set to true, then inserts whitespace before the close of an empty
|
||||
# tag, so that IE's bad XML parser doesn't choke.
|
||||
def initialize( ie_hack=false )
|
||||
@ie_hack = ie_hack
|
||||
end
|
||||
|
||||
# Writes the node to some output.
|
||||
#
|
||||
# node::
|
||||
# The node to write
|
||||
# output::
|
||||
# A class implementing <TT><<</TT>. Pass in an Output object to
|
||||
# change the output encoding.
|
||||
def write( node, output )
|
||||
case node
|
||||
|
||||
when Document
|
||||
if node.xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
|
||||
output = Output.new( output, node.xml_decl.encoding )
|
||||
end
|
||||
write_document( node, output )
|
||||
|
||||
when Element
|
||||
write_element( node, output )
|
||||
|
||||
when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity,
|
||||
Attribute, AttlistDecl
|
||||
node.write( output,-1 )
|
||||
|
||||
when Instruction
|
||||
write_instruction( node, output )
|
||||
|
||||
when DocType, XMLDecl
|
||||
node.write( output )
|
||||
|
||||
when Comment
|
||||
write_comment( node, output )
|
||||
|
||||
when CData
|
||||
write_cdata( node, output )
|
||||
|
||||
when Text
|
||||
write_text( node, output )
|
||||
|
||||
else
|
||||
raise Exception.new("XML FORMATTING ERROR")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def write_document( node, output )
|
||||
node.children.each { |child| write( child, output ) }
|
||||
end
|
||||
|
||||
def write_element( node, output )
|
||||
output << "<#{node.expanded_name}"
|
||||
|
||||
node.attributes.each_attribute do |attr|
|
||||
output << " "
|
||||
attr.write( output )
|
||||
end unless node.attributes.empty?
|
||||
|
||||
if node.children.empty?
|
||||
output << " " if @ie_hack
|
||||
output << "/"
|
||||
else
|
||||
output << ">"
|
||||
node.children.each { |child|
|
||||
write( child, output )
|
||||
}
|
||||
output << "</#{node.expanded_name}"
|
||||
end
|
||||
output << ">"
|
||||
end
|
||||
|
||||
def write_text( node, output )
|
||||
output << node.to_s()
|
||||
end
|
||||
|
||||
def write_comment( node, output )
|
||||
output << Comment::START
|
||||
output << node.to_s
|
||||
output << Comment::STOP
|
||||
end
|
||||
|
||||
def write_cdata( node, output )
|
||||
output << CData::START
|
||||
output << node.to_s
|
||||
output << CData::STOP
|
||||
end
|
||||
|
||||
def write_instruction( node, output )
|
||||
output << Instruction::START.sub(/\\/u, '')
|
||||
output << node.target
|
||||
output << ' '
|
||||
output << node.content
|
||||
output << Instruction::STOP.sub(/\\/u, '')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
137
lib/rexml/formatters/pretty.rb
Normal file
137
lib/rexml/formatters/pretty.rb
Normal file
|
@ -0,0 +1,137 @@
|
|||
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 = ""
|
||||
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
|
||||
|
||||
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
|
||||
|
56
lib/rexml/formatters/transitive.rb
Normal file
56
lib/rexml/formatters/transitive.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
require 'rexml/formatters/pretty'
|
||||
|
||||
module REXML
|
||||
module Formatters
|
||||
# The Transitive formatter writes an XML document that parses to an
|
||||
# identical document as the source document. This means that no extra
|
||||
# whitespace nodes are inserted, and whitespace within text nodes is
|
||||
# preserved. Within these constraints, the document is pretty-printed,
|
||||
# with whitespace inserted into the metadata to introduce formatting.
|
||||
#
|
||||
# Note that this is only useful if the original XML is not already
|
||||
# formatted. Since this formatter does not alter whitespace nodes, the
|
||||
# results of formatting already formatted XML will be odd.
|
||||
class Transitive < Default
|
||||
def initialize( indentation=2 )
|
||||
@indentation = indentation
|
||||
@level = 0
|
||||
end
|
||||
|
||||
protected
|
||||
def write_element( node, output )
|
||||
output << "<#{node.expanded_name}"
|
||||
|
||||
node.attributes.each_attribute do |attr|
|
||||
output << " "
|
||||
attr.write( output )
|
||||
end unless node.attributes.empty?
|
||||
|
||||
output << "\n"
|
||||
output << ' '*@level
|
||||
if node.children.empty?
|
||||
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
|
||||
@level += @indentation
|
||||
node.children.each { |child|
|
||||
write( child, output )
|
||||
}
|
||||
@level -= @indentation
|
||||
output << "</#{node.expanded_name}"
|
||||
output << "\n"
|
||||
output << ' '*@level
|
||||
end
|
||||
output << ">"
|
||||
end
|
||||
|
||||
def write_text( node, output )
|
||||
output << node.to_s()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue