Как найти и удалить элементы в XML-файле (с name_spaces) по условию с Python - PullRequest
0 голосов
/ 20 октября 2019

У меня есть файл XML, из которого я хочу удалить элементы в зависимости от условий. Однако файл XML имеет пространства имен, которые по какой-то неясной причине не позволяют мне выполнить описанные процедуры: 1 , 2 , 3 , 4 и 5 .

Мой XML выглядит следующим образом:

    <?xml version='1.0' encoding='UTF-8'?>
        <PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15/pagecontent.xsd">
            <Page imageFilename="1.png">
                <TextRegion custom="a">
                    <TextLine custom="readingOrder {index:0;}" id="Ar0010001l1">
                        <TextEquiv>
                            <Unicode> abc </Unicode>
                        </TextEquiv>
                    </TextLine>
                    <TextLine custom="readingOrder {index:1;}" id="Ad0010100l2">
                        <TextEquiv>
                            <Unicode />
                        </TextEquiv>
                </TextRegion>
            </Page>
        </PcGts>

Моя цель - очистить все узлы TextLine, где нет текста в «Юникоде»" тег. Таким образом, результат будет:

    <?xml version='1.0' encoding='UTF-8'?>
        <PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15/pagecontent.xsd">
            <Page imageFilename="1.png">
                <TextRegion custom="a">
                    <TextLine custom="readingOrder {index:0;}" id="Ar0010001l1">
                        <TextEquiv>
                            <Unicode> abc </Unicode>
                        </TextEquiv>
                    </TextLine>
                </TextRegion>
            </Page>
        </PcGts>

Я попытался использовать некоторые из предложений в ссылках выше. но:

 import lxml.etree as ET
 data = ET.parse(file)
 root = data.getroot()
 for x in root.xpath("//Unicode"):
     print(x.text)

тег не найден. и еще одна попытка:

for x in root.xpath("//{http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15}Unicode"):
   print(x.text)

выдает «XPathEvalError: Invalid expression»

Хорошо, каков самый простой способ удалить все узлы, тег Unicode которых пуст в этом XML-файле (и какнайти их вообще?)

Спасибо.

Ответы [ 2 ]

1 голос
/ 20 октября 2019

Во-первых, у вас в xml отсутствует закрывающий тег для <TextLine custom="readingOrder {index:1;}" id="Ad0010100l2">, но если вы вставите его в подходящее место, вы должны получить следующее:

my_xml = """[your xml above, corrected]"""
data = ET.XML(my_xml.encode('ascii'))
for target in data.xpath("//*[local-name() = 'Unicode'][not(text())]"):
    target.getparent().remove(target)     

print(etree.tostring(data,  xml_declaration=True))

Вывод:

    <?xml version=\'1.0\' encoding=\'ASCII\'?>\n
<PcGts
    xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2013-07-15/pagecontent.xsd">
    <Page imageFilename="1.png">
        <TextRegion custom="a">
            <TextLine custom="readingOrder {index:0;}" id="Ar0010001l1">
                <TextEquiv>
                    <Unicode> abc </Unicode>
                </TextEquiv>
            </TextLine>
            <TextLine custom="readingOrder {index:1;}" id="Ad0010100l2">
                <TextEquiv/>
            </TextLine>
        </TextRegion>
    </Page>
</PcGts>  
0 голосов
/ 24 октября 2019

Ну, я наконец-то нашел решение проблемы.

import lxml.etree as ET
my_xml = """...xml content..."""
data = ET.XML(my_xml.encode('UTF-8'))

#this loop remove "<Unicode />" tags.
for target in data.xpath("//*[local-name() = 'Unicode'][not(text())]"):
    target.getparent().remove(target)  

#and this loop remove nodes without children like "<TextEquiv><Unicode /></TextEquiv>" 
#(after the removing of "<Unicode />")
for el in data.iter():
    if len(list(el.iterchildren())) or ''.join([_.strip() for _ in el.itertext()]):
        pass
    else:
        parent = el.getparent()
        if parent is not None:
            parent.remove(el)
#and this loop remove nodes without children again, but now - it's "<TextLine>" tag
for el in data.iter():
    if len(list(el.iterchildren())) or ''.join([_.strip() for _ in el.itertext()]):
        pass
    else:
        parent = el.getparent()
        if parent is not None:
            parent.remove(el)

print(ET.tostring(data,  xml_declaration=True))

Идея пришла от Удаление узлов XML без дочерних узлов с помощью python

...