pretty-vcxproj-manx.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/python2.6
  2. # Copyright (c) 2009 Google Inc. All rights reserved.
  3. # Copyright (C) 2012 Sony Computer Entertainment Inc. All rights reserved.
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. """Make the format of a vcproj really pretty.
  7. It outputs the resulting xml to stdout.
  8. """
  9. import os
  10. import sys
  11. from xml.dom.minidom import parse
  12. from xml.dom.minidom import Node
  13. class CmpTuple:
  14. """Compare function between 2 tuple."""
  15. def __call__(self, x, y):
  16. (key1, value1) = x
  17. (key2, value2) = y
  18. return cmp(key1, key2)
  19. class CmpNode:
  20. """Compare function between 2 xml nodes."""
  21. def get_string(self, node):
  22. node_string = "node"
  23. node_string += node.nodeName
  24. if node.nodeValue:
  25. node_string += node.nodeValue
  26. if node.attributes:
  27. # We first sort by name, if present.
  28. node_string += node.getAttribute("Name")
  29. all_nodes = []
  30. for (name, value) in node.attributes.items():
  31. all_nodes.append((name, value))
  32. all_nodes.sort(CmpTuple())
  33. for (name, value) in all_nodes:
  34. node_string += name
  35. node_string += value
  36. return node_string
  37. def __call__(self, x, y):
  38. return cmp(self.get_string(x), self.get_string(y))
  39. def _write_data(writer, data):
  40. "Writes datachars to writer."
  41. data = data.replace("&", "&amp;").replace("<", "&lt;")
  42. data = data.replace("\"", "&quot;").replace(">", "&gt;")
  43. writer.write(data)
  44. def _has_only_text_node(node):
  45. def is_text_node(node):
  46. return node.nodeType == Node.TEXT_NODE
  47. return all(map(is_text_node, node.childNodes))
  48. def writexml(node, writer, indent="", addindent="", newl=""):
  49. # indent = current indentation
  50. # addindent = indentation to add to higher levels
  51. # newl = newline string
  52. writer.write(indent+"<" + node.tagName)
  53. attrs = node._get_attributes()
  54. a_names = attrs.keys()
  55. for a_name in a_names:
  56. writer.write(" %s=\"" % a_name)
  57. _write_data(writer, attrs[a_name].value)
  58. writer.write("\"")
  59. writer.write(">")
  60. if _has_only_text_node(node):
  61. for c in node.childNodes:
  62. writer.write(c.data)
  63. writer.write("</%s>%s" % (node.tagName, newl))
  64. else:
  65. writer.write("\n")
  66. for c in node.childNodes:
  67. writexml(c,writer,indent+addindent,addindent,newl)
  68. writer.write("%s</%s>%s" % (indent,node.tagName,newl))
  69. def CleanupVcproj(node):
  70. # For each sub node, we call recursively this function.
  71. for sub_node in node.childNodes:
  72. CleanupVcproj(sub_node)
  73. # For each node, take a copy, and remove it from the list.
  74. node_array = []
  75. while node.childNodes and node.childNodes[0]:
  76. # Take a copy of the node and remove it from the list.
  77. current = node.childNodes[0]
  78. node_array.append(current)
  79. node.removeChild(current)
  80. # Sort the list.
  81. if node.nodeName == 'ItemGroup':
  82. node_array.sort(CmpNode())
  83. for new_node in node_array:
  84. node.appendChild(new_node)
  85. def main(argv):
  86. """Main function of this vcproj prettifier."""
  87. # check if we have exactly 1 parameter.
  88. if len(argv) < 1:
  89. print ('Usage: %s <vcproj.vcproj>' % argv[0])
  90. return
  91. # Open the vcproj and parse the xml.
  92. dom = parse(argv[1])
  93. CleanupVcproj(dom)
  94. sys.stdout.write('<?xml version="1.0" encoding="utf-8"?>\n')
  95. writexml(dom.documentElement, sys.stdout, "", " ", "\n")
  96. if __name__ == '__main__':
  97. main(sys.argv)