tkxml.py ライブラリ技術ドキュメント
ライブラリの機能や目的
tkxml.py は、XMLデータとPythonの辞書構造間の変換、およびXMLファイルからの特定の情報抽出を容易にするためのユーティリティライブラリです。主に、科学技術計算に関連する複雑なXMLファイル(例: ATLAS最適化XML、VASPのvasprun.xml)の解析を目的としており、以下の課題を解決します。
XMLとPython辞書の相互変換: 複雑なXML構造をPythonの辞書に変換することで、プログラミングによるデータ操作を簡素化します。また、辞書からXMLを生成することも可能です。
特定のXMLセクションの抽出: XPathライクなタグパス指定により、XMLツリー内の特定のセクション(要素のグループや属性)を効率的に抽出し、構造化されたPythonデータとして取得します。
XMLの読み書きと整形: XMLファイルを読み込み、Pythonの
xml.etree.ElementTreeオブジェクトとして扱ったり、整形してファイルに書き出したりする機能を提供します。
このライブラリは、XMLデータをよりプログラマティックに扱いやすくし、特に特定のフォーマットを持つXMLファイルからのデータ抽出や加工のプロセスを自動化するのに役立ちます。
importする方法
tkxml.py ライブラリを他のPythonプログラムから利用するには、通常のモジュールと同様に import ステートメントを使用します。
import tkxml
# tkxml.py 内の関数や変数にアクセス
root_element = tkxml.get_root("path/to/your/file.xml")
特定の関数のみをインポートすることも可能です。
from tkxml import file2dict, dict2xml
data_dict = file2dict("path/to/your/file.xml")
xml_element = dict2xml(data_dict)
必要な非標準ライブラリとインストール方法
tkxml.py は、XMLと辞書の変換に特化した外部ライブラリに依存しています。これらは pip コマンドでインストールできます。
xmltodict: XMLドキュメントをPython辞書に変換するために使用されます。dicttoxml: Python辞書をXMLドキュメントに変換するために使用されます。numpy: 数値計算ライブラリとしてインポートされていますが、このソースコード内では直接的な利用箇所が見られません。一部の環境での依存関係や、将来的な利用を想定している可能性があります。
これらのライブラリは、以下のコマンドでインストールできます。
pip install xmltodict dicttoxml numpy
importできる変数と関数
グローバル変数
infile(str):デフォルトの入力XMLファイルパス。スクリプトが直接実行された際に、コマンドライン引数がない場合にこの値が使用されます。初期値は
'opt_2onl.xml'です。
関数
get_elements_recursive(element)
XML要素の子要素を再帰的に走査し、その情報を抽出します。
動作: 入力された
elementに子要素がない場合はそのテキスト内容を返します。子要素がある場合は、各子要素のタグ、テキスト、属性、およびその子要素の再帰的な情報を辞書のリストとして返します。引数:
element(xml.etree.ElementTree.Element): 処理対象のXML要素インスタンス。
戻り値:
str: 要素が子要素を持たない場合、そのテキスト内容。list[dict]: 要素が子要素を持つ場合、子要素の情報を格納した辞書のリスト。各辞書は"tag","text","attrib"、および子要素を持つ場合は"child"キーを含みます。
get_unique_key(d, section, val = None)
指定されたsectionとvalに基づいて、辞書d内でユニークなキーを生成します。
動作:
sectionとvalからキーを生成し、そのキーが辞書dに既に存在しない場合はそのキーを返します。存在する場合は、section[i]またはsection[i]:valの形式でインデックスiを付加し、ユニークなキーが見つかるまでiをインクリメントします。引数:
d(dict): キーの重複を確認する対象の辞書。section(str): キーのベースとなるセクション名。val(str,None): オプションのキーの値を指定する。デフォルトはNone。
戻り値:
str: 辞書d内でユニークなキー。
get_section_inf(parent, sections = None, inf = None, params = None, ret_type = 'list', add_parent_params = True)
XMLツリー内の特定のセクション(タグパスで指定)の情報を取得します。
動作:
parent要素からsectionsで指定されたタグパスを辿り、最後のセクションの子要素の情報を抽出します。抽出された情報はret_typeに基づいてリストまたは辞書として整形されます。add_parent_paramsがTrueの場合、親要素の属性情報も追加されます。引数:
parent(xml.etree.ElementTree.Element): 検索を開始する親XML要素。sections(list[str],None): 検索するタグ名のリスト。例:['parameter-list', 'parameter']。デフォルトはNone。inf(listordict,None): 既存の情報に追加する場合に指定。デフォルトはNone。params(dict,None): 既存のパラメータ情報に追加する場合に指定。デフォルトはNone。ret_type(str): 戻り値の型を指定 ('list'または'dict')。デフォルトは'list'。add_parent_params(bool): 親要素の属性情報を結果に追加するかどうか。デフォルトはTrue。
戻り値:
listordict: 抽出された情報。ret_typeが'list'の場合は辞書のリスト、'dict'の場合はキーが最後のセクションの属性値(または'list')となる辞書。
get_section_inf_all(parent, sections = None, section_parent = 'root', inf = None, level = 0, params = None, pkey = None, ret_type = 'list', last_node_only = True)
XMLツリー内の特定のセクションパスを再帰的に走査し、一致する全ての要素の情報を取得します。get_section_infよりも汎用的な情報抽出を目的としています。
動作:
parent要素からsectionsのタグパスを再帰的に辿り、パス内の各レベルで一致する要素の情報を抽出します。last_node_onlyがTrueの場合、パスの最後のノードのみを結果に含めます。levelとparamsは再帰の階層と親の属性を保持します。引数:
parent(xml.etree.ElementTree.Element): 検索を開始する親XML要素。sections(list[str],None): 検索するタグ名のリスト。例:['parameter-list', 'parameter']。デフォルトはNone。section_parent(str): 現在のparentのタグ名。内部的な再帰処理で使用。デフォルトは'root'。inf(listordict,None): 既存の情報に追加する場合に指定。デフォルトはNone。level(int): 現在の処理レベル(深さ)。内部的な再帰処理で使用。デフォルトは0。params(dict,None): 現在の要素に継承される親要素の属性の辞書。デフォルトはNone。pkey(str,None):ret_typeが'dict'の場合にキーとして使用する属性名。デフォルトはNone。ret_type(str): 戻り値の型を指定 ('list'または'dict')。デフォルトは'list'。last_node_only(bool):Trueの場合、sectionsパスの最後の要素のみを結果に含める。Falseの場合、パス上の全ての要素を含める。デフォルトはTrue。
戻り値:
listordict: 抽出された情報。各要素は"level","tag","text","attrib","params"キーを持つ辞書です。
xml2dict(xml)
XMLインスタンスまたはXML文字列をPython辞書に変換します。
動作: 内部で
xmltodict.parse()を使用し、入力されたXMLデータをPython辞書構造に変換します。引数:
xml(strorxml.etree.ElementTree.Element): XML文字列、またはxml.etree.ElementTree.Elementインスタンス。
戻り値:
dict: 変換されたPython辞書。
_element_to_dict(element)
xml.etree.ElementTree.Elementオブジェクトを再帰的に辞書に変換する内部ヘルパー関数です。
動作: 要素の属性は
'@attributes'キーの下に、テキスト内容は'#text'キーの下に格納されます。同じタグ名の子要素が複数ある場合はリストとして扱われます。この関数は、xml2dictがxmltodictを使用する代替として、または標準ライブラリのみでXML-Dict変換を行うための内部実装として存在します。引数:
element(xml.etree.ElementTree.Element): 変換するXML要素。
戻り値:
dict: 変換されたPython辞書。
file2dict(infile)
指定されたファイルパスのXMLファイルを読み込み、その内容をPython辞書に変換します。
動作: ファイルを読み込み、その内容を
xml2dict関数に渡して辞書に変換します。引数:
infile(str): 入力XMLファイルのパス。
戻り値:
dict: 変換されたPython辞書。
dict2xml(d, attr_type = True, root = True)
Python辞書をXMLインスタンスに変換します。
動作: 内部で
dicttoxml.dicttoxml()を使用し、入力されたPython辞書をXMLインスタンスに変換します。引数:
d(dict): 変換するPython辞書。attr_type(bool): 属性の型を考慮するかどうか。dicttoxmlの引数に準拠。デフォルトはTrue。root(bool): ルート要素を生成するかどうか。dicttoxmlの引数に準拠。デフォルトはTrue。
戻り値:
bytes: 変換されたXMLインスタンス(バイト列)。
to_xml(outfile, element, encoding = 'utf-8', newl = '', indent = '', addindent = ' ', xml_declaration = True, use_minidom = False)
XML要素をファイルに書き出します。必要に応じてxml.dom.minidomを使用してXMLを整形できます。
動作:
elementをoutfileに書き込みます。use_minidomがTrueの場合、xml.dom.minidomを使用してXMLを整形(インデントや改行を追加)してから書き込みます。xml_declarationフラグでXML宣言の有無を制御します。引数:
outfile(str): 書き込み先のファイルパス。element(xml.etree.ElementTree.Element): 書き込むルートXML要素。encoding(str): 出力ファイルのエンコーディング。デフォルトは'utf-8'。newl(str):use_minidom=Trueの場合の改行文字。デフォルトは''。indent(str):use_minidom=Trueの場合の最初のインデント文字。デフォルトは''。addindent(str):use_minidom=Trueの場合の各レベルの追加インデント文字。デフォルトは' '。xml_declaration(bool): XML宣言をファイルに含めるかどうか。デフォルトはTrue。use_minidom(bool):xml.dom.minidomを使ってXMLを整形するかどうか。デフォルトはFalse。
戻り値:
None
get_attrib(element)
XML要素のタグ名、テキスト内容、および属性を抽出します。
動作: 入力されたXML要素の
tag、text、attribプロパティを返します。引数:
element(xml.etree.ElementTree.Element): 情報を取得するXML要素インスタンス。
戻り値:
tuple[str, str, dict]: 要素のタグ名、テキスト内容、属性の辞書を順に格納したタプル。
get_root(xml)
XMLソースからXMLのルート要素を取得します。
動作:
xml引数がファイルパスである場合はファイルを解析し、文字列である場合は文字列を解析して、XMLツリーのルート要素を返します。引数:
xml(str): XMLファイルパスまたはXMLデータを含む文字列。
戻り値:
xml.etree.ElementTree.Element: XMLツリーのルート要素。
main scriptとして実行したときの動作
tkxml.py がPythonスクリプトとして直接実行された場合(python tkxml.py)、main() 関数が呼び出されます。この main() 関数は以下の動作を実行します。
入力ファイルの決定:
コマンドライン引数が指定されている場合(例:
python tkxml.py your_file.xml)、最初の引数 (sys.argv[1]) を入力ファイルパス (infile) として使用します。コマンドライン引数がない場合、グローバル変数
infileのデフォルト値('opt_2onl.xml')を使用します。
XMLファイルのロード:
決定された入力ファイルパスから
get_root()関数を使用してXMLのルート要素を読み込みます。
XMLタイプの判別と情報抽出:
読み込んだXMLルート要素に対して、特定のXPath (
.//parameter-listまたは.//incar) を使ってXMLの種類を判別します。ATLAS最適化XMLと判断された場合 (
.//parameter-listが見つかる場合):parameter-list、settings、target-listセクションから、それぞれparameter、setting、target要素の情報をget_section_inf_all()関数を使って辞書形式で抽出します。抽出された
parameter_inf、setting_inf、target_infの内容を標準出力に表示します。
VASPの
vasprun.xmlと判断された場合 (.//incarが見つかる場合):projected_kpoints_opt、eigenvalues、set[@comment]、rなど、バンド情報に関連するセクションからデータをget_section_inf_all()関数を使って抽出します。incarセクションから、その子要素の情報をget_section_inf_all()関数を使って辞書形式で抽出します(pkey='name'でキーを生成)。抽出された
band_infやincar_infの内容を標準出力に表示します。
上記以外のXMLタイプの場合:
"Error: Invalid XML type" というメッセージを標準出力に表示し、プログラムを終了します。
この main() 関数は、ライブラリの様々な情報抽出機能のデモンストレーションとして機能し、特定のXMLフォーマットからのデータ解析の具体的な例を示しています。