1module REXML
2  module Formatters
3    class Default
4      # Prints out the XML document with no formatting -- except if id_hack is
5      # set.
6      #
7      # ie_hack::
8      #   If set to true, then inserts whitespace before the close of an empty
9      #   tag, so that IE's bad XML parser doesn't choke.
10      def initialize( ie_hack=false )
11        @ie_hack = ie_hack
12      end
13
14      # Writes the node to some output.
15      #
16      # node::
17      #   The node to write
18      # output::
19      #   A class implementing <TT>&lt;&lt;</TT>.  Pass in an Output object to
20      #   change the output encoding.
21      def write( node, output )
22        case node
23
24        when Document
25          if node.xml_decl.encoding != 'UTF-8' && !output.kind_of?(Output)
26            output = Output.new( output, node.xml_decl.encoding )
27          end
28          write_document( node, output )
29
30        when Element
31          write_element( node, output )
32
33        when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity,
34             Attribute, AttlistDecl
35          node.write( output,-1 )
36
37        when Instruction
38          write_instruction( node, output )
39
40        when DocType, XMLDecl
41          node.write( output )
42
43        when Comment
44          write_comment( node, output )
45
46        when CData
47          write_cdata( node, output )
48
49        when Text
50          write_text( node, output )
51
52        else
53          raise Exception.new("XML FORMATTING ERROR")
54
55        end
56      end
57
58      protected
59      def write_document( node, output )
60        node.children.each { |child| write( child, output ) }
61      end
62
63      def write_element( node, output )
64        output << "<#{node.expanded_name}"
65
66        node.attributes.to_a.map { |a|
67          Hash === a ? a.values : a
68        }.flatten.sort_by {|attr| attr.name}.each do |attr|
69          output << " "
70          attr.write( output )
71        end unless node.attributes.empty?
72
73        if node.children.empty?
74          output << " " if @ie_hack
75          output << "/"
76        else
77          output << ">"
78          node.children.each { |child|
79            write( child, output )
80          }
81          output << "</#{node.expanded_name}"
82        end
83        output << ">"
84      end
85
86      def write_text( node, output )
87        output << node.to_s()
88      end
89
90      def write_comment( node, output )
91        output << Comment::START
92        output << node.to_s
93        output << Comment::STOP
94      end
95
96      def write_cdata( node, output )
97        output << CData::START
98        output << node.to_s
99        output << CData::STOP
100      end
101
102      def write_instruction( node, output )
103        output << Instruction::START.sub(/\\/u, '')
104        output << node.target
105        output << ' '
106        output << node.content
107        output << Instruction::STOP.sub(/\\/u, '')
108      end
109    end
110  end
111end
112