telemeta.util.xmltodict2 module
xmltodict(): convert xml into tree of Python dicts.
This was copied and modified from John Bair's recipe at aspn.activestate.com: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/149368
# -*- coding: utf-8 -*- """ xmltodict(): convert xml into tree of Python dicts. This was copied and modified from John Bair's recipe at aspn.activestate.com: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/149368 """ import os import string import locale from xml.parsers import expat # If we're in Dabo, get the default encoding. #import dabo #import dabo.lib.DesignerUtils as desUtil #from dabo.dLocalize import _ #from dabo.lib.utils import resolvePath #app = dabo.dAppRef #if app is not None: #default_encoding = app.Encoding #else: #enc = locale.getlocale()[1] #if enc is None: #enc = dabo.defaultEncoding #default_encoding = enc # Python seems to need to compile code with \n linesep: code_linesep = "\n" eol = os.linesep default_encoding = 'utf-8' default_decoding = 'utf-8' class Xml2Obj: """XML to Object""" def __init__(self): self.root = None self.nodeStack = [] self.attsToSkip = [] self._inCode = False self._mthdName = "" self._mthdCode = "" self._codeDict = None self._inProp = False self._propName = "" self._propData = "" self._propDict = None self._currPropAtt = "" self._currPropDict = None def StartElement(self, name, attributes): """SAX start element even handler""" if name == "code": # This is code for the parent element self._inCode = True parent = self.nodeStack[-1] if not parent.has_key("code"): parent["code"] = {} self._codeDict = parent["code"] elif name == "properties": # These are the custom property definitions self._inProp = True self._propName = "" self._propData = "" parent = self.nodeStack[-1] if not parent.has_key("properties"): parent["properties"] = {} self._propDict = parent["properties"] else: if self._inCode: self._mthdName = name.encode() elif self._inProp: if self._propName: # In the middle of a prop definition self._currPropAtt = name.encode() else: self._propName = name.encode() self._currPropDict = {} self._currPropAtt = "" else: element = {"name": name.encode()} if len(attributes) > 0: for att in self.attsToSkip: if attributes.has_key(att): del attributes[att] element["attributes"] = attributes # Push element onto the stack and make it a child of parent if len(self.nodeStack) > 0: parent = self.nodeStack[-1] if not parent.has_key("children"): parent["children"] = [] parent["children"].append(element) else: self.root = element self.nodeStack.append(element) def EndElement(self, name): """SAX end element event handler""" if self._inCode: if name == "code": self._inCode = False self._codeDict = None else: # End of an individual method mth = self._mthdCode.strip() if not mth.endswith("\n"): mth += "\n" self._codeDict[self._mthdName] = mth self._mthdName = "" self._mthdCode = "" elif self._inProp: if name == "properties": self._inProp = False self._propDict = None elif name == self._propName: # End of an individual prop definition self._propDict[self._propName] = self._currPropDict self._propName = "" else: # end of a property attribute self._currPropDict[self._currPropAtt] = self._propData self._propData = self._currPropAtt = "" else: self.nodeStack = self.nodeStack[:-1] def CharacterData(self, data): """SAX character data event handler""" if self._inCode or data.strip(): data = data.replace("<", "<") data = data.encode(default_encoding) if self._inCode: if self._mthdCode: self._mthdCode += data else: self._mthdCode = data elif self._inProp: self._propData += data else: element = self.nodeStack[-1] if not element.has_key("cdata"): element["cdata"] = "" element["cdata"] += data def Parse(self, xml): # Create a SAX parser Parser = expat.ParserCreate(default_encoding) # SAX event handlers Parser.StartElementHandler = self.StartElement Parser.EndElementHandler = self.EndElement Parser.CharacterDataHandler = self.CharacterData # Parse the XML File ParserStatus = Parser.Parse(xml, 1) return self.root def ParseFromFile(self, filename): return self.Parse(open(filename,"r").read()) def xmltodict(xml, attsToSkip=[], addCodeFile=False): """Given an xml string or file, return a Python dictionary.""" parser = Xml2Obj() parser.attsToSkip = attsToSkip isPath = os.path.exists(xml) errmsg = "" if eol not in xml and isPath: # argument was a file try: ret = parser.ParseFromFile(xml) except expat.ExpatError, e: errmsg = "The XML in '%s' is not well-formed and cannot be parsed: %s" % (xml, e) else: # argument must have been raw xml: if not xml.strip().startswith("<?xml "): # it's a bad file name errmsg = "The file '%s' could not be found" % xml else: try: ret = parser.Parse(xml) except expat.ExpatError: errmsg = "An invalid XML string was encountered" if errmsg: raise Exception(errmsg) if addCodeFile and isPath: # Get the associated code file, if any codePth = "%s-code.py" % os.path.splitext(xml)[0] if os.path.exists(codePth): try: codeDict = desUtil.parseCodeFile(open(codePth).read()) desUtil.addCodeToClassDict(ret, codeDict) except StandardError, e: print "Failed to parse code file:", e return ret def escQuote(val, noEscape=False, noQuote=False): """Add surrounding quotes to the string, and escape any illegal XML characters. """ if not isinstance(val, basestring): val = str(val) if not isinstance(val, unicode): val = unicode(val, default_encoding) if noQuote: qt = '' else: qt = '"' slsh = "\\" # val = val.replace(slsh, slsh+slsh) if not noEscape: # First escape internal ampersands. We need to double them up due to a # quirk in wxPython and the way it displays this character. val = val.replace("&", "&&") # Escape any internal quotes val = val.replace('"', '"').replace("'", "'") # Escape any high-order characters chars = [] for pos, char in enumerate(list(val)): if ord(char) > 127: chars.append("&#%s;" % ord(char)) else: chars.append(char) val = "".join(chars) val = val.replace("<", "<").replace(">", ">") return "%s%s%s" % (qt, val, qt) def dicttoxml(dct, level=0, header=None, linesep=None): """Given a Python dictionary, return an xml string. The dictionary must be in the format returned by dicttoxml(), with keys on "attributes", "code", "cdata", "name", and "children". Send your own XML header, otherwise a default one will be used. The linesep argument is a dictionary, with keys on levels, allowing the developer to add extra whitespace depending on the level. """ att = "" ret = "" if dct.has_key("attributes"): for key, val in dct["attributes"].items(): # Some keys are already handled. noEscape = key in ("sizerInfo",) val = escQuote(val, noEscape) att += " %s=%s" % (key, val) ret += "%s<%s%s" % ("\t" * level, dct["name"], att) if (not dct.has_key("cdata") and not dct.has_key("children") and not dct.has_key("code") and not dct.has_key("properties")): ret += " />%s" % eol else: ret += ">" if dct.has_key("cdata"): ret += "%s" % dct["cdata"].decode(default_encoding).replace("<", "<") if dct.has_key("code"): if len(dct["code"].keys()): ret += "%s%s<code>%s" % (eol, "\t" * (level+1), eol) methodTab = "\t" * (level+2) for mthd, cd in dct["code"].items(): # Convert \n's in the code to eol: cd = eol.join(cd.splitlines()) # Make sure that the code ends with a linefeed if not cd.endswith(eol): cd += eol ret += "%s<%s><![CDATA[%s%s]]>%s%s</%s>%s" % (methodTab, mthd, eol, cd, eol, methodTab, mthd, eol) ret += "%s</code>%s" % ("\t" * (level+1), eol) if dct.has_key("properties"): if len(dct["properties"].keys()): ret += "%s%s<properties>%s" % (eol, "\t" * (level+1), eol) currTab = "\t" * (level+2) for prop, val in dct["properties"].items(): ret += "%s<%s>%s" % (currTab, prop, eol) for propItm, itmVal in val.items(): itmTab = "\t" * (level+3) ret += "%s<%s>%s</%s>%s" % (itmTab, propItm, itmVal, propItm, eol) ret += "%s</%s>%s" % (currTab, prop, eol) ret += "%s</properties>%s" % ("\t" * (level+1), eol) if dct.has_key("children") and len(dct["children"]) > 0: ret += eol for child in dct["children"]: ret += dicttoxml(child, level+1, linesep=linesep) indnt = "" if ret.endswith(eol): # Indent the closing tag indnt = ("\t" * level) ret += "%s</%s>%s" % (indnt, dct["name"], eol) if linesep: ret += linesep.get(level, "") if level == 0: if header is None: header = '<?xml version="1.0" encoding="%s" standalone="no"?>%s' \ % (default_encoding, eol) ret = header + ret return ret def flattenClassDict(cd, retDict=None): """Given a dict containing a series of nested objects such as would be created by restoring from a cdxml file, returns a dict with all classIDs as keys, and a dict as the corresponding value. The dict value will have keys for the attributes and/or code, depending on what was in the original dict. The end result is to take a nested dict structure and return a flattened dict with all objects at the top level. """ if retDict is None: retDict = {} atts = cd.get("attributes", {}) props = cd.get("properties", {}) kids = cd.get("children", []) code = cd.get("code", {}) classID = atts.get("classID", "") classFile = resolvePath(atts.get("designerClass", "")) superclass = resolvePath(atts.get("superclass", "")) superclassID = atts.get("superclassID", "") if superclassID and os.path.exists(superclass): # Get the superclass info superCD = xmltodict(superclass, addCodeFile=True) flattenClassDict(superCD, retDict) if classID: if os.path.exists(classFile): # Get the class info classCD = xmltodict(classFile, addCodeFile=True) classAtts = classCD.get("attributes", {}) classProps = classCD.get("properties", {}) classCode = classCD.get("code", {}) classKids = classCD.get("children", []) currDict = retDict.get(classID, {}) retDict[classID] = {"attributes": classAtts, "code": classCode, "properties": classProps} retDict[classID].update(currDict) # Now update the child objects in the dict for kid in classKids: flattenClassDict(kid, retDict) else: # Not a file; most likely just a component in another class currDict = retDict.get(classID, {}) retDict[classID] = {"attributes": atts, "code": code, "properties": props} retDict[classID].update(currDict) if kids: for kid in kids: flattenClassDict(kid, retDict) return retDict def addInheritedInfo(src, super, updateCode=False): """Called recursively on the class container structure, modifying the attributes to incorporate superclass information. When the 'updateCode' parameter is True, superclass code is added to the object's code """ atts = src.get("attributes", {}) props = src.get("properties", {}) kids = src.get("children", []) code = src.get("code", {}) classID = atts.get("classID", "") if classID: superInfo = super.get(classID, {"attributes": {}, "code": {}, "properties": {}}) src["attributes"] = superInfo["attributes"].copy() src["attributes"].update(atts) src["properties"] = superInfo.get("properties", {}).copy() src["properties"].update(props) if updateCode: src["code"] = superInfo["code"].copy() src["code"].update(code) if kids: for kid in kids: addInheritedInfo(kid, super, updateCode) #if __name__ == "__main__": #test_dict = {"name": "test", "attributes":{"path": "c:\\temp\\name", #"problemChars": "Welcome to <Jos\xc3\xa9's \ Stuff!>\xc2\xae".decode("latin-1")}} #print "test_dict:", test_dict #xml = dicttoxml(test_dict) #print "xml:", xml #test_dict2 = xmltodict(xml) #print "test_dict2:", test_dict2 #print "same?:", test_dict == test_dict2
Module variables
var code_linesep
var default_decoding
var default_encoding
var eol
Functions
def addInheritedInfo(
src, super, updateCode=False)
Called recursively on the class container structure, modifying the attributes to incorporate superclass information. When the 'updateCode' parameter is True, superclass code is added to the object's code
def addInheritedInfo(src, super, updateCode=False): """Called recursively on the class container structure, modifying the attributes to incorporate superclass information. When the 'updateCode' parameter is True, superclass code is added to the object's code """ atts = src.get("attributes", {}) props = src.get("properties", {}) kids = src.get("children", []) code = src.get("code", {}) classID = atts.get("classID", "") if classID: superInfo = super.get(classID, {"attributes": {}, "code": {}, "properties": {}}) src["attributes"] = superInfo["attributes"].copy() src["attributes"].update(atts) src["properties"] = superInfo.get("properties", {}).copy() src["properties"].update(props) if updateCode: src["code"] = superInfo["code"].copy() src["code"].update(code) if kids: for kid in kids: addInheritedInfo(kid, super, updateCode)
def dicttoxml(
dct, level=0, header=None, linesep=None)
Given a Python dictionary, return an xml string.
The dictionary must be in the format returned by dicttoxml(), with keys on "attributes", "code", "cdata", "name", and "children".
Send your own XML header, otherwise a default one will be used.
The linesep argument is a dictionary, with keys on levels, allowing the developer to add extra whitespace depending on the level.
def dicttoxml(dct, level=0, header=None, linesep=None): """Given a Python dictionary, return an xml string. The dictionary must be in the format returned by dicttoxml(), with keys on "attributes", "code", "cdata", "name", and "children". Send your own XML header, otherwise a default one will be used. The linesep argument is a dictionary, with keys on levels, allowing the developer to add extra whitespace depending on the level. """ att = "" ret = "" if dct.has_key("attributes"): for key, val in dct["attributes"].items(): # Some keys are already handled. noEscape = key in ("sizerInfo",) val = escQuote(val, noEscape) att += " %s=%s" % (key, val) ret += "%s<%s%s" % ("\t" * level, dct["name"], att) if (not dct.has_key("cdata") and not dct.has_key("children") and not dct.has_key("code") and not dct.has_key("properties")): ret += " />%s" % eol else: ret += ">" if dct.has_key("cdata"): ret += "%s" % dct["cdata"].decode(default_encoding).replace("<", "<") if dct.has_key("code"): if len(dct["code"].keys()): ret += "%s%s<code>%s" % (eol, "\t" * (level+1), eol) methodTab = "\t" * (level+2) for mthd, cd in dct["code"].items(): # Convert \n's in the code to eol: cd = eol.join(cd.splitlines()) # Make sure that the code ends with a linefeed if not cd.endswith(eol): cd += eol ret += "%s<%s><![CDATA[%s%s]]>%s%s</%s>%s" % (methodTab, mthd, eol, cd, eol, methodTab, mthd, eol) ret += "%s</code>%s" % ("\t" * (level+1), eol) if dct.has_key("properties"): if len(dct["properties"].keys()): ret += "%s%s<properties>%s" % (eol, "\t" * (level+1), eol) currTab = "\t" * (level+2) for prop, val in dct["properties"].items(): ret += "%s<%s>%s" % (currTab, prop, eol) for propItm, itmVal in val.items(): itmTab = "\t" * (level+3) ret += "%s<%s>%s</%s>%s" % (itmTab, propItm, itmVal, propItm, eol) ret += "%s</%s>%s" % (currTab, prop, eol) ret += "%s</properties>%s" % ("\t" * (level+1), eol) if dct.has_key("children") and len(dct["children"]) > 0: ret += eol for child in dct["children"]: ret += dicttoxml(child, level+1, linesep=linesep) indnt = "" if ret.endswith(eol): # Indent the closing tag indnt = ("\t" * level) ret += "%s</%s>%s" % (indnt, dct["name"], eol) if linesep: ret += linesep.get(level, "") if level == 0: if header is None: header = '<?xml version="1.0" encoding="%s" standalone="no"?>%s' \ % (default_encoding, eol) ret = header + ret return ret
def escQuote(
val, noEscape=False, noQuote=False)
Add surrounding quotes to the string, and escape any illegal XML characters.
def escQuote(val, noEscape=False, noQuote=False): """Add surrounding quotes to the string, and escape any illegal XML characters. """ if not isinstance(val, basestring): val = str(val) if not isinstance(val, unicode): val = unicode(val, default_encoding) if noQuote: qt = '' else: qt = '"' slsh = "\\" # val = val.replace(slsh, slsh+slsh) if not noEscape: # First escape internal ampersands. We need to double them up due to a # quirk in wxPython and the way it displays this character. val = val.replace("&", "&&") # Escape any internal quotes val = val.replace('"', '"').replace("'", "'") # Escape any high-order characters chars = [] for pos, char in enumerate(list(val)): if ord(char) > 127: chars.append("&#%s;" % ord(char)) else: chars.append(char) val = "".join(chars) val = val.replace("<", "<").replace(">", ">") return "%s%s%s" % (qt, val, qt)
def flattenClassDict(
cd, retDict=None)
Given a dict containing a series of nested objects such as would be created by restoring from a cdxml file, returns a dict with all classIDs as keys, and a dict as the corresponding value. The dict value will have keys for the attributes and/or code, depending on what was in the original dict. The end result is to take a nested dict structure and return a flattened dict with all objects at the top level.
def flattenClassDict(cd, retDict=None): """Given a dict containing a series of nested objects such as would be created by restoring from a cdxml file, returns a dict with all classIDs as keys, and a dict as the corresponding value. The dict value will have keys for the attributes and/or code, depending on what was in the original dict. The end result is to take a nested dict structure and return a flattened dict with all objects at the top level. """ if retDict is None: retDict = {} atts = cd.get("attributes", {}) props = cd.get("properties", {}) kids = cd.get("children", []) code = cd.get("code", {}) classID = atts.get("classID", "") classFile = resolvePath(atts.get("designerClass", "")) superclass = resolvePath(atts.get("superclass", "")) superclassID = atts.get("superclassID", "") if superclassID and os.path.exists(superclass): # Get the superclass info superCD = xmltodict(superclass, addCodeFile=True) flattenClassDict(superCD, retDict) if classID: if os.path.exists(classFile): # Get the class info classCD = xmltodict(classFile, addCodeFile=True) classAtts = classCD.get("attributes", {}) classProps = classCD.get("properties", {}) classCode = classCD.get("code", {}) classKids = classCD.get("children", []) currDict = retDict.get(classID, {}) retDict[classID] = {"attributes": classAtts, "code": classCode, "properties": classProps} retDict[classID].update(currDict) # Now update the child objects in the dict for kid in classKids: flattenClassDict(kid, retDict) else: # Not a file; most likely just a component in another class currDict = retDict.get(classID, {}) retDict[classID] = {"attributes": atts, "code": code, "properties": props} retDict[classID].update(currDict) if kids: for kid in kids: flattenClassDict(kid, retDict) return retDict
def xmltodict(
xml, attsToSkip=[], addCodeFile=False)
Given an xml string or file, return a Python dictionary.
def xmltodict(xml, attsToSkip=[], addCodeFile=False): """Given an xml string or file, return a Python dictionary.""" parser = Xml2Obj() parser.attsToSkip = attsToSkip isPath = os.path.exists(xml) errmsg = "" if eol not in xml and isPath: # argument was a file try: ret = parser.ParseFromFile(xml) except expat.ExpatError, e: errmsg = "The XML in '%s' is not well-formed and cannot be parsed: %s" % (xml, e) else: # argument must have been raw xml: if not xml.strip().startswith("<?xml "): # it's a bad file name errmsg = "The file '%s' could not be found" % xml else: try: ret = parser.Parse(xml) except expat.ExpatError: errmsg = "An invalid XML string was encountered" if errmsg: raise Exception(errmsg) if addCodeFile and isPath: # Get the associated code file, if any codePth = "%s-code.py" % os.path.splitext(xml)[0] if os.path.exists(codePth): try: codeDict = desUtil.parseCodeFile(open(codePth).read()) desUtil.addCodeToClassDict(ret, codeDict) except StandardError, e: print "Failed to parse code file:", e return ret
Classes
class Xml2Obj
XML to Object
class Xml2Obj: """XML to Object""" def __init__(self): self.root = None self.nodeStack = [] self.attsToSkip = [] self._inCode = False self._mthdName = "" self._mthdCode = "" self._codeDict = None self._inProp = False self._propName = "" self._propData = "" self._propDict = None self._currPropAtt = "" self._currPropDict = None def StartElement(self, name, attributes): """SAX start element even handler""" if name == "code": # This is code for the parent element self._inCode = True parent = self.nodeStack[-1] if not parent.has_key("code"): parent["code"] = {} self._codeDict = parent["code"] elif name == "properties": # These are the custom property definitions self._inProp = True self._propName = "" self._propData = "" parent = self.nodeStack[-1] if not parent.has_key("properties"): parent["properties"] = {} self._propDict = parent["properties"] else: if self._inCode: self._mthdName = name.encode() elif self._inProp: if self._propName: # In the middle of a prop definition self._currPropAtt = name.encode() else: self._propName = name.encode() self._currPropDict = {} self._currPropAtt = "" else: element = {"name": name.encode()} if len(attributes) > 0: for att in self.attsToSkip: if attributes.has_key(att): del attributes[att] element["attributes"] = attributes # Push element onto the stack and make it a child of parent if len(self.nodeStack) > 0: parent = self.nodeStack[-1] if not parent.has_key("children"): parent["children"] = [] parent["children"].append(element) else: self.root = element self.nodeStack.append(element) def EndElement(self, name): """SAX end element event handler""" if self._inCode: if name == "code": self._inCode = False self._codeDict = None else: # End of an individual method mth = self._mthdCode.strip() if not mth.endswith("\n"): mth += "\n" self._codeDict[self._mthdName] = mth self._mthdName = "" self._mthdCode = "" elif self._inProp: if name == "properties": self._inProp = False self._propDict = None elif name == self._propName: # End of an individual prop definition self._propDict[self._propName] = self._currPropDict self._propName = "" else: # end of a property attribute self._currPropDict[self._currPropAtt] = self._propData self._propData = self._currPropAtt = "" else: self.nodeStack = self.nodeStack[:-1] def CharacterData(self, data): """SAX character data event handler""" if self._inCode or data.strip(): data = data.replace("<", "<") data = data.encode(default_encoding) if self._inCode: if self._mthdCode: self._mthdCode += data else: self._mthdCode = data elif self._inProp: self._propData += data else: element = self.nodeStack[-1] if not element.has_key("cdata"): element["cdata"] = "" element["cdata"] += data def Parse(self, xml): # Create a SAX parser Parser = expat.ParserCreate(default_encoding) # SAX event handlers Parser.StartElementHandler = self.StartElement Parser.EndElementHandler = self.EndElement Parser.CharacterDataHandler = self.CharacterData # Parse the XML File ParserStatus = Parser.Parse(xml, 1) return self.root def ParseFromFile(self, filename): return self.Parse(open(filename,"r").read())
Ancestors (in MRO)
Instance variables
var attsToSkip
var nodeStack
var root
Methods
def __init__(
self)
def __init__(self): self.root = None self.nodeStack = [] self.attsToSkip = [] self._inCode = False self._mthdName = "" self._mthdCode = "" self._codeDict = None self._inProp = False self._propName = "" self._propData = "" self._propDict = None self._currPropAtt = "" self._currPropDict = None
def CharacterData(
self, data)
SAX character data event handler
def CharacterData(self, data): """SAX character data event handler""" if self._inCode or data.strip(): data = data.replace("<", "<") data = data.encode(default_encoding) if self._inCode: if self._mthdCode: self._mthdCode += data else: self._mthdCode = data elif self._inProp: self._propData += data else: element = self.nodeStack[-1] if not element.has_key("cdata"): element["cdata"] = "" element["cdata"] += data
def EndElement(
self, name)
SAX end element event handler
def EndElement(self, name): """SAX end element event handler""" if self._inCode: if name == "code": self._inCode = False self._codeDict = None else: # End of an individual method mth = self._mthdCode.strip() if not mth.endswith("\n"): mth += "\n" self._codeDict[self._mthdName] = mth self._mthdName = "" self._mthdCode = "" elif self._inProp: if name == "properties": self._inProp = False self._propDict = None elif name == self._propName: # End of an individual prop definition self._propDict[self._propName] = self._currPropDict self._propName = "" else: # end of a property attribute self._currPropDict[self._currPropAtt] = self._propData self._propData = self._currPropAtt = "" else: self.nodeStack = self.nodeStack[:-1]
def Parse(
self, xml)
def Parse(self, xml): # Create a SAX parser Parser = expat.ParserCreate(default_encoding) # SAX event handlers Parser.StartElementHandler = self.StartElement Parser.EndElementHandler = self.EndElement Parser.CharacterDataHandler = self.CharacterData # Parse the XML File ParserStatus = Parser.Parse(xml, 1) return self.root
def ParseFromFile(
self, filename)
def ParseFromFile(self, filename): return self.Parse(open(filename,"r").read())
def StartElement(
self, name, attributes)
SAX start element even handler
def StartElement(self, name, attributes): """SAX start element even handler""" if name == "code": # This is code for the parent element self._inCode = True parent = self.nodeStack[-1] if not parent.has_key("code"): parent["code"] = {} self._codeDict = parent["code"] elif name == "properties": # These are the custom property definitions self._inProp = True self._propName = "" self._propData = "" parent = self.nodeStack[-1] if not parent.has_key("properties"): parent["properties"] = {} self._propDict = parent["properties"] else: if self._inCode: self._mthdName = name.encode() elif self._inProp: if self._propName: # In the middle of a prop definition self._currPropAtt = name.encode() else: self._propName = name.encode() self._currPropDict = {} self._currPropAtt = "" else: element = {"name": name.encode()} if len(attributes) > 0: for att in self.attsToSkip: if attributes.has_key(att): del attributes[att] element["attributes"] = attributes # Push element onto the stack and make it a child of parent if len(self.nodeStack) > 0: parent = self.nodeStack[-1] if not parent.has_key("children"): parent["children"] = [] parent["children"].append(element) else: self.root = element self.nodeStack.append(element)