Как объединить теги XML при условии (Python)? - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть файл XML, структурированный так:

<?xml version="1.0" encoding="utf-8" ?>
    <pages>
    <page id="1" bbox="0.000,0.000,462.047,680.315" rotate="0">
    <textbox id="0" bbox="179.739,592.028,261.007,604.510">
    <textline bbox="179.739,592.028,261.007,604.510">
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">C</text>
    <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">A</text>
    <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">P</text>
    <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">I</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">T</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">O</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">L</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">O</text>
    <text> </text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
    <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
    <text>
    </text>
    </textline>
    </textbox>
</page>
</pages>

Обратите внимание, что файл намного больше этого и повторяет страницы. Итак, у меня есть два вида тегов, различающихся шрифтом и размером шрифта. Я хочу объединить буквы одних и тех же тегов, поэтому мне нужен вывод, который сохраняет шрифт и размер шрифта, а также объединяет то, что можно объединить, например:

<?xml version="1.0" encoding="utf-8" ?>
        <pages>
        <page id="1" bbox="0.000,0.000,462.047,680.315" rotate="0">
        <textbox id="0" bbox="179.739,592.028,261.007,604.510">
        <textline bbox="179.739,592.028,261.007,604.510">
        <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">C</text>
        <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">API</text>
        <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">TOLO III</text>
        </textline>
        </textbox>
    </page>
    </pages>

Важно то, что Оригинальный порядок букв сохраняется вместе с тегами (поэтому я знаю, какой размер шрифта). Таким образом, код выглядит следующим образом:

import xml.etree.ElementTree as ET

MY_XML = ET.parse('fe.xml')

textlines = MY_XML.findall("./page/textbox/textline")

for textline in textlines:
    fulltext = []
    for text_elem in list(textline):
        # Get the text of each 'text' element and then remove it
        fulltext.append(text_elem.text)
        textline.remove(text_elem)

    # Create a new 'text' element and add the joined letters to it
    new_text_elem = ET.Element("text", font="NUMPTY+ImprintMTnum", ncolour="0", size="12.482")
    new_text_elem.text = "".join(fulltext).strip()

    # Append the new 'text' element to its parent
    textline.append(new_text_elem)

print(ET.tostring(MY_XML.getroot(), encoding="unicode"))

Но он работает только для одного тега. Я думаю, мне нужно было бы поставить условие, чтобы for l oop проверял все теги, но я не нашел в сети информации о том, как это сделать. Как я могу включить другой тег? Большое спасибо

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Ниже приведено логическое ядро ​​c, которое необходимо реализовать.

Это не сквозное решение, но оно заботится о базовой логике c.

import xml.etree.ElementTree as ET


xml = '''<?xml version="1.0" encoding="utf-8" ?>
<pages>
    <page id="1" bbox="0.000,0.000,462.047,680.315" rotate="0">
        <textbox id="0" bbox="179.739,592.028,261.007,604.510">
            <textline bbox="179.739,592.028,261.007,604.510">
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">C</text>
                <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">A</text>
                <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">P</text>
                <text font="NUMPTY+ImprintMTnum-it"  ncolour="0" size="12.333">I</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">T</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">O</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">L</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">O</text>
                <text> </text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
                <text font="NUMPTY+ImprintMTnum"  ncolour="0" size="12.482">I</text>
                <text>
                </text>
            </textline>
        </textbox>
    </page>
</pages>'''
words = []
root = ET.fromstring(xml)
pages = root.findall('.//page')
for page in pages:
    previous_key = None
    current_key = None
    texts = page.findall('.//text')
    for txt in texts:
        if previous_key:
            current_key = (txt.attrib.get('font',previous_key[0]),txt.attrib.get('size',previous_key[1]))
        else:
            current_key = (txt.attrib.get('font','empty'),txt.attrib.get('size','empty'))
        if current_key != previous_key:
            words.append([])
        words[-1].append(txt.text)
        previous_key = current_key

for group in words:
    if group:
        print(''.join(group))

output

C
API
TOLO III
1 голос
/ 11 апреля 2020

Почему new_text_elem является жестко закодированным элементом с фиксированными атрибутами? Вы не знаете, какие атрибуты назначать.

Попробуйте следующее. Создайте еще один внутренний элемент для l oop, который записывает ВСЕ теги в словарь. Вы также можете перебирать теги.

Для следующего элемента проверьте, все ли теги находятся в словаре и совпадают ли они. Прочитайте о словарном сравнении или просто переберите ключи и сравните их с ==.

Если они одинаковые, добавьте элемент в список идентичных элементов, которые вы уже нашли. Затем проверьте следующий элемент.

Если они не совпадают, добавьте все элементы списка в качестве нового элемента, объединяя текст. Затем очистите список и начните все сначала.

Сводка:

  • Вы перебираете элементы <text>.
  • Сохраняете все подряд <text> Элементы имеют одинаковые теги в списке.
  • Хранение их один за другим в списке сохраняет порядок.
  • Как только вы встретите первый элемент <text>, запишите сохраненные. во-первых, объединяя их текст, используя их сохраненные теги и значения.
  • Очистите список магазинов и повторите.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...