どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

ElementTreeを使ってみる。

pythonに標準で入ってるXMLを扱えるモジュールElementTreeを使ってみました。

この記事ではElementTreeを使ってXMLではなくAIMLをパースしてプログラム内で利用しやすい形に変換してみます。

 

関連リンク

20.5. xml.etree.ElementTree — ElementTree XML API — Python 3.6.5 ドキュメント

AIML Tutorial

AIML

AIMLとはArtificial Intelligence Markup Languageの略でXMLベースのマークアップ言語です。Artificial Linguistic Internet Computer Entity (A.L.I.C.E.) と呼ばれるチャットボットの開発の際に作られました。(※AIMLについての詳細な説明は今回は省略します。)

AIMLの中身は以下のような感じです。このようなAIML形式のファイルをElementTreeを使って解析したいと思います。

<aiml>
  <category>
    <pattern>こんにちは</pattern>
    <template>こんにちはー</template>
  </category>
  <category>
    <pattern>おはよう</pattern>
    <template>おっはー</template>
  </category>
</aiml>

ElementTreeを使ってデータを読み込む

上にあるファイルを解析するファイルとして使います。ファイルの名前をsample.aimlとします。

モジュールのインポート

まずは必要なモジュールをインポートします。

import xml.etree.ElementTree as ET

ファイルを読み込む

parse()からAIMLファイルを読み込みます。

fname = "sample.aiml" # 読み込みたいAIMLファイル
document = ET.parse(fname) # xml.etree.ElementTree.ElementTree
categories = document.findall("./category")
# [<Element 'category' at 0x00>, <Element 'category' at 0x00>]

続いてfindall()を使って<category></category>で囲まれた部分を取得します。

categoryの中身を見る。

先ほど取得したcategoriesはリストになっていて、その中身は<category></category>で囲まれている要素が入っています。

以下のコードではcategoryの要素であるpatternとtemplateのテキストを取り出しています。

for category in categories:
    pattern = category.find('pattern').text
    template = category.find('template').text
    print(pattern)
    print(template)
    print()

find()を使ってcategoryの中から指定したタグを見つけたらそれをテキスト形式にしています。

こんにちは
こんにちはー

おはよう
おっはー

AIMLファイルを作る

ElementTreeを使ってAIML形式のファイルを作ってみます。

AIMLファイルを作る

fromstring()を使って文字列からElementを生成します。このとき作られたElementはパースされた木のルート要素になります。つまり、parse()を使ってAIMLファイルを読み込んだときと同じ状態になっています。

import xml.etree.ElementTree as ET
aiml = ET.fromstring("<aiml>\n</aiml>")

aimlに新しい要素を追加してみます。追加する要素はElementクラスのオブジェクトでなければなりません。文字列を直接追加しようとするとエラーがでます。

今回は例としてsample.aimlのpattern要素の文字列の長さが5以上のものをaimlに加えてみます。

fname = "sample.aiml"
document = ET.parse(fname)
for category in document.findall("./category"):
    pattern = category.find("pattern").text
    if len(pattern) >= 5:
        # categoryはElementクラスのオブジェクト
        # <class 'xml.etree.ElementTree.Element'>
        aiml.append(category)

aimlをファイルとして保存するには、新しくElementTreeを生成した上でwrite()で中身をファイルに書き込みます。

aiml_file = ET.ElementTree(aiml)
aiml_file.write('new_sample.aiml', encoding='utf-8')

生成されたファイル

<aiml>
<category>
    <pattern>こんにちは</pattern>
    <template>こんにちはー</template>
  </category>
  </aiml>

ソースコード

データを読み込む

import xml.etree.ElementTree as ET

fname = "sample.aiml" # 読み込みたいAIMLファイル
document = ET.parse(fname) # xml.etree.ElementTree.ElementTree
categories = document.findall("./category")
# [<Element 'category' at 0x00>, <Element 'category' at 0x00>]
for category in categories:
    pattern = category.find('pattern').text
    template = category.find('template').text
    print(pattern)
    print(template)
    print()

データを書き込む

import xml.etree.ElementTree as ET

aiml = ET.fromstring("<aiml>\n</aiml>")

fname = "sample.aiml"
document = ET.parse(fname)
for category in document.findall("./category"):
    pattern = category.find("pattern").text
    if len(pattern) >= 5:
        # categoryはElementクラスのオブジェクト
        # <class 'xml.etree.ElementTree.Element'>
        aiml.append(category)

aiml_file = ET.ElementTree(aiml)
aiml_file.write('new_sample.aiml', encoding='utf-8')