def extend_element( element: etree.ElementBase, children_or_attributes: Iterable[etree.ElementBase] ): for item in children_or_attributes: if isinstance(item, dict): element.attrib.update(item) continue if isinstance(item, str): try: previous_element = element[-1] except IndexError: previous_element = None if previous_element is not None: previous_element.tail = ( (previous_element.tail or '') + item ) else: element.text = ( (element.text or '') + item ) continue element.append(item)
def get_or_create_element_at(parent: etree.ElementBase, path: List[str]) -> etree.ElementBase: if not path: return parent child = parent.find(TEI_NS_PREFIX + path[0]) if child is None: LOGGER.debug('creating element: %s', path[0]) tag_expression = parse_tag_expression(path[0]) child = tag_expression.create_node( element_maker=TEI_E ) parent.append(child) return get_or_create_element_at(child, path[1:])
def _get_element_at_path( current_element: etree.ElementBase, current_path: Sequence[str], required_path: Sequence[str], element_maker: ElementMaker ) -> Tuple[etree.ElementBase, Sequence[str]]: if required_path != current_path: common_path = _get_common_path(current_path, required_path) LOGGER.debug('required element path: %s -> %s (common path: %s)', current_path, required_path, common_path) for _ in range(len(current_path) - len(common_path)): current_element = current_element.getparent() current_path = list(common_path) for path_fragment in required_path[len(common_path):]: try: parsed_path_fragment = parse_tag_expression(path_fragment) child = parsed_path_fragment.create_node( element_maker=element_maker) except ValueError as exc: raise ValueError('failed to create node for %r due to %s' % (path_fragment, exc)) from exc current_element.append(child) current_element = child current_path.append(path_fragment) return current_element, current_path
def add(self, name: str, figure_template: et.ElementBase, diagram_root: et.ElementBase): """ Добавляет фигуру на схему """ # скопируем xml-объект фигуры из шаблона xml_object_template: et.ElementBase = figure_template xml_object: et.ElementBase = deepcopy(xml_object_template) cell: et.ElementBase = xml_object.getchildren()[0] geometry: et.ElementBase = cell.getchildren()[0] # создадим фигуру child_figure: Figure = Figure(self, xml_object, name, figure_template.attrib['type']) # инкремент ключа в случае совпадения с уже имеющимся if child_figure.id in g_figures.keys(): key_incrementer: int = 2 while f'{child_figure.id}-{str(key_incrementer)}' in g_figures.keys( ): key_incrementer += 1 child_figure.id += '-' + str(key_incrementer) g_figures[ child_figure. id] = child_figure # добавим значение по уникальному ID в словарь фигур if 'max_rows' in figure_template.attrib: child_figure.max_rows = int(figure_template.attrib['max_rows']) del xml_object.attrib['max_rows'] if 'padding' in figure_template.attrib: child_figure.padding = int(figure_template.attrib['padding']) del xml_object.attrib['padding'] # добавим фигуру в схему xml_object.attrib['id'] = child_figure.id exist_xml_object: et.ElementBase = diagram_root.find( f'object[@id="{child_figure.id}"]') if exist_xml_object is None: diagram_root.append(xml_object) else: # фиксируем положение фигуры child_figure.is_exists = True exist_cell: et.ElementBase = exist_xml_object.getchildren()[0] exist_geometry: et.ElementBase = exist_cell.getchildren()[0] # if 'edge' in exist_cell.attrib: # для соединений сохраним геометрию целиком new_geometry = deepcopy(exist_geometry) cell.replace(geometry, new_geometry) geometry = new_geometry # else: # # для фигур фиксируем положение (x, y) # geometry.attrib['x'] = exist_geometry.attrib['x'] # geometry.attrib['y'] = exist_geometry.attrib['y'] diagram_root.replace(exist_xml_object, xml_object) child_figure.geometry = geometry if 'edge' in cell.attrib: # соединение cell.attrib['source'] = self.xml_object.attrib[ 'id'] # источник - родительская фигура self.connectors.append(child_figure) return child_figure # далее обрабатываем фигуры, не являющиеся соединениями # имя соединения в глобальный список не добавляем g_figures[ name] = child_figure # наименование, может быть не уникально, перезаписывается # пересчитаем оценку площади фигур child_figure.min_area = float(geometry.attrib['width']) * float( geometry.attrib['height']) parent: Figure = self while parent is not None: parent.min_area += child_figure.min_area parent = parent.parent if 'align' in xml_object.attrib: # фигура "прилеплена" к границе родителя align_type: str = xml_object.attrib['align'] if self.aligned_figures.get(align_type) is None: self.aligned_figures[align_type] = [] self.aligned_figures[align_type].append(xml_object) else: # фигура вложена в контейнер self.inner_figures.append(child_figure) return child_figure