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 = attrs.keys()
36  a_names.sort()
37
38  for a_name in a_names:
39    writer.write(" %s=\"" % a_name)
40    _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
41    writer.write("\"")
42  if self.childNodes:
43    writer.write(">%s" % newl)
44    for node in self.childNodes:
45      node.writexml(writer, indent + addindent, addindent, newl)
46    writer.write("%s</%s>%s" % (indent, self.tagName, newl))
47  else:
48    writer.write("/>%s" % newl)
49
50
51class XmlFix(object):
52  """Object to manage temporary patching of xml.dom.minidom."""
53
54  def __init__(self):
55    # Preserve current xml.dom.minidom functions.
56    self.write_data = xml.dom.minidom._write_data
57    self.writexml = xml.dom.minidom.Element.writexml
58    # Inject replacement versions of a function and a method.
59    xml.dom.minidom._write_data = _Replacement_write_data
60    xml.dom.minidom.Element.writexml = _Replacement_writexml
61
62  def Cleanup(self):
63    if self.write_data:
64      xml.dom.minidom._write_data = self.write_data
65      xml.dom.minidom.Element.writexml = self.writexml
66      self.write_data = None
67
68  def __del__(self):
69    self.Cleanup()
70