Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 35 additions & 19 deletions lib/rexml/formatters/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,32 @@ def write_document( node, output )
node.children.each { |child| write( child, output ) }
end

# Descendants are walked with an explicit stack instead of recursion so
# that a deeply nested document doesn't exhaust the machine stack. A
# String on the stack is an end tag waiting to be written.
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}"
stack = [node]
until stack.empty?
current = stack.pop
case current
when String
output << current
when Element
output << "<#{current.expanded_name}"
write_element_attributes( current, output )
children = current.children
if children.empty?
output << " " if @ie_hack
output << "/>"
else
output << ">"
stack << "</#{current.expanded_name}>"
stack.concat(children.reverse)
end
else
write( current, output )
end
end
output << ">"
end

def write_text( node, output )
Expand Down Expand Up @@ -111,6 +116,17 @@ def write_instruction( node, output )
end
output << Instruction::STOP
end

private
def write_element_attributes( node, output )
return if node.attributes.empty?
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
end
end
end
end