Есть ли элегантный способ подсчета элементов тега в файле XML с использованием lxml в Python? - PullRequest
15 голосов
/ 26 июня 2011

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

Учитывая xml-файл (см. Ниже), как вы подсчитываете xml-теги, например, количество авторских тегов в примере ниже самого элегантного способа ? Предполагается, что каждый автор появляется ровно один раз.

<root>
    <author>Tim</author>
    <author>Eva</author>
    <author>Martin</author>
    etc.
</root>

Этот xml-файл тривиален, но возможно, что авторы не всегда перечисляются один за другим, между ними могут быть другие теги.

Ответы [ 3 ]

24 голосов
/ 26 июня 2011

Если вы хотите сосчитать все теги автора:

import lxml.etree
doc = lxml.etree.parse(xml)
count = doc.xpath('count(//author)')
8 голосов
/ 26 июня 2011

Используйте XPath с count.

2 голосов
/ 26 июня 2011

Нужно быть осторожным, используя модуль re для обработки текста SGML / XML / HTML, потому что не все обработки таких файлов не могут быть выполнены с помощью регулярных выражений (регулярные выражения не могут парсинг текст SGML / HTML / XML)

Но здесь, в этой конкретной проблеме, мне кажется, что это возможно (re.DOTALL является обязательным, потому что элемент может занимать более одной строки; кроме этого, я не могу представить никакой другой возможной ошибки)

from time import clock
n= 10000
print 'n ==',n,'\n'



import lxml.etree
doc = lxml.etree.parse('xml.txt')

te = clock()
for i in xrange(n):
    countlxml = doc.xpath('count(//author)')
tf = clock()
print 'lxml\ncount:',countlxml,'\n',tf-te,'seconds'



import re
with open('xml.txt') as f:
    ch = f.read()

regx = re.compile('<author>.*?</author>',re.DOTALL)
te = clock()
for i in xrange(n):
    countre = sum(1 for mat in regx.finditer(ch))
tf = clock()
print '\nre\ncount:',countre,'\n',tf-te,'seconds'

результат

n == 10000 

lxml
count: 3.0 
2.84083032899 seconds

re
count: 3 
0.141663256084 seconds
...