def process_aux(self, conf_tree: etree._Element, rule_tree: etree._Element): for conf_elem in conf_tree.iterchildren(tag=etree.Element): conf_tag = conf_elem.tag rule_elem = rule_tree.findall(conf_tag) if len(rule_elem ) > 0: # If the entry corresponds to one or more rules if len(rule_elem) == 1: rule_elem = rule_elem[0] action_attr = rule_elem.get('action', default=None) if action_attr is not None and action_attr == 'no-translate': # If labeled "no translate", skip pass elif len(conf_elem) > 0: # If the config file has subelements if len(rule_elem) > 0: # If the rules also have subelements self.process_aux(conf_elem, rule_elem) # recursive call else: # If no corresponding elements in rules logging.warning( f'Mismatch between element contents: {conf_elem} and rule: {rule_elem}' ) else: # Otherwise, it is a key-value pair self.add_property(rule_elem.text, conf_elem.text) else: # If the rules have a list, self.process_multi( conf_elem, rule_elem ) # We are distinguishing cases based on attribute else: # If the key isn't in the rules, ignore it but warn because it is probably an error. logging.warning(f"Tag {conf_tag} is not in element rules.")
def merge_nodes(src: etree._Element, dst: etree._Element): """ Merges the node ``src`` including their subelements to ``dst``. The Nodes are considered as equal - and thus merged - if their fully qualified names are identical. Different matching and merging strategies will be added as needed. """ def child_with_qname(element: etree._Element, qname: etree.QName): for child in element.iterchildren(qname.text): if etree.QName(child).text == qname.text: return child merged_elements = set() for child in dst.iterchildren(): twin = child_with_qname(src, etree.QName(child)) if twin is not None: merge_nodes(twin, child) merged_elements.add(twin) for child in src.iterchildren(): if child in merged_elements: continue dst.append(deepcopy(child))
def _evaluate_node(self, node: etree._Element) -> ast.Node: qname = etree.QName(node.tag) if node.tag in self.tag_map: parse_func = self.tag_map[node.tag] elif qname.namespace in self.namespace_map: parse_func = self.namespace_map[qname.namespace] else: raise NodeParsingError(f"Cannot parse XML tag {node.tag}") if parse_func.subiter: sub_nodes = [ self._evaluate_node(child) for child in node.iterchildren() ] return parse_func(self, node, *sub_nodes) else: return parse_func(self, node)
def _parse_number(element: _Element, _: str) -> str: result = [] if element.text is not None: result.append(element.text.strip()) for child in element.iterchildren(): if child.attrib['class'] == 'shopNum': # result.append(self.font_parser.parse(num_font_url, child.text).strip()) result.append('1') else: result.append(child.text.strip()) if child.tail is not None: result.append(child.tail.strip()) return ''.join(result).strip()
def _parse_number(self, element: _Element, num_font_url: str) -> str: result = [] if element.text is not None: result.append(element.text.strip()) for child in element.iterchildren(): if child.tag == 'p': result.append(self._parse_number(child, num_font_url)) elif child.attrib['class'] == 'num': result.append(self.font_parser.parse('num', num_font_url, child.text).strip()) else: result.append(child.text.strip()) if child.tail is not None: result.append(child.tail.strip()) return ''.join(result).strip()
def _process_dxcc(self, resp_xml: etree._Element) -> Union[QrzDxccData, List[QrzDxccData]]: # check for errors like "not found" self._process_check_session(resp_xml) resp_xml_data = list(resp_xml.iterchildren(tag="{http://xmldata.qrz.com}DXCC")) data_list = [{el.tag.split("}")[1]: el.text for el in itm.getiterator()} for itm in resp_xml_data] # type: ignore parsed = [] for data in data_list: dxccdata = QrzDxccData() dxccdata.dxcc = int(data.get("dxcc", 0)) dxccdata.cc2 = data.get("cc", "") dxccdata.cc3 = data.get("ccc", "") dxccdata.name = data.get("name", "") cont = data.get("continent", None) if cont == "AF": dxccdata.continent = Continent.AF elif cont == "AS": dxccdata.continent = Continent.AS elif cont == "EU": dxccdata.continent = Continent.EU elif cont == "NA": dxccdata.continent = Continent.NA elif cont == "OC": dxccdata.continent = Continent.OC elif cont == "SA": dxccdata.continent = Continent.SA dxccdata.ituzone = int(data.get("ituzone", 0)) dxccdata.cqzone = int(data.get("cqzone", 0)) dxccdata.utc_offset = data.get("timezone", "") dxccdata.latlong = LatLong(float(data.get("lat", 0)), float(data.get("lon", 0))) dxccdata.notes = data.get("notes", "") parsed.append(dxccdata) if len(parsed) == 1: return parsed[0] return parsed
def parse_xmlelement( self, xmlelement: etree._Element, schema: "Schema" = None, allow_none: bool = True, context: XmlParserContext = None, schema_type: "Type" = None, ) -> typing.Optional[typing.Union[str, CompoundValue, typing.List[etree._Element]]]: """Consume matching xmlelements and call parse() on each :param xmlelement: XML element objects :param schema: The parent XML schema :param allow_none: Allow none :param context: Optional parsing context (for inline schemas) :param schema_type: The original type (not overriden via xsi:type) """ # If this is an empty complexType (<xsd:complexType name="x"/>) if not self.attributes and not self.elements: return None attributes = xmlelement.attrib init_kwargs = OrderedDict() # If this complexType extends a simpleType then we have no nested # elements. Parse it directly via the type object. This is the case # for xsd:simpleContent if isinstance(self._element, Element) and isinstance( self._element.type, AnySimpleType ): name, element = self.elements_nested[0] init_kwargs[name] = element.type.parse_xmlelement( xmlelement, schema, name, context=context ) else: elements = deque(xmlelement.iterchildren()) if allow_none and len(elements) == 0 and len(attributes) == 0: return None # Parse elements. These are always indicator elements (all, choice, # group, sequence) assert len(self.elements_nested) < 2 for name, element in self.elements_nested: try: result = element.parse_xmlelements( elements, schema, name, context=context ) if result: init_kwargs.update(result) except UnexpectedElementError as exc: raise XMLParseError(exc.message) # Check if all children are consumed (parsed) if elements: if schema.settings.strict: raise XMLParseError("Unexpected element %r" % elements[0].tag) else: init_kwargs["_raw_elements"] = elements # Parse attributes if attributes: attributes = copy.copy(attributes) for name, attribute in self.attributes: if attribute.name: if attribute.qname.text in attributes: attr_value = attributes.pop(attribute.qname.text) init_kwargs[name] = attribute.parse(attr_value) else: init_kwargs[name] = attribute.parse(attributes) value: CompoundValue = self._value_class(**init_kwargs) schema_type = schema_type or self if schema_type and getattr(schema_type, "_array_type", None): return schema_type._array_class.from_value_object(value) return value
def unwrap_value(element: _Element) -> XmlRpcTypes: try: return xml2py(next(iter(element.iterchildren()))) except StopIteration: return xml2py(element.text or "")
def child_with_qname(element: etree._Element, qname: etree.QName): for child in element.iterchildren(qname.text): if etree.QName(child).text == qname.text: return child