def create_element(handle: IO[bytes], element: Node, tokens: Dict[str, int], depth: int) -> bool: if element.tagName == "_var": return create_text(handle, element.firstChild, tokens, depth) # Open a new element() macros handle.write(b"\t" * depth) handle.write(b"element(\n") # First argument -- the tag name of the element handle.write(b"\t" * (depth + 1)) handle.write(f'"{element.tagName}",\n'.encode("utf-8")) # Second argument -- list of attributes attrs = element.attributes handle.write(b"\t" * (depth + 1)) if attrs: # Start the attrs() macro handle.write(b"attrs( ") for key in attrs.keys(): val = element.getAttribute(key) # Attribute values that start with $ are replacements # with the replacement token being the rest of the value. if val[0] == "$": tokens[val[1:]] = 1 handle.write(f'at_rep( "{key}", {val[1:]} ), '.encode("utf-8")) # Otherwise, the value is taken as a literal string else: handle.write(f'at_str( "{key}", "{val}" ), '.encode("utf-8")) # Each attribute above ends in ", ". To end the macro, we must # remove this and put the closing bracket. handle.seek(-2, SEEK_CUR) handle.write(b" ),\n") # No attributes just has this list point to NULL else: handle.write(b"NULL,\n") # Third argument: the list of child nodes handle.write(b"\t" * (depth + 1)) if element.hasChildNodes(): handle.write(b"children(\n") for child in element.childNodes: if create_node(handle, child, tokens, depth + 2): handle.seek(-1, SEEK_CUR) handle.write(b",\n") handle.seek(-2, SEEK_CUR) handle.write(b"\n") handle.write(b"\t" * (depth + 1)) handle.write(b")\n") else: handle.write(b"NULL\n") # End the element() macro handle.write(b"\t" * depth) handle.write(b")\n") # We create new code return True
def _node_to_dict(self, node: minidom.Node) -> dict: """ <node atr1="val1" atr2="val2></node> convert to "node": { "atr1":"val1", "atr2":"val2", "atr3":"val3" } AND <node> <atr1>val1</atr1> <atr2>val1</atr2> </node> *** will be convert to "node": { "atr1":"val1", "atr2":"val2", "atr3":"val3" } ////////////////////////////////////////////////// <node> <row>element1</row> <row>element2</row> <row>element3</row> </node> *** will be convert to "node":["element1","element2", "element3"] ////////////////////////////////////////////////// <node> <subnode>subnode value</subnode> <row>element1</row> <row>element2</row> <row>element3</row> </node> *** will be convert to "node":{ "subnode": "subnode value", "row": ["element1","element2", "element3"] } """ result = {} if isinstance(node, minidom.Document): if node.hasChildNodes(): return self._node_to_dict(node.childNodes[0]) else: return XDict() if not isinstance(node, minidom.Element): return XDict() attributes = node.attributes if attributes is None: no_attributes = True else: no_attributes = False result = dict(attributes.items()) values = {} for _node in node.childNodes: if isinstance(_node, minidom.Element): name = _node.tagName text = _node.firstChild if text is not None: text = text.data.strip() if text == '': text = None if text is None: value = self._node_to_dict(_node) else: if no_attributes: result['#text'] = text continue else: value = text if name in values: values[name].append(value) else: values[name] = [value] if len(values) == 1: result = values[list(values.keys())[0]] else: for name in values: value = values[name] if len(value) == 1: value = value[0] result[name] = value #result[name] = self._node_to_dict(_node) return result