1# Copyright (c) 2011 Google Inc. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Applies a fix to CR LF TAB handling in xml.dom.
6
7Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
8Working around this: http://bugs.python.org/issue5752
9TODO(bradnelson): Consider dropping this when we drop XP support.
10"""
11
12
13import xml.dom.minidom
14
15
16def _Replacement_write_data(writer, data, is_attrib=False):
17  """Writes datachars to writer."""
18  data = data.replace("&", "&amp;").replace("<", "&lt;")
19  data = data.replace("\"", "&quot;").replace(">", "&gt;")
20  if is_attrib:
21    data = data.replace(
22        "\r", "&#xD;").replace(
23        "\n", "&#xA;").replace(
24        "\t", "&#x9;")
25  writer.write(data)
26
27
28def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
29  # indent = current indentation
30  # addindent = indentation to add to higher levels
31  # newl = newline string
32  writer.write(indent+"<" + self.tagName)
33
34  attrs = self._get_attributes()
35  a_names = sorted(attrs.keys())
36
37  for a_name in a_names:
38    writer.write(" %s=\"" % a_name)
39    _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
40    writer.write("\"")
41  if self.childNodes:
42    writer.write(">%s" % newl)
43    for node in self.childNodes:
44      node.writexml(writer, indent + addindent, addindent, newl)
45    writer.write("%s</%s>%s" % (indent, self.tagName, newl))
46  else:
47    writer.write("/>%s" % newl)
48
49
50class XmlFix(object):
51  """Object to manage temporary patching of xml.dom.minidom."""
52
53  def __init__(self):
54    # Preserve current xml.dom.minidom functions.
55    self.write_data = xml.dom.minidom._write_data
56    self.writexml = xml.dom.minidom.Element.writexml
57    # Inject replacement versions of a function and a method.
58    xml.dom.minidom._write_data = _Replacement_write_data
59    xml.dom.minidom.Element.writexml = _Replacement_writexml
60
61  def Cleanup(self):
62    if self.write_data:
63      xml.dom.minidom._write_data = self.write_data
64      xml.dom.minidom.Element.writexml = self.writexml
65      self.write_data = None
66
67  def __del__(self):
68    self.Cleanup()
69