def __init__(self): self.typeParser = TypeParser()
class XMLConfigurationParser(object): def __init__(self): self.typeParser = TypeParser() def clean(self, text): if text is not None: return text.replace("\n", "").replace("\t", "") else: return "" def parseTupleOrListTag(self, element, structure, type): """ Parses a tag of type 'tuple' or 'list' and analyse the content type of this structure e.g.: <tag type="tuple(int)">"20", "10"</tag> <tag type="tuple(float)">"20.3", "10.1"</tag> <tag type="list(str)">"hello", "world"</tag> :type element: Element :param element: The element tree which contains the tag :rtype : tuple|list """ if structure == "tuple": return self.typeParser.tuple(element.text, type) if structure == "list": return self.typeParser.list(element.text, type) def processType(self, element): """ Process a value using the default cast, referenced by the type attribute into the tag e.g.: <tag type="int">20</tag> <tag type="float">1.9</tag> :type element: Element :param element: The tag to covert """ match = re.match(r"(?P<struct>tuple|list)\((?P<type>.*)\)", element.attrib["type"]) if match: processed = self.parseTupleOrListTag(element, match.group("struct"), match.group("type")) elif element.attrib["type"] == "int": processed = self.typeParser.int(element.text) elif element.attrib["type"] == "float": processed = self.typeParser.float(element.text) elif element.attrib["type"] == "bool": processed = self.typeParser.bool(element.text) else: processed = element.text return processed def XMLToDict(self, parent_element, template_args=None): """ Parse a XML etree object into a dict, recursively :type parent_element: Element :param parent_element: The parent element to serve as the wrapper of the dict :type template_args: dict :param template_args: Template arguments to process the tags with the 'template' attribute :returns The parsed dict """ result = dict() for element in parent_element: if len(element): obj = self.XMLToDict(element, template_args) else: obj = self.clean(element.text) if result.get(element.tag): if hasattr(result[element.tag], "append"): result[element.tag].append(obj) else: result[element.tag] = [result[element.tag], obj] else: if "type" in element.attrib: obj = self.processType(element) if "template" in element.attrib: if element.attrib["template"] == "true" and template_args != None: try: obj = element.text.format(**template_args) except KeyError as e: raise XMLTemplateError("Template parse error. Missing argument %s" % e.args) result[element.tag] = obj return result def parse(self, filePath, **variables): """ Parse a file and loads it into a structured format :type filePath: str :param filePath: The path to the XML configuration file :type variables: dict :param variables: The template variables to substitute in the xml file :rtype : DictStruct """ xml = None with open(filePath, "rt") as confFile: xml = ElementTree.parse(confFile) confDict = self.XMLToDict(xml._root, variables) return DictStruct(**confDict)