Expatを使ってpythonでxmlを解析する話
結論
from textwrap import dedent
from xml.parsers import expat
class xml_parser:
def __init__(self, xml):
self.xml = xml
self.p = expat.ParserCreate()
# parse setting
self.p.StartElementHandler = self.start_element # start tag
self.p.EndElementHandler = self.end_element # end tag
self.p.CharacterDataHandler = self.char_data # tag value
def start_element(self, name, attrs):
print('Start element:', name, attrs)
def end_element(self, name):
print('End element:', name)
def char_data(self, data):
print('Character data:', repr(data))
def parse(self):
self.p.Parse(self.xml, 1) # parse xml
def parse_file(self, filename):
self.p.ParseFile(filename) # only byte code
背景
XMLファイルをpythonから解析するときに、Expatを使うと早いと聞いたため、exampleをやってみた話です。使いまわしが少しでもできるように、クラスで実装をしました。
実行してみた
- 実行環境
- windows 10 64-bit
- python 3.7.3
- 事前ダウンロード&インストール
- 標準搭載のため不要
# main program
def main():
src = dedent("""<?xml version="1.0"?>
<parent id="top">
<child1 name="paul">Text goes here</child1>
<child2 name="fred">More text</child2>
</parent>""").strip()
ins = xml_parser(src)
ins.parse()
if __name__ == "__main__":
main()
# output
<?xml version="1.0"?>
<parent id="top"><child1 name="paul">Text goes here</child1>
<child2 name="fred">More text</child2>
</parent>
Start element: parent {'id': 'top'}
Start element: child1 {'name': 'paul'}
Character data: 'Text goes here'
End element: child1
Character data: '\n'
Start element: child2 {'name': 'fred'}
Character data: 'More text'
End element: child2
Character data: '\n'
End element: parent
Expat関数
start_element関数、char_element関数、end_element関数とその引数の名称は、どうやらハンドラとして認識させるために固定のようです.
start_element関数
tagを発見したときに行う処理です。各引数については以下の表通りになります。
引数 | データ型 | 例 |
---|---|---|
name | str | 'parent' |
attrs | dict | {'id': 'top'} |
char_element関数
tagの値を取得するときに行う処理です。
end_element関数
終わりのtagを発見したときに行う処理です。