From 38e5e342f8f58b1649efaa25cf24ec6e843c51e7 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Mon, 7 Jun 2010 09:03:03 +0000 Subject: [PATCH] added prettyprint module with fixed toprettyxml() method --- extra/prettyprint/__init__.py | 19 ++++++ extra/prettyprint/prettyprint.py | 100 +++++++++++++++++++++++++++++++ lib/core/xmldump.py | 4 +- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100755 extra/prettyprint/__init__.py create mode 100644 extra/prettyprint/prettyprint.py diff --git a/extra/prettyprint/__init__.py b/extra/prettyprint/__init__.py new file mode 100755 index 000000000..c1a869589 --- /dev/null +++ b/extra/prettyprint/__init__.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# +# Copyright 2008-2009 Jose Fonseca +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +pass diff --git a/extra/prettyprint/prettyprint.py b/extra/prettyprint/prettyprint.py new file mode 100644 index 000000000..4961fadba --- /dev/null +++ b/extra/prettyprint/prettyprint.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +#Copyright (c) 2010, Miroslav Stampar +#Added formatXML method + +#Copyright (c) 2010, Chris Hall +#All rights reserved. + +#Redistribution and use in source and binary forms, with or without modification, +#are permitted provided that the following conditions are met: + +#* Redistributions of source code must retain the above copyright notice, +#this list of conditions and the following disclaimer. +#* Redistributions in binary form must reproduce the above copyright notice, +#this list of conditions and the following disclaimer in the documentation +#and/or other materials provided with the distribution. + +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +#ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from xml.dom import minidom +from xml.dom import Node + +def format(text): + doc = minidom.parseString(text) + root = doc.childNodes[0] + return root.toprettyxml(indent=' ') + +def formatXML(doc, encoding=None): + root = doc.childNodes[0] + return root.toprettyxml(indent=' ', encoding=encoding) + +def _patch_minidom(): + minidom.Text.writexml = _writexml_text + minidom.Element.writexml = _writexml_element + minidom.Node.toprettyxml = _toprettyxml_node + +def _collapse(node): + for child in node.childNodes: + if child.nodeType == Node.TEXT_NODE and len(child.data.strip()) == 0: + child.data = '' + else: + _collapse(child) + +def _writexml_text(self, writer, indent="", addindent="", newl=""): + minidom._write_data(writer, "%s"%(self.data.strip())) + +def _writexml_element(self, writer, indent="", addindent="", newl=""): + # indent = current indentation + # addindent = indentation to add to higher levels + # newl = newline string + writer.write(indent+"<" + self.tagName) + + attrs = self._get_attributes() + a_names = attrs.keys() + a_names.sort() + + for a_name in a_names: + writer.write(" %s=\"" % a_name) + minidom._write_data(writer, attrs[a_name].value) + writer.write("\"") + if self.childNodes: + if self.childNodes[0].nodeType == Node.TEXT_NODE and len(self.childNodes[0].data) > 0: + writer.write(">") + else: + writer.write(">%s"%(newl)) + for node in self.childNodes: + node.writexml(writer,indent+addindent,addindent,newl) + if self.childNodes[-1].nodeType == Node.TEXT_NODE and len(self.childNodes[0].data) > 0: + writer.write("%s" % (self.tagName,newl)) + else: + writer.write("%s%s" % (indent,self.tagName,newl)) + else: + writer.write("/>%s"%(newl)) + +def _toprettyxml_node(self, indent="\t", newl="\n", encoding = None): + _collapse(self) + # indent = the indentation string to prepend, per level + # newl = the newline string to append + writer = minidom._get_StringIO() + if encoding is not None: + import codecs + # Can't use codecs.getwriter to preserve 2.0 compatibility + writer = codecs.lookup(encoding)[3](writer) + if self.nodeType == Node.DOCUMENT_NODE: + # Can pass encoding only to document, to put it into XML header + self.writexml(writer, "", indent, newl, encoding) + else: + self.writexml(writer, "", indent, newl) + return writer.getvalue() + +_patch_minidom() diff --git a/lib/core/xmldump.py b/lib/core/xmldump.py index aa0fe8848..baaff4251 100644 --- a/lib/core/xmldump.py +++ b/lib/core/xmldump.py @@ -10,6 +10,7 @@ import xml.sax.saxutils as saxutils from xml.dom.minidom import Document from xml.parsers.expat import ExpatError +from extra.prettyprint import prettyprint from lib.core.common import getUnicode from lib.core.data import conf from lib.core.data import logger @@ -524,8 +525,7 @@ class XMLDump: statusElem.appendChild(errorElem) self.__addToRoot(statusElem) - #self.__write(self.__doc.toprettyxml(encoding=conf.dataEncoding)) ##don't use toprettyxml, lots of bugs with it - self.__write(self.__doc.toxml(encoding=conf.dataEncoding)) ##not human readable, but at least without bugs + self.__write(prettyprint.formatXML(self.__doc, encoding=conf.dataEncoding)) self.__outputFP.close() def closeDumper(status, msg=""):