Python XML 解析


XMLとは?

XMLは拡張可能なマークアップ言語(eXtensible Markup Language)を指します。XMLチュートリアル

XMLはデータの転送と保存のために設計されています。

XMLはセマンティックマークを定義する一連のルールです。これらのマークはドキュメントを多くの部分に分割し、それらの部分を識別します。

また、メタマークアップ言語でもあります。つまり、特定の分野に関連する、意味的で構造的なマークアップ言語を定義するための構文言語を定義します。


PythonによるXMLの解析

一般的なXMLプログラミングインターフェースにはDOMとSAXがあります。これら2つのインターフェースはXMLファイルの処理方法が異なり、もちろん使用場面も異なります。

PythonにはXMLを解析する3つの方法があります。SAX、DOM、およびElementTreeです:

1.SAX (simple API for XML )

Python標準ライブラリにはSAXパーサーが含まれています。SAXはイベント駆動モデルを使用し、XML解析中にイベントを1つずつトリガーし、ユーザー定義のコールバック関数を呼び出してXMLファイルを処理します。

2.DOM(Document Object Model)

XMLデータをメモリ内でツリーに解析し、ツリーの操作を通じてXMLを操作します。

3.ElementTree(要素ツリー)

ElementTreeは軽量なDOMのようなもので、便利で使いやすいAPIを備えています。コードの再利用性が良く、高速で、メモリ消費も少ないです。

注:DOMはXMLデータをメモリ内のツリーにマッピングする必要があるため、遅く、メモリを多く消費します。一方、SAXはXMLファイルをストリーミング方式で読み取るため、比較的速く、メモリ使用量も少ないですが、ユーザーがコールバック関数(handler)を実装する必要があります。

この章で使用するXMLサンプルファイル movies.xml の内容は次のとおりです:

movies.xml

<collection shelf="New Arrivals"> <movie title="Enemy Behind"> <type>War, Thriller</type> <format>DVD</format> <year>2003</year> <rating>PG</rating> <stars>10</stars> <description>Talk about a US-Japan war</description> </movie> <movie title="Transformers"> <type>Anime, Science Fiction</type> <format>DVD</format> <year>1989</year> <rating>R</rating> <stars>8</stars> <description>A schientific fiction</description> </movie> <movie title="Trigun"> <type>Anime, Action</type> <format>DVD</format> <episodes>4</episodes> <rating>PG</rating> <stars>10</stars> <description>Vash the Stampede!</description> </movie> <movie title="Ishtar"> <type>Comedy</type> <format>VHS</format> <rating>PG</rating> <stars>2</stars> <description>Viewable boredom</description> </movie> </collection>

pythonでSAXを使用してXMLを解析する

SAXはイベント駆動型のAPIです。

SAXを使用してXMLドキュメントを解析するには、2つの部分が関係します:パーサーとイベントハンドラー。

パーサーはXMLドキュメントを読み取り、要素の開始や終了などのイベントをイベントハンドラーに送信します。

イベントハンドラーはイベントに応答し、渡されたXMLデータを処理します。

  • 1、大きなファイルを処理する;
  • 2、ファイルの一部の内容だけが必要、またはファイルから特定の情報だけを取得する必要がある場合。
  • 3、独自のオブジェクトモデルを構築したい場合。

pythonでsax方式を使用してXMLを処理するには、まずxml.saxのparse関数と、xml.sax.handlerのContentHandlerをインポートする必要があります。

ContentHandlerクラスのメソッド紹介

characters(content)メソッド

呼び出しタイミング:

行の先頭からタグに遭遇する前に文字が存在する場合、contentの値はそれらの文字列になります。

あるタグから次のタグに遭遇する前に文字が存在する場合、contentの値はそれらの文字列になります。

あるタグから行終了記号に遭遇する前に文字が存在する場合、contentの値はそれらの文字列になります。

タグは開始タグの場合もあれば、終了タグの場合もあります。

startDocument() メソッド

ドキュメントの解析開始時に呼び出されます。

endDocument() メソッド

パーサーがドキュメントの末尾に到達したときに呼び出されます。

startElement(name, attrs)メソッド

XML開始タグに遭遇したときに呼び出されます。nameはタグの名前で、attrsはタグの属性値の辞書です。

endElement(name) メソッド

XML終了タグに遭遇したときに呼び出されます。


make_parserメソッド

次のメソッドは新しいパーサーオブジェクトを作成して返します。

xml.sax.make_parser( [parser_list] )

パラメータの説明:

  • parser_list- オプションのパラメータ、パーサーのリスト

parserメソッド

次のメソッドはSAXパーサーを作成し、XMLドキュメントを解析します:

xml.sax.parse( xmlfile, contenthandler[, errorhandler])

パラメータの説明:

  • xmlfile- XMLファイル名
  • contenthandler- ContentHandlerオブジェクトである必要があります
  • errorhandler- このパラメータを指定する場合、errorhandlerはSAX ErrorHandlerオブジェクトである必要があります

parseStringメソッド

parseStringメソッドはXMLパーサーを作成し、XML文字列を解析します:

xml.sax.parseString(xmlstring, contenthandler[, errorhandler])

パラメータの説明:

  • xmlstring- XML文字列
  • contenthandler- ContentHandlerオブジェクトである必要があります
  • errorhandler- このパラメータを指定する場合、errorhandlerはSAX ErrorHandlerオブジェクトである必要があります

PythonによるXML解析の例

例

#!/usr/bin/python # -*- coding: UTF-8 -*- import xml.sax class MovieHandler( xml.sax.ContentHandler ): def __init__(self): self.CurrentData = "" self.type = "" self.format = "" self.year = "" self.rating = "" self.stars = "" self.description = "" # 要素開始イベント処理 def startElement(self, tag, attributes): self.CurrentData = tag if tag == "movie": print "*****Movie*****" title = attributes["title"] print "Title:", title # 要素終了イベント処理 def endElement(self, tag): if self.CurrentData == "type": print "Type:", self.type elif self.CurrentData == "format": print "Format:", self.format elif self.CurrentData == "year": print "Year:", self.year elif self.CurrentData == "rating": print "Rating:", self.rating elif self.CurrentData == "stars": print "Stars:", self.stars elif self.CurrentData == "description": print "Description:", self.description self.CurrentData = "" # コンテンツイベント処理 def characters(self, content): if self.CurrentData == "type": self.type = content elif self.CurrentData == "format": self.format = content elif self.CurrentData == "year": self.year = content elif self.CurrentData == "rating": self.rating = content elif self.CurrentData == "stars": self.stars = content elif self.CurrentData == "description": self.description = content if ( __name__ == "__main__"): # XMLReaderを作成 parser = xml.sax.make_parser() # turn off namepsaces parser.setFeature(xml.sax.handler.feature_namespaces, 0) # ContextHandlerをオーバーライド Handler = MovieHandler() parser.setContentHandler( Handler ) parser.parse("movies.xml")

上記のコードの実行結果は次のとおりです:

*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Year: 2003
Rating: PG
Stars: 10
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Year: 1989
Rating: R
Stars: 8
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Stars: 10
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Stars: 2
Description: Viewable boredom

完全なSAX APIドキュメントは次を参照してくださいPython SAX APIs


xml.domを使用したXML解析

ドキュメントオブジェクトモデル(Document Object Model、略称DOM)は、W3Cが推奨する拡張可能なマークアップ言語を処理するための標準プログラミングインターフェースです。

DOMパーサーはXMLドキュメントを解析する際、ドキュメント全体を一度に読み取り、ドキュメント内のすべての要素をメモリ内のツリー構造に保存します。その後、DOMが提供するさまざまな関数を使用して、ドキュメントの内容や構造を読み取ったり変更したり、変更した内容をXMLファイルに書き込むこともできます。

pythonではxml.dom.minidomを使用してXMLファイルを解析します。例は次のとおりです:

例

#!/usr/bin/python # -*- coding: UTF-8 -*- from xml.dom.minidom import parse import xml.dom.minidom # minidomパーサーを使用してXMLドキュメントを開く DOMTree = xml.dom.minidom.parse("movies.xml") collection = DOMTree.documentElement if collection.hasAttribute("shelf"): print "Root element : %s" % collection.getAttribute("shelf") # コレクション内のすべての映画を取得 movies = collection.getElementsByTagName("movie") # 各映画の詳細情報を出力 for movie in movies: print "*****Movie*****" if movie.hasAttribute("title"): print "Title: %s" % movie.getAttribute("title") type = movie.getElementsByTagName('type')[0] print "Type: %s" % type.childNodes[0].data format = movie.getElementsByTagName('format')[0] print "Format: %s" % format.childNodes[0].data rating = movie.getElementsByTagName('rating')[0] print "Rating: %s" % rating.childNodes[0].data description = movie.getElementsByTagName('description')[0] print "Description: %s" % description.childNodes[0].data

上記のプログラムの実行結果は次のとおりです:

Root element : New Arrivals
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Rating: PG
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Rating: R
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Description: Viewable boredom

完全なDOM APIドキュメントは次を参照してくださいPython DOM APIs。

その他の拡張