Viewer.XMLView のソースコード

"""
XMLファイルを読み込み、TkinterのGUIツリービューで表示するスクリプト。

概要:
    このスクリプトは、指定されたXMLファイルの内容を読み込み、
    それをグラフィカルユーザーインターフェース(GUI)のツリービュー形式で表示します。
    ユーザーはXMLファイルの構造を視覚的に探索できます。

詳細説明:
    - コマンドライン引数またはTOML形式のINIファイルから、XMLファイルのパスとウィンドウサイズを読み込みます。
    - `xml.etree.ElementTree` モジュールを使用してXMLファイルを解析し、その構造を再帰的に走査します。
    - Tkinterとttk(themed Tkinter)を使用して、解析されたXML要素を階層的なTreeviewウィジェットに表示します。
    - ウィンドウを閉じる際に、現在のウィンドウのジオメトリをINIファイルに保存する機能を提供し、
      次回の起動時に前回の設定を復元できるようにします。

使用方法:
    python xml_viewer.py [XMLファイルパス] [ウィンドウサイズ (例: 800x600)]

関連リンク:
    :doc:`XMLView_usage`
"""
import os
import sys
import toml
import xml.etree.ElementTree as ET
import tkinter as tk
from tkinter import ttk


if len(sys.argv) <= 1:
    print("Usage: python xml_viewer.py infile window_size")
    sys.exit(1)

infile = '../XML/vasprun.xml'
geometry = '800x600'

inifile = os.path.splitext(sys.argv[0])[0] + ".ini"
if os.path.isfile(inifile): 
    geometry = toml.load(inifile).get("geometry", geometry)

nargs = len(sys.argv)
if nargs >= 2:
    infile = sys.argv[1]
if nargs >= 3:
    geometry = sys.argv[2]


[ドキュメント] class XMLViewer: """ XMLデータをTkinterのTreeviewウィジェットに表示するためのビューアクラス。 概要: XMLファイルを読み込み、その内容をTkinterのTreeviewウィジェットに階層的に表示します。 詳細説明: このクラスは、Tkinterのルートウィンドウを受け取り、XMLファイルのパスと初期ウィンドウサイズに基づいて、 Treeviewウィジェットを作成し、XML構造を解析して表示します。 XML要素はタグ、テキスト、属性に基づいてTreeviewノードとして追加されます。 """ def __init__(self, root: tk.Tk, infile: str, geometry: str = '800x600', tree_open: bool = True): """ XMLViewerクラスのコンストラクタ。GUIの初期設定とXMLファイルの読み込みを行います。 概要: Tkinterのルートウィンドウを設定し、Treeviewウィジェットを作成。 指定されたXMLファイルを読み込み、その内容をTreeviewに表示します。 :param root: tk.Tk - Tkinterのルートウィンドウオブジェクト。 :param infile: str - 読み込むXMLファイルのパス。 :param geometry: str - ウィンドウの初期サイズと位置を指定する文字列(例: '800x600')。デフォルトは '800x600'。 :param tree_open: bool - Treeviewの初期状態でノードを開くかどうか。Trueの場合、特定のレベルまで開く。 """ self.tree_open = tree_open self.root = root self.root.title(f"XML Viewer - {infile}") self.root.geometry(geometry) self.treeview = ttk.Treeview(self.root) self.treeview.heading('#0', text = infile) self.treeview.pack(fill = 'both', expand = True) self.read_xml(infile)
[ドキュメント] def read_xml(self, infile: str): """ 指定されたXMLファイルを解析し、Treeviewに表示するための準備を行う。 概要: `xml.etree.ElementTree` を使用してXMLファイルを解析し、ルート要素を取得。 その後、`display_element` メソッドを呼び出してTreeviewに内容を再帰的に表示します。 詳細説明: ファイルが存在しない場合やXML解析エラーが発生した場合は、 エラーメッセージをコンソールとTreeviewに表示し、アプリケーションを終了します。 正常に解析された場合、XMLのルート要素から表示を開始します。 :param infile: str - 読み込むXMLファイルのパス。 :returns: None """ if not os.path.isfile(infile): print(f"\nError: Can not find [{infile}]") input("Press ENTER to terminate>>\n") exit() try: self.etree = ET.parse(infile) self.root_element = self.etree.getroot() self.display_element(self.root_element, '') except ET.ParseError as e: self.treeview.insert("", "end", text="Error", values = (str(e)))
[ドキュメント] def display_element(self, element: ET.Element, item_id: str = '', level: int = 0): """ XML要素を再帰的にTkinterのTreeviewウィジェットに表示する。 概要: 指定されたXML要素のタグ、テキスト、属性をTreeviewのノードとして追加し、 子要素があればそれらも再帰的に表示します。 詳細説明: ノードの表示テキストは、`name` 属性が存在すればそれを優先し、次に要素のテキスト、 最後にタグ名を使用します。 レベル1までのノードは初期状態で開き、それ以降のレベルは閉じられた状態で挿入されます。 各要素に対して、そのタグ、テキスト、属性が詳細として子ノードに追加されます。 属性はさらに個別のキーと値のペアとして表示されます。 :param element: ET.Element - 表示するXML要素。 :param item_id: str - 親となるTreeviewアイテムのID。ルート要素の場合は空文字列。 :param level: int - 現在の要素の深さ(ネストレベル)。 :returns: None """ if level <= 1: tree_open = self.tree_open else: tree_open = False text = None if element.attrib.get('name', None) is not None: text = element.attrib["name"] if element.text is not None: if text is None: text = element.text.strip() else: text += f":{element.text.strip()}" if text is None or text == '': text = element.tag.strip() if text is None or text == '': text = 'root' child_item = self.treeview.insert(item_id, "end", text = text, open = tree_open) self.treeview.insert(child_item, "end", text = f"tag: {element.tag.strip()}", open = tree_open) if element.text is not None: self.treeview.insert(child_item, "end", text = f"text: {element.text.strip()}") self.treeview.insert(child_item, "end", text = f"attrib: {element.attrib}", open = tree_open) for key, value in element.attrib.items(): self.treeview.insert(child_item, "end", text = f"{key}: {value}", open = tree_open) for child in element.findall('*'): self.display_element(child, child_item, level = level + 1)
[ドキュメント] def window_close(root: tk.Tk): """ ウィンドウが閉じられたときに呼び出され、現在のウィンドウのジオメトリをINIファイルに保存する。 概要: Tkinterウィンドウが閉じられる際に実行され、現在のウィンドウのサイズと位置をTOML形式のINIファイルに保存します。 詳細説明: この関数は、`WM_DELETE_WINDOW` プロトコルハンドラとして設定されます。 ウィンドウの現在のジオメトリ情報を取得し、`inifile` で指定されたパスにあるINIファイルに `geometry` キーとして書き込みます。その後、アプリケーションを終了します。 :param root: tk.Tk - Tkinterのルートウィンドウオブジェクト。 :returns: None """ with open(inifile, "w") as file: toml.dump({"geometry": root.geometry()}, file) root.quit()
[ドキュメント] def main(): """ アプリケーションのエントリポイント。TkinterウィンドウとXMLViewerインスタンスを作成し、GUIイベントループを開始する。 概要: XMLビューアアプリケーションを初期化し、実行します。 詳細説明: Tkinterのルートウィンドウを初期化し、コマンドライン引数やINIファイルから取得した設定(XMLファイルパス、ウィンドウサイズ)に基づいて `XMLViewer` インスタンスを作成します。 ウィンドウが閉じられる際のプロトコルハンドラとして `window_close` 関数を設定し、 GUIイベントループを開始してアプリケーションをユーザー操作可能にします。 :returns: None """ root = tk.Tk() app = XMLViewer(root, infile, geometry, tree_open = True) root.protocol("WM_DELETE_WINDOW", lambda: window_close(root)) root.mainloop()
if __name__ == "__main__": main()