Вы можете использовать XPath 'product/*[starts-with(local-name(),"element")]'
:
import lxml.etree as ET
import io
content = '''\
<catalog>
<product>
<element1>text 1</element1>
<element2>text 2</element2>
<element3>text ..</element3>
</product>
</catalog>'''
def fast_iter(context, func, *args, **kwargs):
"""
http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
Author: Liza Daly
See also http://effbot.org/zone/element-iterparse.htm
"""
for event, elem in context:
func(elem, *args, **kwargs)
# It's safe to call clear() here because no descendants will be
# accessed
elem.clear()
# Also eliminate now-empty references from the root node to elem
for ancestor in elem.xpath('ancestor-or-self::*'):
while ancestor.getprevious() is not None:
del ancestor.getparent()[0]
del context
def process_element(catalog):
for elt in catalog.xpath('product/*[starts-with(local-name(),"element")]'):
print(elt)
context = ET.iterparse(io.BytesIO(content), tag='catalog', events = ('end',))
fast_iter(context, process_element)
дает
<Element element1 at 0xb7449374>
<Element element2 at 0xb744939c>
<Element element3 at 0xb74493c4>
Кстати, я сделал изменения в fast_iter Лиз Дейли, который будет удалять больше элементов, поскольку они становятся невостребованными. Это должно уменьшить требования к памяти при анализе больших XML-файлов.
Вот пример, который показывает, как модифицированный fast_iter
выше удаляет больше элементов, чем оригинальный fast_iter
:
import logging
import textwrap
import lxml.etree as ET
import io
logger = logging.getLogger(__name__)
level = logging.INFO
# level = logging.DEBUG # uncomment to see more debugging information
logging.basicConfig(level=level)
def fast_iter(context, func, *args, **kwargs):
"""
http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
Author: Liza Daly
See also http://effbot.org/zone/element-iterparse.htm
"""
for event, elem in context:
logger.debug('Processing {e}'.format(e=ET.tostring(elem)))
func(elem, *args, **kwargs)
# It's safe to call clear() here because no descendants will be
# accessed
logger.debug('Clearing {e}'.format(e=ET.tostring(elem)))
elem.clear()
# Also eliminate now-empty references from the root node to elem
for ancestor in elem.xpath('ancestor-or-self::*'):
logger.debug('Checking ancestor: {a}'.format(a=ancestor.tag))
while ancestor.getprevious() is not None:
logger.info('Deleting {p}'.format(
p=(ancestor.getparent()[0]).tag))
del ancestor.getparent()[0]
del context
def orig_fast_iter(context, func, *args, **kwargs):
for event, elem in context:
logger.debug('Processing {e}'.format(e=ET.tostring(elem)))
func(elem, *args, **kwargs)
logger.debug('Clearing {e}'.format(e=ET.tostring(elem)))
elem.clear()
while elem.getprevious() is not None:
logger.info('Deleting {p}'.format(
p=(elem.getparent()[0]).tag))
del elem.getparent()[0]
del context
def setup_ABC():
content = textwrap.dedent('''\
<root>
<A1>
<B1></B1>
<C>1<D1></D1></C>
<E1></E1>
</A1>
<A2>
<B2></B2>
<C>2<D></D></C>
<E2></E2>
</A2>
</root>
''')
return content
content = setup_ABC()
context = ET.iterparse(io.BytesIO(content), events=('end',), tag='C')
orig_fast_iter(context, lambda elem: None)
# DEBUG:__main__:Deleting B1
# DEBUG:__main__:Deleting B2
print('-'*80)
"""
The improved fast_iter deletes A1. The original fast_iter does not.
"""
content = setup_ABC()
context = ET.iterparse(io.BytesIO(content), events=('end',), tag='C')
fast_iter(context, lambda elem: None)
# DEBUG:__main__:Deleting B1
# DEBUG:__main__:Deleting A1
# DEBUG:__main__:Deleting B2
Таким образом, вы видите, модифицированный fast_iter
удается удалить A1
элемент, поскольку он не нужен к тому времени обрабатывается второй элемент C
. В оригинале fast_iter
удаляются только родители из C
элементов (т. Е. B
элементов). Вы могли бы представить, что такие вещи, как A1
, могут быть довольно большими в большом XML-файле, и таких элементов может быть много. Таким образом, модифицированный fast_iter
позволит осваивать много памяти, что оригинал fast_iter
не освобождает.
У вас есть вопросы? –
Как я могу перечислить все элементы в моем продукте? – Benabra
Что вы подразумеваете под "* list *"? Вы имеете в виду распечатать их по стандарту? Вы имеете в виду создать «список», члены которого связаны с вашим ''? –