У меня есть файл 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-файле (и какнайти их вообще?)
Спасибо.
Во-первых, у вас в xml отсутствует закрывающий тег для <TextLine custom="readingOrder {index:1;}" id="Ad0010100l2">, но если вы вставите его в подходящее место, вы должны получить следующее:
<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>
Ну, я наконец-то нашел решение проблемы.
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