예제 #1
0
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)
예제 #2
0
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:])
예제 #3
0
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
예제 #4
0
    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