From bc1df2a6082f10587e194de20454e18909bf11d3 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 2 Aug 2010 12:37:37 -0400 Subject: [PATCH] Add hooke.compat.minidom to fix Python's XML generation issue5752. xml.dom.minidom.Element.writexml doesn't escape some special characters (e.g. '\n'). See http://bugs.python.org/issue5752 importing hooke.compat.minidom fixes this bug dynamically. --- hooke/compat/minidom.py | 50 +++++++++++++++++++++++++++++++++++++++++ hooke/playlist.py | 17 ++++++++------ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 hooke/compat/minidom.py diff --git a/hooke/compat/minidom.py b/hooke/compat/minidom.py new file mode 100644 index 0000000..9d9f1a2 --- /dev/null +++ b/hooke/compat/minidom.py @@ -0,0 +1,50 @@ +# Copyright + +"""Dynamically patch :mod:`xml.dom.minidom`'s attribute value escaping. + +:meth:`xml.dom.minidom.Element.setAttribute` doesn't preform some +character escaping (see the `Python bug`_ and `XML specs`_). +Importing this module applies the suggested patch dynamically. + +.. _Python bug: http://bugs.python.org/issue5752 +.. _XML specs: + http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping +""" + +import xml.dom.minidom + + +def _write_data(writer, data, isAttrib=False): + "Writes datachars to writer." + if isAttrib: + data = data.replace("\r", " ").replace("\n", " ") + data = data.replace("\t", " ") + writer.write(data) +xml.dom.minidom._write_data = _write_data + +def writexml(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) + _write_data(writer, attrs[a_name].value, isAttrib=True) + writer.write("\"") + if self.childNodes: + writer.write(">%s"%(newl)) + for node in self.childNodes: + node.writexml(writer,indent+addindent,addindent,newl) + writer.write("%s%s" % (indent,self.tagName,newl)) + else: + writer.write("/>%s"%(newl)) +# For an introduction to overriding instance methods, see +# http://irrepupavel.com/documents/python/instancemethod/ +instancemethod = type(xml.dom.minidom.Element.writexml) +xml.dom.minidom.Element.writexml = instancemethod( + writexml, None, xml.dom.minidom.Element) diff --git a/hooke/playlist.py b/hooke/playlist.py index 8efac47..b58e9b6 100644 --- a/hooke/playlist.py +++ b/hooke/playlist.py @@ -27,6 +27,7 @@ import os.path import xml.dom.minidom from . import curve as curve +from .compat import minidom as minidom # dynamically patch xml.sax.minidom class NoteIndexList (list): @@ -185,20 +186,20 @@ class FilePlaylist (Playlist): >>> c.info['note'] = 'The first curve' >>> p.append(c) >>> c = curve.Curve(os.path.join(root_path, 'to', 'curve', 'two')) - >>> c.info['note'] = 'The second curve' + >>> c.info['note'] = 'The second curve\\nwith endlines' >>> p.append(c) >>> print p.flatten() # doctest: +NORMALIZE_WHITESPACE +REPORT_UDIFF - - + + >>> print p.flatten(absolute_paths=True) # doctest: +NORMALIZE_WHITESPACE +REPORT_UDIFF - - + + """ @@ -224,7 +225,7 @@ class FilePlaylist (Playlist): for key,value in curve.info.items(): if key in self._ignored_keys: continue - curve_element.setAttribute(key, str(value)) + curve_element.setAttribute(key,str(value)) string = doc.toprettyxml(encoding='utf-8') root.unlink() # break circular references for garbage collection return string @@ -259,7 +260,7 @@ class FilePlaylist (Playlist): >>> string = ''' ... ... - ... + ... ... ... ''' >>> p = FilePlaylist(drivers=[], @@ -273,6 +274,8 @@ class FilePlaylist (Playlist): ... print curve.path path/to/curve/one path/to/curve/two + >>> p[-1].info['note'] + u'The second curve\\nwith endlines' """ doc = xml.dom.minidom.parseString(string) self._from_xml_doc(doc, identify=identify) -- 2.26.2