次のストリーム指向の XML 解析ハックでは、Python 標準ライブラリのみを使用します。
長々とした回答で申し訳ありません:XMLの解析は非常に面倒なので、「創造的に」行う方法を見つけることを好みます:)
次のコードは、結果のタプルをリストに蓄積します。しかし、コルーチンは任意の方法で連鎖できるため、車両のタプルを遅延取得して 1 つずつまたはチャンクなどで処理する、より堅牢なソリューションにこれを進化させることができます。
# Remixed from: http://www.dabeaz.com/coroutines/cosax.py
# Don't shy away from reading http://www.dabeaz.com/coroutines/ if the stuff below
# seems weird.
from xml.sax import ContentHandler, parse
from collections import namedtuple
ElementStart = namedtuple('ElementStart', 'name attrs')
ElementEnd = namedtuple('ElementEnd', 'name')
class LazySax(ContentHandler):
def __init__(self, target):
self.target = target
def startElement(self, name, attrs):
self.target.send(ElementStart(name, attrs._attrs))
def endElement(self, name):
self.target.send(ElementEnd(name))
def pull_tuples(tuples):
while True:
event = yield
if isinstance(event, ElementStart) and event.name == 'vehicle':
vid = event.attrs['id']
edges = None
while True:
event = yield
if isinstance(event, ElementStart) and event.name == 'route':
edges = event.attrs['edges']
elif isinstance(event, ElementEnd) and event.name == 'vehicle':
tuples.append((vid, edges))
break
これがあるとしましょうvehicles.xml
:
<root>
<foo />
<bar>
<!-- This block will be skipped. Try that with regex (please DON'T!).
<vehicle id="1292441" depart="26060.00">
<route edges="24449167#2 27659684#1 24686876#1"/>
</vehicle>
-->
<vehicle id="1292442" depart="26060.00">
<route edges="24449167#2 27659684#1 24686876#1"/>
</vehicle>
</bar>
<vehicle id="1292443" depart="26060.00">
<route edges="34449167#2 37659684#1 34686876#1"/>
</vehicle>
<vehicle id="1292444" depart="26060.00">
<route edges="44449167#2 47659684#1 44686876#1"/>
</vehicle>
</root>
今あなたがするならば:
results = []
puller = pull_tuples(results); puller.next()
with open('vehicles.xml') as f:
parse(f, LazySax(puller))
for result in results:
print result
わかるでしょ:
(u'1292442', u'24449167#2 27659684#1 24686876#1')
(u'1292443', u'34449167#2 37659684#1 34686876#1')
(u'1292444', u'44449167#2 47659684#1 44686876#1')
どちらが多かれ少なかれ欲しいものです。単純な古い XML 解析です。