summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rexml/formatters
diff options
context:
space:
mode:
Diffstat (limited to 'jni/ruby/lib/rexml/formatters')
-rw-r--r--jni/ruby/lib/rexml/formatters/default.rb111
-rw-r--r--jni/ruby/lib/rexml/formatters/pretty.rb141
-rw-r--r--jni/ruby/lib/rexml/formatters/transitive.rb57
3 files changed, 309 insertions, 0 deletions
diff --git a/jni/ruby/lib/rexml/formatters/default.rb b/jni/ruby/lib/rexml/formatters/default.rb
new file mode 100644
index 0000000..574c821
--- /dev/null
+++ b/jni/ruby/lib/rexml/formatters/default.rb
@@ -0,0 +1,111 @@
+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>&lt;&lt;</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.to_a.map { |a|
+ Hash === a ? a.values : a
+ }.flatten.sort_by {|attr| attr.name}.each 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
diff --git a/jni/ruby/lib/rexml/formatters/pretty.rb b/jni/ruby/lib/rexml/formatters/pretty.rb
new file mode 100644
index 0000000..e5ba561
--- /dev/null
+++ b/jni/ruby/lib/rexml/formatters/pretty.rb
@@ -0,0 +1,141 @@
+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 XML parser to
+ # function. Defaults to false.
+ def initialize( indentation=2, ie_hack=false )
+ @indentation = indentation
+ @level = 0
+ @ie_hack = ie_hack
+ @width = 80
+ @compact = false
+ 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, @width - @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)
+ 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
+
+ end
+ end
+end
+
diff --git a/jni/ruby/lib/rexml/formatters/transitive.rb b/jni/ruby/lib/rexml/formatters/transitive.rb
new file mode 100644
index 0000000..6cc690d
--- /dev/null
+++ b/jni/ruby/lib/rexml/formatters/transitive.rb
@@ -0,0 +1,57 @@
+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, ie_hack=false )
+ @indentation = indentation
+ @level = 0
+ @ie_hack = ie_hack
+ 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 << " " if @ie_hack
+ 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
+ @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