lxml iterparse в python не может обрабатывать пространства имен - PullRequest
7 голосов
/ 11 августа 2011
from lxml import etree
import StringIO

data= StringIO.StringIO('<root xmlns="http://some.random.schema"><a>One</a><a>Two</a><a>Three</a></root>')
docs = etree.iterparse(data,tag='a')
a,b = docs.next()


Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "iterparse.pxi", line 478, in lxml.etree.iterparse.__next__ (src/lxml/lxml.etree.c:95348)
  File "iterparse.pxi", line 534, in lxml.etree.iterparse._read_more_events (src/lxml/lxml.etree.c:95938)
StopIteration

Работает нормально, пока я не добавлю пространство имен в корневой узел.Любые идеи относительно того, что я могу сделать, как обойти, или правильный способ сделать это?Мне нужно быть управляемым событиями из-за очень больших файлов.

Ответы [ 2 ]

10 голосов
/ 11 августа 2011

Когда к нему прикреплено пространство имен, тег не a, а {http://some.random.schema}a. Попробуйте это:

from lxml import etree
import StringIO

data= StringIO.StringIO('<root xmlns="http://some.random.schema"><a>One</a><a>Two</a><a>Three</a></root>')
docs = etree.iterparse(data,tag='{http://some.random.schema}a')
for event, elem in docs:
    print event, elem
0 голосов
/ 11 августа 2011

Почему не с регулярным выражением?

1)

Использование lxml медленнее, чем использование регулярных выражений.

from time import clock
import StringIO



from lxml import etree

times1 = []
for i in xrange(1000):
    data= StringIO.StringIO('<root ><a>One</a><a>Two</a><a>Three\nlittle pigs</a><b>Four</b><a>another</a></root>')
    te = clock()
    docs = etree.iterparse(data,tag='a')
    tf = clock()
    times1.append(tf-te)
print min(times1)

print [etree.tostring(y) for x,y in docs]




import re

regx = re.compile('<a>[\s\S]*?</a>')

times2 = []
for i in xrange(1000):
    data= StringIO.StringIO('<root ><a>One</a><a>Two</a><a>Three\nlittle pigs</a><b>Four</b><a>another</a></root>')
    te = clock()
    li = regx.findall(data.read())
    tf = clock()
    times2.append(tf-te)
print min(times2)

print li

результат

0.000150298431784
['<a>One</a>', '<a>Two</a>', '<a>Three\nlittle pigs</a>', '<a>another</a>']
2.40253998762e-05
['<a>One</a>', '<a>Two</a>', '<a>Three\nlittle pigs</a>', '<a>another</a>']

0,000150298431784 / 2.40253998762e-05 - 6,25
lxml медленнее, чем регулярное выражение, в 6,25 раза

.

2)

Нет проблем, если пространство имен:

import StringIO
import re

regx = re.compile('<a>[\s\S]*?</a>')

data= StringIO.StringIO('<root xmlns="http://some.random.schema"><a>One</a><a>Two</a><a>Three\nlittle pigs</a><b>Four</b><a>another</a></root>')
print regx.findall(data.read())
*

результат * тысяча двадцать-одна

['<a>One</a>', '<a>Two</a>', '<a>Three\nlittle pigs</a>', '<a>another</a>']
...