Converts Python ASTs to XML files for reading in other languages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import ast, re, sys
from xml.dom import minidom
try:
from xml.etree import cElementTree as etree
except:
try:
from lxml import etree
except:
from xml.etree import ElementTree as etree
def prettify(xml_string):
reparsed = minidom.parseString(xml_string)
return reparsed.toprettyxml(indent=" ")
class ast2xml(ast.NodeVisitor):
def __init__(self):
super(ast.NodeVisitor, self).__init__()
self.path = []
self.root = etree.Element('ast')
self.celement = self.root
self.lname = 'module'
def convert(self, tree):
self.visit(tree)
return etree.tostring(self.root)
def generic_visit(self, node):
self.path.append(type(node).__name__)
ocelement = self.celement
self.celement = etree.SubElement(self.celement, self.lname)
self.celement.attrib.update({'_name': type(node).__name__})
olname = self.lname
self.lname = type(node).__name__
for item in node.__dict__:
self.lname = item
if isinstance(getattr(node, item), ast.AST):
self.generic_visit(getattr(node, item))
elif isinstance(getattr(node, item), list):
ocel2 = self.celement
olname2 = self.lname
self.celement = etree.SubElement(self.celement, self.lname)
self.celement.attrib.update({'_name': '_list'})
self.lname = '_list_element'
[self.generic_visit(childnode) for childnode in getattr(node, item) if isinstance(childnode, (ast.AST, list))]
self.celement = ocel2
self.lname = olname2
else:
self.celement.attrib.update({item: str(getattr(node, item))})
self.path.pop()
self.celement = ocelement
self.lname = olname
def main(fpath):
with open(fpath, 'r') as f:
tree = ast.parse(f.read())
res = ast2xml().convert(tree)
print prettify(res)
if __name__ == '__main__':
main(sys.argv[1])
|
Converts a Python AST into an XML file.
Command line usage:
ast2xml.py <file>
Usage in another script:
import ast2xml
...
ast2xml.ast2xml().convert(ast_tree)