xml.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import threading
  2. import StringIO
  3. from lxml import etree
  4. from path import path
  5. NS_MAP = {'svg': "http://www.w3.org/2000/svg",
  6. 'inkscape': "http://www.inkscape.org/namespaces/inkscape"}
  7. # thread safe parser storage
  8. class ParserTLS(threading.local):
  9. def getParser(self):
  10. parser = getattr(self, "parser", None)
  11. if parser is not None:
  12. return parser
  13. self.parser = parser = etree.XMLParser()
  14. return parser
  15. parsel_tls = ParserTLS()
  16. def TreeToString(tree, pretty=False, encoding=None, method="xml"):
  17. return etree.tostring(tree, pretty_print=pretty, encoding=encoding, method=method)
  18. def TreeToFile(tree, fname, encoding='utf-8'):
  19. tree.write(fname, encoding=encoding, xml_declaration=True, method="xml")
  20. def FileToTree(fname):
  21. return etree.parse(fname, parsel_tls.getParser())
  22. def StringToTree(s):
  23. if not s:
  24. raise ValueError("Empty or invalid string %r (%s)'" % (s, type(s)))
  25. return etree.parse(StringIO.StringIO(s), parsel_tls.getParser())
  26. def subelement(destEl, tag, pos=None, attribs=None):
  27. e = etree.SubElement(destEl, tag)
  28. if pos is not None:
  29. e.getparent().insert(pos, e)
  30. if attribs is not None:
  31. e.attrib.update(dict(((k, unicode(v)) for k, v in attribs.items())))
  32. return e
  33. prettyXSL = """<?xml version="1.0" encoding="UTF-8"?>
  34. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  35. <xsl:output encoding="UTF-8" method="xml"/>
  36. <xsl:param name="indent-increment" select="' '"/>
  37. <xsl:template match="* | comment()|processing-instruction()">
  38. <xsl:param name="indent" select="'&#xA;'"/>
  39. <xsl:value-of select="$indent"/>
  40. <xsl:copy>
  41. <xsl:copy-of select="@*"/>
  42. <xsl:apply-templates>
  43. <xsl:with-param name="indent" select="concat($indent, $indent-increment)"/>
  44. </xsl:apply-templates>
  45. <xsl:if test="*">
  46. <xsl:value-of select="$indent"/>
  47. </xsl:if>
  48. </xsl:copy>
  49. </xsl:template>
  50. <!-- WARNING: this is dangerous. Handle with care -->
  51. <xsl:template match="text()[normalize-space(.)='']"/>
  52. </xsl:stylesheet>"""
  53. def prettyPrint(data):
  54. ''' pretty-print data - can be a:
  55. * xml string
  56. * list of etree.elements (return single pretty-prints that will be \n concatenated)
  57. * single etree or single element
  58. '''
  59. xslt_doc = etree.fromstring(prettyXSL)
  60. transform = etree.XSLT(xslt_doc)
  61. if isinstance(data, basestring):
  62. doc = etree.fromstring(data)
  63. return etree.tostring(transform(doc))
  64. elif isinstance(data, (tuple, list)): #assume data is list of etree.elements
  65. return '\n'.join(etree.tostring(transform(e)) for e in data)
  66. else:
  67. return etree.tostring(transform(data))