覚書: xml.saxとelementtree.SimpleXMLWriterを使ったXMLフィルター

読み込んだXMLと同等のものを出力するフィルター。SAXなんで巨大なXMLファイルでも処理できる。


import sys
import xml.sax.handler
from elementtree.SimpleXMLWriter import XMLWriter
import codecs

class Parser(xml.sax.handler.ContentHandler):
""" 読み込んだXMLと同等のもを掃き出す何もしないフィルター """

def __init__(self, outfh=sys.stdout):

self.w=XMLWriter(outfh, encoding='utf8')

# ウインドーズで読み込むにはボムじいさんをつけておくといいらしい。
outfh.write(codecs.BOM_UTF8)

# elementtree.SimpleXMLWriter.declaration()はエンコーディング
#「utf8」とするんだけど、これだとxml.saxが嫌がる。誰が正しいのかわからないが
#「utf-8」にするためにxml宣言をハードコードしておく。
#self.w.declaration()
sys.stdout.write('')

def startElement(self, name, attrs):

self.w.start(name, **attrs)

def endElement(self, name):

self.w.end()

def characters(self, content):

self.w.data(content)

def done(self):

pass

if __name__=='__main__':

import baker

@baker.command
def filter(xml_file):
parser=Parser()
xml.sax.parse(file(xml_file), parser)

baker.run()

XMLってそもそも木構造のドキュメントを表記するためのものでしょ。データstreamの処理には向かないと思う。そういうときにはsaxでもっと扱いやすい表記法に変換する。 処理したデータをXMLにして返さなきゃいけないときはelementtree.SimpleXMLWriterが便利。