У меня есть большой (5+ гигабайт) XML-файл, который мне нужно проанализировать, выполнить некоторые операции и написать новый XML-файл.
dummy.xml
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
<header>
<name>Product Catalog</name>
</header>
<product product-id="1234">
<available-flag>false</available-flag>
<name>product1</name>
</product>
<product product-id="5678">
<available-flag>false</available-flag>
<name>product1</name>
</product>
<product product-id="9999">
<available-flag>false</available-flag>
<name>product1</name>
</product>
</catalog>
Как высм. выше XML имеет 3 product
тегов, и мне нужно отфильтровать некоторые идентификаторы продуктов на основе предварительно определенного списка идентификаторов.
Я использую lxml iterparse
для итеративного анализа XML и хочуиспользовать xmlfile
API для создания нового XML в пошаговом режиме, чтобы сохранить объем памяти.Итак, мой мотив состоит в том, чтобы отфильтровать теги продукта, которые не соответствуют критериям, и скопировать остальные теги XML, как есть.
from lxml import etree
f = './dummy.xml'
f1 = './test.xml'
context = etree.iterparse(f, events=('start',))
productsToExport = ['1234']
with etree.xmlfile(f1, encoding='utf-8') as xf:
xf.write_declaration()
with xf.element('catalog xmlns="http://www.namespace.com" catalog-id="test-catalog"'):
for event, element in context:
tagName = etree.QName(element.tag).localname
if (tagName == 'product'):
pid = element.get('product-id')
if (pid in productsToExport):
xf.write(element)
elif (tagName == 'header'):
xf.write(element) # copy existing header tag as it is
Над кодом работает нормально и генерирует XML, как показано ниже
<?xml version='1.0' encoding='utf-8'?>
<catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
<header xmlns="http://www.namespace.com">
<name>Product Catalog</name>
</header>
<product xmlns="http://www.namespace.com" product-id="1234">
<available-flag>false</available-flag>
<name>product1</name>
</product>
</catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
Если вы наблюдаете вышеупомянутый XML, у него есть несколько проблем:
- Закрывающий тег
<catalog>
содержит xmlns
& catalog-id
в нем - Все теги, такие как
header, product
, имеют атрибут xmlns
, присутствующий в нем
Я проверил Документация API xmlfile , но не смог найти способ исправить вышеуказанные проблемы.
РЕДАКТИРОВАТЬ:
Мне удалось решить 1-й вопрос, используя ниже
attribs = {'xmlns' : 'http://www.namespace.com', 'catalog-id' : 'test-catalog'}
with xf.element('catalog', attribs):
# previous logic
Итак, теперь мне осталось удалить пространство имен из каждого элемента.