Pretty Print XML using Ruby
require 'rexml/document' include REXML def pretty_print(parent_node, itab) buffer = '' parent_node.elements.each do |node| buffer += ' ' * itab + "<#{node.name}#{get_att_list(node)}" if node.to_a.length > 0 buffer += ">" if node.text.nil? buffer += "\n" buffer += pretty_print(node,itab+2) buffer += ' ' * itab + "</#{node.name}>\n" else node_text = node.text.strip if node_text != '' buffer += node_text buffer += "</#{node.name}>\n" else buffer += "\n" + pretty_print(node,itab+2) buffer += ' ' * itab + "</#{node.name}>\n" end end else buffer += "/>\n" end end buffer end def get_att_list(node) att_list = '' node.attributes.each { |attribute, val| att_list += " #{attribute}='#{val}'" } att_list end def pretty_xml(doc) buffer = '' xml_declaration = doc.to_s.match('<\?.*\?>').to_s buffer += "#{xml_declaration}\n" if not xml_declaration.nil? xml_doctype = doc.to_s.match('<\!.*\">').to_s buffer += "#{xml_doctype}\n" if not xml_doctype.nil? buffer += "<#{doc.root.name}#{get_att_list(doc.root)}" if doc.root.to_a.length > 0 buffer +=">\n#{pretty_print(doc.root,2)}</#{doc.root.name}>" else buffer += "/>\n" end end xml_data = "<hi id='124'><yo><a id='1'/><b/><c/></yo><sushi><love>Ruby</love></sushi></hi>" doc = Document.new(xml_data) pretty_xml(doc)
output
<hi id='124'> <yo> <a id='1'/> <b/> <c/> </yo> <sushi> <love>Ruby</love> </sushi> </hi>
*Update 7-Jan-08 1:51AM *
Although I haven't tried running the following XSL code, this might actually have been a better solution to my problem. source: http://www.printk.net/~bds/indent.html
*Pretty Print XML using XSLT*
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="ISO-8859-1"/> <xsl:param name="indent-increment" select="' '"/> <xsl:template name="newline"> <xsl:text disable-output-escaping="yes"> </xsl:text> </xsl:template> <xsl:template match="comment() | processing-instruction()"> <xsl:param name="indent" select="''"/> <xsl:call-template name="newline"/> <xsl:value-of select="$indent"/> <xsl:copy /> </xsl:template> <xsl:template match="text()"> <xsl:param name="indent" select="''"/> <xsl:call-template name="newline"/> <xsl:value-of select="$indent"/> <xsl:value-of select="normalize-space(.)"/> </xsl:template> <xsl:template match="text()[normalize-space(.)='']"/> <xsl:template match="*"> <xsl:param name="indent" select="''"/> <xsl:call-template name="newline"/> <xsl:value-of select="$indent"/> <xsl:choose> <xsl:when test="count(child::*) > 0"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates select="*|text()"> <xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/> </xsl:apply-templates> <xsl:call-template name="newline"/> <xsl:value-of select="$indent"/> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>