Created
May 16, 2014 18:30
-
-
Save akavel/eabf0a5002ff8ef1b976 to your computer and use it in GitHub Desktop.
Python AST to XML (Python recipe). Converts Python ASTs to XML files for reading in other languages. http://code.activestate.com/recipes/578625-python-ast-to-xml/ Created by Ryan Gonzalez on Wed, 7 Aug 2013 (MIT) meta:license=mit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment