20.5. "xml.etree.ElementTree" --- ElementTree XML API
*****************************************************

**Source code:** Lib/xml/etree/ElementTree.py

======================================================================

"xml.etree.ElementTree" モジュールは、XML データを解析および作成するシ
ンプルかつ効率的な API を実装しています。

バージョン 3.3 で変更: このモジュールは利用出来る場合は常に高速な実装
を使用します。"xml.etree.cElementTree" は非推奨です。

警告: "xml.etree.ElementTree" モジュールは悪意を持って作成されたデー
  タに対 して安全ではありません。信頼できないデータや認証されていない
  データを をパースする必要がある場合は XML の脆弱性 を参照してくださ
  い。


20.5.1. チュートリアル
======================

これは "xml.etree.ElementTree" (略して "ET") を使用するための短いチュ
ートリアルで、ブロックの構築およびモジュールの基本コンセプトを紹介する
ことを目的としています。


20.5.1.1. XML 木構造と要素
--------------------------

XML は本質的に階層データ形式で、木構造で表すのが最も自然な方法です。
"ET" はこの目的のために 2 つのクラス - XML 文書全体を木で表す
"ElementTree" および木構造内の単一ノードを表す "Element" - を持ってい
ます。文書全体とのやりとり (ファイルの読み書き) は通常 "ElementTree"
レベルで行います。単一 XML 要素およびその子要素とのやりとりは
"Element" レベルで行います。


20.5.1.2. XML の解析
--------------------

このセクションでは例として以下の XML 文書を使います:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank>1</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank>4</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
       <country name="Panama">
           <rank>68</rank>
           <year>2011</year>
           <gdppc>13600</gdppc>
           <neighbor name="Costa Rica" direction="W"/>
           <neighbor name="Colombia" direction="E"/>
       </country>
   </data>

ファイルを読み込むことでこのデータをインポートすることが出来ます:

   import xml.etree.ElementTree as ET
   tree = ET.parse('country_data.xml')
   root = tree.getroot()

文字列から直接インポートすることも出来ます:

   root = ET.fromstring(country_data_as_string)

"fromstring()" は XML を文字列から "Element" に直接パースします。
"Element" はパースされた木のルート要素です。他のパース関数は
"ElementTree" を作成するかもしれません。ドキュメントをきちんと確認して
ください。

"Element" として、"root" はタグと属性の辞書を持ちます:

   >>> root.tag
   'data'
   >>> root.attrib
   {}

さらにイテレート可能な子ノードも持ちます:

   >>> for child in root:
   ...     print(child.tag, child.attrib)
   ...
   country {'name': 'Liechtenstein'}
   country {'name': 'Singapore'}
   country {'name': 'Panama'}

子ノードは入れ子になっており、インデックスで子ノードを指定してアクセス
できます:

   >>> root[0][1].text
   '2008'

注釈: XML 入力の全ての要素が、パース後の木に要素として含まれる訳では
  ありま せん。現在、このモジュールは入力中のいかなる XML コメント、処
  理命令 、ドキュメントタイプ宣言も読み飛ばします。しかし、XML テキス
  トからの パースではなく、このモジュールの API を使用して構築された木
  には、コ メントや処理命令を含むことができ、それらは XML 出力の生成時
  に含まれ ます。ドキュメントタイプ宣言は、 "XMLParser" コンストラクタ
  にカスタ ムの "TreeBuilder" インスタンスを渡すことで、アクセスするこ
  とができ ます。


20.5.1.3. 非ブロックパースのためのプル API
------------------------------------------

このモジュールが提供するパース関数のほとんどは、結果を返す前に、ドキュ
メント全体を読む必要があります。 "XMLParser" を使用して、インクリメン
タルにデータを渡すことは可能ではありますが、それはコールバック対象のメ
ソッドを呼ぶプッシュ API であり、多くの場合、低水準すぎて不便です。ユ
ーザーが望むのは、完全に出来上がった "Element" オブジェクトを便利に使
いながら、操作をブロックすることなく XML のパースをインクリメンタルに
行えることです。

これを行うための最も強力なツールは、 "XMLPullParser" です。XML データ
を取得するためにブロックするような読み込みは必要なく、
"XMLPullParser.feed()" を呼び出して、インクリメンタルにデータを読みま
す。パースされた XML 要素を取得するには、"XMLPullParser.read_events()"
を呼び出します。以下に、例を示します。

   >>> parser = ET.XMLPullParser(['start', 'end'])
   >>> parser.feed('<mytag>sometext')
   >>> list(parser.read_events())
   [('start', <Element 'mytag' at 0x7fa66db2be58>)]
   >>> parser.feed(' more text</mytag>')
   >>> for event, elem in parser.read_events():
   ...     print(event)
   ...     print(elem.tag, 'text=', elem.text)
   ...
   end

これの分かりやすい用途は、XML データをソケットから受信したり、ストレー
ジデバイスからインクリメンタルに読み出したりするような、非ブロック式に
動作するアプリケーションです。このような場合、ブロッキング読み出しは使
用できません。

"XMLPullParser" は柔軟性が非常に高いため、単純に使用したいユーザーにと
っては不便かもしれません。アプリケーションにおいて、XML データの読み取
り時にブロックすることに支障がないが、インクリメンタルにパースする能力
が欲しい場合、"iterparse()" を参照してください。大きな XML ドキュメン
トを読んでいて、全てメモリ上にあるという状態にしたくない場合に有用です
。


20.5.1.4. 関心ある要素の検索
----------------------------

"Element" は、例えば、"Element.iter()" などの、配下 (その子ノードや孫
ノードなど) の部分木全体を再帰的にイテレートするいくつかの役立つメソッ
ドを持っています:

   >>> for neighbor in root.iter('neighbor'):
   ...     print(neighbor.attrib)
   ...
   {'name': 'Austria', 'direction': 'E'}
   {'name': 'Switzerland', 'direction': 'W'}
   {'name': 'Malaysia', 'direction': 'N'}
   {'name': 'Costa Rica', 'direction': 'W'}
   {'name': 'Colombia', 'direction': 'E'}

"Element.findall()" はタグで現在の要素の直接の子要素のみ検索します。
"Element.find()" は特定のタグで *最初の* 子要素を検索し、
"Element.text" は要素のテキストコンテンツにアクセスします。
"Element.get()" は要素の属性にアクセスします:

   >>> for country in root.findall('country'):
   ...     rank = country.find('rank').text
   ...     name = country.get('name')
   ...     print(name, rank)
   ...
   Liechtenstein 1
   Singapore 4
   Panama 68

XPath を使用すると、より洗練された方法で、検索したい要素を指定すること
ができます。


20.5.1.5. XML ファイルの編集
----------------------------

"ElementTree" は XML 文書を構築してファイルに出力する簡単な方法を提供
しています。"ElementTree.write()" メソッドはこの目的に適います。

"Element" オブジェクトを作成すると、そのフィールドの直接変更
("Element.text" など) や、属性の追加および変更 ("Element.set()" メソッ
ド)、あるいは新しい子ノードの追加 (例えば "Element.append()" など) に
よってそれを操作できます。

例えば各 country の rank に 1 を足して、rank 要素に "updated" 属性を追
加したい場合:

   >>> for rank in root.iter('rank'):
   ...     new_rank = int(rank.text) + 1
   ...     rank.text = str(new_rank)
   ...     rank.set('updated', 'yes')
   ...
   >>> tree.write('output.xml')

XML はこのようになります:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank updated="yes">2</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank updated="yes">5</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
       <country name="Panama">
           <rank updated="yes">69</rank>
           <year>2011</year>
           <gdppc>13600</gdppc>
           <neighbor name="Costa Rica" direction="W"/>
           <neighbor name="Colombia" direction="E"/>
       </country>
   </data>

"Element.remove()" を使って要素を削除することが出来ます。例えば rank
が 50 より大きい全ての country を削除したい場合:

   >>> for country in root.findall('country'):
   ...     rank = int(country.find('rank').text)
   ...     if rank > 50:
   ...         root.remove(country)
   ...
   >>> tree.write('output.xml')

XML はこのようになります:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank updated="yes">2</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank updated="yes">5</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
   </data>


20.5.1.6. XML 文書の構築
------------------------

"SubElement()" 関数は、与えられた要素に新しい子要素を作成する便利な手
段も提供しています:

   >>> a = ET.Element('a')
   >>> b = ET.SubElement(a, 'b')
   >>> c = ET.SubElement(a, 'c')
   >>> d = ET.SubElement(c, 'd')
   >>> ET.dump(a)
   <a><b /><c><d /></c></a>


20.5.1.7. 名前空間のある XML の解析
-----------------------------------

XML 入力が 名前空間 を持っている場合、 "prefix:sometag" の形式で修飾さ
れたタグと属性が、その *prefix* が完全な *URI* で置換された
"{uri}sometag" の形に展開されます。さらに、 デフォルトの XML 名前空間
があると、修飾されていない全てのタグにその完全 URI が前置されます。

ひとつは接頭辞 "fictional" でもうひとつがデフォルト名前空間で提供され
た、 2 つの名前空間を組み込んだ XML の例をここにお見せします:

   <?xml version="1.0"?>
   <actors xmlns:fictional="http://characters.example.com"
           xmlns="http://people.example.com">
       <actor>
           <name>John Cleese</name>
           <fictional:character>Lancelot</fictional:character>
           <fictional:character>Archie Leach</fictional:character>
       </actor>
       <actor>
           <name>Eric Idle</name>
           <fictional:character>Sir Robin</fictional:character>
           <fictional:character>Gunther</fictional:character>
           <fictional:character>Commander Clement</fictional:character>
       </actor>
   </actors>

この XML の例を、検索し、渡り歩くためのひとつの方法としては、 "find()"
や "findall()" に渡す xpath で全てのタグや属性に手作業で URI を付けて
まわる手があります:

   root = fromstring(xml_text)
   for actor in root.findall('{http://people.example.com}actor'):
       name = actor.find('{http://people.example.com}name')
       print(name.text)
       for char in actor.findall('{http://characters.example.com}character'):
           print(' |-->', char.text)

もっと良い方法があります。接頭辞の辞書を作り、これを検索関数で使うこと
です:

   ns = {'real_person': 'http://people.example.com',
         'role': 'http://characters.example.com'}

   for actor in root.findall('real_person:actor', ns):
       name = actor.find('real_person:name', ns)
       print(name.text)
       for char in actor.findall('role:character', ns):
           print(' |-->', char.text)

どちらのアプローチでも同じ結果です:

   John Cleese
    |--> Lancelot
    |--> Archie Leach
   Eric Idle
    |--> Sir Robin
    |--> Gunther
    |--> Commander Clement


20.5.1.8. その他の情報
----------------------

http://effbot.org/zone/element-index.htm にはチュートリアルと他のドキ
ュメントへのリンクがあります。


20.5.2. XPath サポート
======================

このモジュールは木構造内の要素の位置決めのための XPath 表現 を限定的に
サポートしています。その目指すところは短縮構文のほんの一部だけのサポー
トであり、XPath エンジンのフルセットは想定していません。


20.5.2.1. 使用例
----------------

以下はこのモジュールの XPath 機能の一部を紹介する例です。XML の解析 節
から XML 文書 "countrydata" を使用します:

   import xml.etree.ElementTree as ET

   root = ET.fromstring(countrydata)

   # Top-level elements
   root.findall(".")

   # All 'neighbor' grand-children of 'country' children of the top-level
   # elements
   root.findall("./country/neighbor")

   # Nodes with name='Singapore' that have a 'year' child
   root.findall(".//year/..[@name='Singapore']")

   # 'year' nodes that are children of nodes with name='Singapore'
   root.findall(".//*[@name='Singapore']/year")

   # All 'neighbor' nodes that are the second child of their parent
   root.findall(".//neighbor[2]")


20.5.2.2. サポートされている XPath 構文
---------------------------------------

+-------------------------+--------------------------------------------------------+
| 操作                    | 意味                                                   |
|=========================|========================================================|
| "tag"                   | 与えられたタグのすべての子要素を選択します。例えば、   |
|                         | "spam" は "spam" と名付けられた子要素すべてを選択し、  |
|                         | "spam/egg" は "spam" と名付けられ た全子要素の中から   |
|                         | "egg" と名付けられた孫要素をすべて選択します。         |
+-------------------------+--------------------------------------------------------+
| "*"                     | すべての子要素を選択します。例えば、"*/egg" は "egg"   |
|                         | と名付けられた孫 要素をすべて選択します。              |
+-------------------------+--------------------------------------------------------+
| "."                     | 現在のノードを選択します。これはパスの先頭に置くことで |
|                         | 相対パスであるこ とを示すのに役立ちます。              |
+-------------------------+--------------------------------------------------------+
| "//"                    | 現在の要素配下のすべてのレベル上のすべての子要素を選択 |
|                         | します。例えば、 ".//egg" は木全体から "egg" 要素を選  |
|                         | 択します。                                             |
+-------------------------+--------------------------------------------------------+
| ".."                    | 親ノードを選択します。パスが開始要素 ("find" が呼ばれ  |
|                         | た要素) の上位要 素への到達を試みた場合 "None" を返し  |
|                         | ます。                                                 |
+-------------------------+--------------------------------------------------------+
| "[@attrib]"             | 与えられた属性を持つすべての要素を選択します。         |
+-------------------------+--------------------------------------------------------+
| "[@attrib='value']"     | 与えられた属性が、与えられた値を持つすべての要素を選択 |
|                         | します。値に引用 符が含まれてはなりません。            |
+-------------------------+--------------------------------------------------------+
| "[tag]"                 | "tag" と名付けられた子要素を持つすべての要素を選択しま |
|                         | す。隣接した子要 素のみサポートしています。            |
+-------------------------+--------------------------------------------------------+
| "[tag='text']"          | 子孫を含む完全なテキストコンテンツと与えられた "text"  |
|                         | が一致する、 "tag" と名付けられた子要素を持つすべての  |
|                         | 要素を選択します。                                     |
+-------------------------+--------------------------------------------------------+
| "[position]"            | 与えられた位置にあるすべての要素を選択します。位置は整 |
|                         | 数 (1 が先頭)、 表現 "last()" (末尾)、あるいは末尾から |
|                         | の相対位置 (例: "last()-1") のい ずれかで指定できます  |
|                         | 。                                                     |
+-------------------------+--------------------------------------------------------+

述部 (角括弧内の表現) の前にはタグ名、アスタリスク、あるいはその他の述
部がなければなりません。"position" 述部の前にはタグ名がなければなりま
せん。


20.5.3. リファレンス
====================


20.5.3.1. 関数
--------------

xml.etree.ElementTree.Comment(text=None)

   コメント要素のファクトリです。このファクトリ関数は、標準のシリアラ
   イザでは XML コメントにシリアライズされる特別な要素を作ります。コメ
   ント文字列はバイト文字列でも Unicode 文字列でも構いません。*text*
   はそのコメント文字列を含んだ文字列です。コメントを表わす要素のイン
   スタンスを返します。

   "XMLParser" は、入力に含まれるコメントを読み飛ばし、コメントオブジ
   ェクトは作成しません。"ElementTree" は、"Element" メソッドの 1 つを
   使用して木内に挿入されたコメントノードのみを含みます。

xml.etree.ElementTree.dump(elem)

   要素の木もしくは要素の構造を sys.stdout に出力します。この関数はデ
   バッグ目的のみに使用してください。

   出力される形式の正確なところは実装依存です。このバージョンでは、通
   常の XML ファイルとして出力されます。

   *elem* は要素の木もしくは個別の要素です。

xml.etree.ElementTree.fromstring(text)

   文字列定数で与えられた XML 断片を解析します。 "XML()" 関数と同じで
   す。 *text* は XML データの文字列です。 "Element" インスタンスを返
   します。

xml.etree.ElementTree.fromstringlist(sequence, parser=None)

   文字列フラグメントのシーケンスから XML ドキュメントを解析します。
   *sequence* は XML データのフラグメントを格納した、リストかその他の
   シーケンスです。 *parser* はオプションのパーザインスタンスです。パ
   ーザが指定されない場合、標準の "XMLParser" パーザが使用されます。
   "Element" インスタンスを返します。

   バージョン 3.2 で追加.

xml.etree.ElementTree.iselement(element)

   オブジェクトが正当な要素オブジェクトであるかをチェックします。
   *element* は要素インスタンスです。引数が要素オブジェクトならば真値
   を返します。

xml.etree.ElementTree.iterparse(source, events=None, parser=None)

   XML セクションを構文解析して要素の木を漸増的に作っていき、その間進
   行状況をユーザーに報告します。 *source* は XML データを含むファイル
   名またはファイル風オブジェクト (*file object*) です。 *events* は報
   告すべきイベントのシーケンスです。サポートされているイベントは、文
   字列の ""start"", ""end"", ""start-ns"", ""end-ns"" です ("ns" イベ
   ントは、名前空間についての詳細情報を取得するために使用)。*events*
   が省略された場合は ""end"" イベントだけが報告されます。 *parser* は
   オプションの引数で、パーサーのインスタンスです。指定されなかった場
   合は標準の "XMLParser" が利用されます。*parser* は "XMLParser" のサ
   ブクラスでなくてはならず、ターゲットとして既定の "TreeBuilder" のみ
   しか使用できません。"(event, elem)" ペアを提供するイテレータ
   (*iterator*) を返します。

   "iterparse()" は木をインクリメンタルに構築しますが、*source* (また
   は指定のファイル) でのブロッキング読みを起こします。したがって、ブ
   ロッキング読みが許可されないアプリケーションには適しません。完全に
   非ブロックのパースのためには、"XMLPullParser" を参照してください。

   注釈: "iterparse()" は "start" イベントを発行した時に開始タグの文
     字 ">" が現れたことだけを保証します。そのため、属性は定義されます
     が、そ の時点ではテキストの内容も tail 属性も定義されていません。
     同じこ とは子要素にも言えて、その時点ではあるともないとも言えませ
     ん。全 部揃った要素が必要ならば、"end" イベントを探してください。

   バージョン 3.4 で非推奨: *parser* 引数。

xml.etree.ElementTree.parse(source, parser=None)

   XML 断片を解析して要素の木にします。 *source* には XML データを含む
   ファイル名またはファイルオブジェクトを指定します。 *parser* はオプ
   ションでパーザインスタンスを指定します。パーザが指定されない場合、
   標準の "XMLParser" パーザが使用されます。 "ElementTree" インスタン
   スを返します。

xml.etree.ElementTree.ProcessingInstruction(target, text=None)

   PI 要素のファクトリです。このファクトリ関数は XML の処理命令として
   シリアライズされた特別な要素を作成します。*target* は PI ターゲット
   を含んだ文字列です。*text* を指定する場合は PI コンテンツを含む文字
   列にします。PI を表わす要素インスタンスを返します。

   "XMLParser" は、入力に含まれる処理命令を読み飛ばし、コメントオブジ
   ェクトは作成しません。"ElementTree" は、"Element" メソッドの 1 つを
   使用して木内に挿入された処理命令ノードのみを含みます。

xml.etree.ElementTree.register_namespace(prefix, uri)

   名前空間の接頭辞を登録します。レジストリはグローバルで、与えられた
   接頭辞か名前空間 URI のどちらかの既存のマッピングはすべて削除されま
   す。*prefix* には名前空間の接頭辞を指定します。*uri* には名前空間の
   URI を指定します。この名前空間のタグや属性は、可能な限り与えられた
   接頭辞をつけてシリアライズされます。

   バージョン 3.2 で追加.

xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

   子要素のファクトリです。この関数は要素インスタンスを作成し、それを
   既存の要素に追加します。

   要素名、属性名、および属性値はバイト文字列でも Unicode 文字列でも構
   いません。 *parent* には親要素を指定します。 *tag* には要素名を指定
   します。*attrib* はオプションで要素の属性を含む辞書を指定します。
   *extra* は追加の属性で、キーワード引数として与えます。要素インスタ
   ンスを返します。

xml.etree.ElementTree.tostring(element, encoding="us-ascii", method="xml", *, short_empty_elements=True)

   XML 要素を全ての子要素を含めて表現する文字列を生成します。
   *element* は "Element" のインスタンスです。 *encoding* [1] は出力エ
   ンコーディング(デフォルトは US-ASCII)です。Unicode 文字列を生成する
   には、"encoding="unicode"" を使用してください。 *method* は
   ""xml"", ""html"", ""text"" のいずれか(デフォルトは ""xml"") です。
   *short_empty_elements* は、 "ElementTree.write()" での意味と同じ意
   味を持ちます。 XML データを含んだ (オプションで) エンコードされた文
   字列を返します。

   バージョン 3.4 で追加: *short_empty_elements* 引数。

xml.etree.ElementTree.tostringlist(element, encoding="us-ascii", method="xml", *, short_empty_elements=True)

   XML 要素を全ての子要素を含めて表現する文字列を生成します。
   *element* は "Element" のインスタンスです。 *encoding* [1] は出力エ
   ンコーディング(デフォルトは US-ASCII)です。Unicode 文字列を生成する
   には、"encoding="unicode"" を使用してください。 *method* は
   ""xml"", ""html"", ""text"" のいずれか(デフォルトは ""xml"") です。
   *short_empty_elements* は、 "ElementTree.write()" での意味と同じ意
   味を持ちます。 XML データを含んだ (オプションで) エンコードされた文
   字列のリストを返します。"b"".join(tostringlist(element)) ==
   tostring(element)" となること以外、特定の順序になる保証はありません
   。

   バージョン 3.2 で追加.

   バージョン 3.4 で追加: *short_empty_elements* 引数。

xml.etree.ElementTree.XML(text, parser=None)

   文字列定数で与えられた XML 断片を解析します。この関数は Python コー
   ドに "XML リテラル" を埋め込むのに使えます。 *text* には XML データ
   を含む文字列を指定します。 *parser* はオプションで、パーザのインス
   タンスを指定します。指定されなかった場合、標準の "XMLParser" パーザ
   を使用します。 "Element" インスタンスを返します。

xml.etree.ElementTree.XMLID(text, parser=None)

   文字列定数で与えられた XML 断片を解析し、要素 ID と要素を対応付ける
   辞書を返します。 *text* には XMLデータを含んだ文字列を指定します。
   *parser* はオプションで、パーザのインスタンスを指定します。指定され
   なかった場合、標準の "XMLParser" パーザを使用します。 "Element" の
   インスタンスと辞書のタプルを返します。


20.5.3.2. Element オブジェクト
------------------------------

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

   要素クラスです。この関数は Element インタフェースを定義すると同時に
   、そのリファレンス実装を提供します。

   要素名、属性名、および属性値はバイト文字列でも Unicode 文字列でも構
   いません。 *tag* には要素名を指定します。*attrib* はオプションで、
   要素と属性を含む辞書を指定します。*extra* は追加の属性で、キーワー
   ド引数として与えます。要素インスタンスを返します。

   tag

      この要素が表すデータの種類を示す文字列です (言い替えると、要素の
      型です)。

   text
   tail

      これらの属性は要素に結びつけられた付加的なデータを保持するのに使
      われます。これらの属性値はたいてい文字列ですが、アプリケーション
      固有のオブジェクトであって構いません。要素が XML ファイルから作
      られる場合、 *text* 属性は要素の開始タグとその最初の子要素または
      終了タグまでのテキストか、あるいは "None" を保持し、 *tail* 属性
      は要素の終了タグと次のタグまでのテキストか、あるいは "None"  を
      保持します。このような XML データ

         <a><b>1<c>2<d/>3</c></b>4</a>

      の場合、 *a* 要素は *text*, *tail* 属性ともに "None", *b* 要素は
      *text* に ""1"" で *tail* に ""4"", *c* 要素は *text* に ""2""
      で *tail* は "None", *d* 要素 は *text* が "None" で *tail* に
      ""3"" をそれぞれ保持します。

      要素の内側のテキストを収集するためには、"itertext()" を参照して
      ください。例えば """.join(element.itertext())" のようにします。

      アプリケーションはこれらの属性に任意のオブジェクトを格納できます
      。

   attrib

      要素の属性を保持する辞書です。 *attrib* の値は常に書き換え可能な
      Python 辞書ですが、ElementTree の実装によっては別の内部表現を使
      用し、要求されたときにだけ辞書を作るようにしているかもしれません
      。そうした実装の利益を享受するために、可能な限り下記の辞書メソッ
      ドを通じて使用してください。

   以下の辞書風メソッドが要素の属性に対して動作します。

   clear()

      要素をリセットします。この関数は全ての子要素を削除し、全属性を消
      去し、テキストとテール属性を "None" に設定します。

   get(key, default=None)

      要素の *key* という名前の属性を取得します。

      属性の値、または属性がない場合は *default* を返します。

   items()

      要素の属性を (名前, 値) ペアのシーケンスとして返します。返される
      属性の順番は決まっていません。

   keys()

      要素の属性名をリストとして返します。返される名前の順番は決まって
      いません。

   set(key, value)

      要素の属性 *key* に *value* をセットします。

   以下のメソッドは要素の子要素 (副要素) に対して動作します。

   append(subelement)

      要素 *subelement* を、要素の子要素の内部リストの末尾に追加します
      。*subelement* "Element" でない場合、"TypeError" を送出します。

   extend(subelements)

      0 個以上の要素のシーケンスオブジェクトによって *subelements* を
      拡張します。*subelements* が "Element" でない場合、"TypeError"
      を送出します。

      バージョン 3.2 で追加.

   find(match, namespaces=None)

      *match* にマッチする最初の子要素を検索します。*match* はタグ名ま
      たは パス を指定できます。要素インスタンスか "None" を返します。
      *namespaces* はオプションで、名前空間接頭辞から完全名を対応付け
      るマップオブジェクトを指定します。

   findall(match, namespaces=None)

      タグ名または パス にマッチするすべての子要素を検索します。マッチ
      したすべての子要素が文書内の順序で含まれたリストを返します。
      *namespaces* はオプションで、名前空間接頭辞から完全名を対応付け
      るマップオブジェクトを指定します。

   findtext(match, default=None, namespaces=None)

      *match* にマッチする最初の子要素のテキストを検索します。*match*
      にはタグ名または パス を指定できます。最初にマッチした要素の内容
      のテキストを返します。マッチする要素が無い場合 *default* を返し
      ます。マッチした要素の内容にテキストがなかった場合空の文字列が返
      ります。*namespaces* はオプションで、名前空間接頭辞から完全名を
      対応付けるマップオブジェクトを指定します。

   getchildren()

      バージョン 3.2 で非推奨: "list(elem)" かイテレーションを使用して
      ください。

   getiterator(tag=None)

      バージョン 3.2 で非推奨: 代わりに "Element.iter()" メソッドを使
      用してください。

   insert(index, subelement)

      要素内の指定された位置に *subelement* を挿入します。*subelement*
      が "Element" でない場合、"TypeError" を送出します。

   iter(tag=None)

      現在の要素を根とする木の *イテレータ* を作成します。イテレータは
      現在の要素とそれ以下のすべての要素を、文書内での出現順 (深さ優先
      順) でイテレートします。 *tag* が "None" または "'*'" でない場合
      、与えられたタグに等しいものについてのみイテレータから返されます
      。イテレート中に木構造が変更された場合の結果は未定義です。

      バージョン 3.2 で追加.

   iterfind(match, namespaces=None)

      タグ名または パス にマッチするすべての子要素を検索します。マッチ
      したすべての要素を文書内での出現順で yield するイテレータを返し
      ます。*namespaces* はオプションで、名前空間接頭辞と完全名を対応
      付けるマップオブジェクトを指定します。

      バージョン 3.2 で追加.

   itertext()

      テキストのイテレータを作成します。イテレータは、この要素とすべて
      の子要素を文書上の順序で巡回し、すべての内部のテキストを返します
      。

      バージョン 3.2 で追加.

   makeelement(tag, attrib)

      現在の要素と同じ型の新しい要素オブジェクトを作成します。このメソ
      ッドは呼び出さずに、 "SubElement()" ファクトリ関数を使って下さい
      。

   remove(subelement)

      要素から *subelement* を削除します。find* メソッド群と異なり、こ
      のメソッドは要素をインスタンスの同一性で比較します。タグや内容で
      は比較しません。

   "Element" オブジェクトは以下のシーケンス型のメソッドを、サブ要素を
   操作するためにサポートします:  "__delitem__()", "__getitem__()",
   "__setitem__()", "__len__()".

   注意: 子要素を持たない要素の真偽値は "False" になります。この挙動は
   将来のバージョンで変更されるかもしれません。直接真偽値をテストする
   のでなく、 "len(elem)" か "elem is None" を利用してください。

      element = root.find('foo')

      if not element:  # careful!
          print("element not found, or element has no subelements")

      if element is None:
          print("element not found")


20.5.3.3. ElementTree オブジェクト
----------------------------------

class xml.etree.ElementTree.ElementTree(element=None, file=None)

   ElementTree ラッパークラスです。このクラスは要素の全階層を表現し、
   さらに標準 XML との相互変換を追加しています。

   *element* は根要素です。*file* が指定されている場合、その XML ファ
   イルの内容により木は初期化されます。

   _setroot(element)

      この木の根要素を置き換えます。従って現在の木の内容は破棄され、与
      えられた要素が代わりに使われます。注意して使ってください。
      *element* は要素インスタンスです。

   find(match, namespaces=None)

      "Element.find()" と同じで、木の根要素を起点とします。

   findall(match, namespaces=None)

      "Element.findall()" と同じで、木の根要素を起点とします。

   findtext(match, default=None, namespaces=None)

      "Element.findtext()" と同じで、木の根要素を起点とします。

   getiterator(tag=None)

      バージョン 3.2 で非推奨: 代わりに "ElementTree.iter()" メソッド
      を使用してください。

   getroot()

      この木のルート要素を返します。

   iter(tag=None)

      根要素に対する、木を巡回するイテレータを返します。イテレータは木
      のすべての要素に渡ってセクション順にループします。*tag* は探した
      いタグです (デフォルトではすべての要素を返します)。

   iterfind(match, namespaces=None)

      "Element.iterfind()" と同じで、木の根要素を起点とします。

      バージョン 3.2 で追加.

   parse(source, parser=None)

      外部の XML 断片をこの要素木に入れます。*source* にはファイル名か
      *ファイルオブジェクト* を指定します。*parser* はオプションで、パ
      ーザインスタンスを指定します。パーザが指定されない場合、標準の
      "XMLParser" パーザが使用されます。断片の根要素を返します。

   write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml", *, short_empty_elements=True)

      要素の木をファイルに XML として書き込みます。 *file* は、書き込
      み用に開かれたファイル名またはファイル風オブジェクト (*file
      object*) です。 *encoding* [1] は出力エンコーディング(デフォルト
      は US-ASCII)です。 *xml_declaration* は、 XML 宣言がファイルに書
      かれるかどうかを制御します。 "False" の場合は常に書かれず、
      "True" の場合は常に書かれ、 "None" の場合は US-ASCII 、 UTF-8 、
      Unicode 以外の場合に書かれます (デフォルトは "None" です)。
      *default_namespace* でデフォルトの XML 名前空間 ("xmlns" 用) を
      指定します。 *method* は ""xml"", ""html"", ""text"" のいずれか
      です (デフォルトは ""xml"" です)。名前付き引数 (キーワード引数)
      の *short_empty_elements* は、内容がない属性のフォーマットを制御
      します。"True" (既定) の場合、単一の空要素タグとして書かれ、
      "False" の場合、開始タグと終了タグのペアとしてかかれます。

      出力は引数 *encoding* によって、文字列 ("str") かバイト列
      ("bytes") になります。*encoding* が ""unicode"" の場合、出力は文
      字列になり、それ以外ではバイト列になります。*file* が *ファイル
      オブジェクト* の場合、型が衝突する場合があります。文字列をバイト
      列ファイルへ書き込んだり、その逆を行わないよう注意してください。

      バージョン 3.4 で追加: *short_empty_elements* 引数。

以下はこれから操作する XML ファイルです:

   <html>
       <head>
           <title>Example page</title>
       </head>
       <body>
           <p>Moved to <a href="http://example.org/">example.org</a>
           or <a href="http://example.com/">example.com</a>.</p>
       </body>
   </html>

第 1 段落のすべてのリンクの "target" 属性を変更する例:

   >>> from xml.etree.ElementTree import ElementTree
   >>> tree = ElementTree()
   >>> tree.parse("index.xhtml")
   <Element 'html' at 0xb77e6fac>
   >>> p = tree.find("body/p")     # Finds first occurrence of tag p in body
   >>> p
   <Element 'p' at 0xb77ec26c>
   >>> links = list(p.iter("a"))   # Returns list of all links
   >>> links
   [<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
   >>> for i in links:             # Iterates through all found links
   ...     i.attrib["target"] = "blank"
   >>> tree.write("output.xhtml")


20.5.3.4. QName オブジェクト
----------------------------

class xml.etree.ElementTree.QName(text_or_uri, tag=None)

   QName ラッパーです。 このクラスは QName 属性値をラップし、出力時に
   適切な名前空間の扱いを得るために使われます。 *text_or_uri* は
   {uri}local という形式の QName 値を含む文字列、または tag 引数が与え
   られた場合には QName の URI 部分の文字列です。 *tag* が与えられた場
   合、一つめの引数は URI と解釈され、この引数はローカル名と解釈されま
   す。 "QName" インスタンスは不透明です。


20.5.3.5. TreeBuilder オブジェクト
----------------------------------

class xml.etree.ElementTree.TreeBuilder(element_factory=None)

   汎用の要素構造ビルダです。これは start、data、および end メソッドの
   シーケンスを適格な要素構造に変換します。このクラスを使うと、カスタ
   ム XML パーザ、あるいは他の XML に似た形式のパーザを使用して要素構
   造を構築できます。*element_factory* を指定する場合、タグと属性の辞
   書の 2 個の位置引数へのアクセスによって呼び出し可能でなければなりま
   せん。これは新しい要素インスタンスを返すはずです。

   close()

      ビルダのバッファをフラッシュし、最上位の文書要素を返します。戻り
      値は  "Element" インスタンスになります。

   data(data)

      現在の要素にテキストを追加します。 *data* は文字列です。バイト文
      字列もしくは Unicode 文字列でなければなりません。

   end(tag)

      現在の要素を閉じます。 *tag* は要素の名前です。閉じられた要素を
      返します。

   start(tag, attrs)

      新しい要素を開きます。 *tag* は要素の名前です。 *attrs* は要素の
      属性を保持した辞書です。開かれた要素を返します。

   加えて、カスタムの "TreeBuilder" オブジェクトは以下のメソッドを提供
   できます:

   doctype(name, pubid, system)

      doctype 宣言を処理します。 *name* は doctype 名です。 *pubid* は
      公式の識別子です。 *system* はシステム識別子です。このメソッドは
      デフォルトの "TreeBuilder" クラスには存在しません。

      バージョン 3.2 で追加.


20.5.3.6. XMLParser オブジェクト
--------------------------------

class xml.etree.ElementTree.XMLParser(html=0, target=None, encoding=None)

   このクラスは、このモジュールの構成要素のうち、低水準のものです。効
   率的でイベントベースのXMLパースのため、"xml.parsers.expat" を使用し
   ます。"feed()" メソッドで XML データをインクリメンタルに受け取り、
   *target* オブジェクトのコールバックを呼び出すことで、パースイベント
   をプッシュ API に変換します。*target* が省略された場合、標準の
   "TreeBuilder" が使用されます。*html* 引数は、後方互換性のため使われ
   てきましたが、廃止されました。*encoding* [1] が指定された場合、この
   あたいは XML ファイル内で指定されたエンコーディングを上書きします。

   バージョン 3.4 で非推奨: *html* 引数。残りの引数は、キーワード引数
   として渡し、 *html* 引数の削除に向けて備えるべきです。

   close()

      パーザへのデータの提供を完了します。構築中に渡される *target* の
      "close()" メソッドを呼び出す結果を返します。既定では、これがトッ
      プレベルのドキュメント要素になります。

   doctype(name, pubid, system)

      バージョン 3.2 で非推奨: カスタムの TreeBuilder target で
      "TreeBuilder.doctype()" メソッドを定義してください。

   feed(data)

      パーザへデータを入力します。 *data* はエンコードされたデータです
      。

   "XMLParser.feed()" は *target* の "start(tag, attrs_dict)" メソッド
   をそれぞれの開始タグに対して呼び、また "end(tag)" メソッドを終了タ
   グに対して呼び、そしてデータを "data(data)" メソッドで処理します。
   "XMLParser.close()" は *target* の "close()" メソッドを呼びます。
   "XMLParser" は木構造を構築する以外にも使えます。以下の例では、XML
   ファイルの最高の深さを数えます。

      >>> from xml.etree.ElementTree import XMLParser
      >>> class MaxDepth:                     # The target object of the parser
      ...     maxDepth = 0
      ...     depth = 0
      ...     def start(self, tag, attrib):   # Called for each opening tag.
      ...         self.depth += 1
      ...         if self.depth > self.maxDepth:
      ...             self.maxDepth = self.depth
      ...     def end(self, tag):             # Called for each closing tag.
      ...         self.depth -= 1
      ...     def data(self, data):
      ...         pass            # We do not need to do anything with data.
      ...     def close(self):    # Called when all data has been parsed.
      ...         return self.maxDepth
      ...
      >>> target = MaxDepth()
      >>> parser = XMLParser(target=target)
      >>> exampleXml = """
      ... <a>
      ...   <b>
      ...   </b>
      ...   <b>
      ...     <c>
      ...       <d>
      ...       </d>
      ...     </c>
      ...   </b>
      ... </a>"""
      >>> parser.feed(exampleXml)
      >>> parser.close()
      4


20.5.3.7. XMLPullParser オブジェクト
------------------------------------

class xml.etree.ElementTree.XMLPullParser(events=None)

   非ブロックアプリケーションに適したプルパーザです。入力側の API は
   "XMLParser" のものと似ていますが、コールバックターゲットに呼び出し
   をプッシュするのではなく、 "XMLPullParser" はパースイベントの内部リ
   ストを収集し、ユーザーがそこから読み出すことができます。*events* は
   、呼び出し元に報告するイベントのシーケンスです。サポートされている
   イベントは、文字列の ""start"", ""end"", ""start-ns"", ""end-ns""
   ("ns" イベントは、名前空間の詳細情報の取得に使用) です。*events* が
   省略された場合、 ""end"" イベントのみが報告されます。

   feed(data)

      指定したバイトデータをパーザに与えます。

   close()

      パーザに、データストリームが終了したことを伝えます。
      "XMLParser.close()" とは異なり、このメソッドは常に "None" を返し
      ます。パーザがクローズした時にまだ帰って来ていないイベントは、ま
      だ "read_events()" で読むことができます。

   read_events()

      パーザに与えられたデータ中で見つかったイベントのイテレータを返し
      ます。このイテレータは、"(event, elem)" ペアを順に返します。ここ
      で、 *event* はイベントの種類を表す文字列 (例: ""end"")、*elem*
      は見つかった "Element" オブジェクトです。

      "read_events()" の前の呼び出しで提供されたイベントは、再度 yield
      されることはありません。イベントは、イテレータから取得された場合
      にのみ内部キューから消費されるため、"read_events()" から取得され
      たイテレータに対して複数の読み出しを並行して反復的に行うと、予期
      せぬ結果が引き起こされます。

   注釈: "XMLPullParser"  は "start" イベントを発行した時に開始タグ
     の文字 ">" が現れたことだけを保証します。そのため、属性は定義され
     ますが 、その時点ではテキストの内容も tail 属性も定義されていませ
     ん。子 要素にもそれが存在する、しないにかかわらず同じ物が適用され
     ます。 全部揃った要素が必要ならば、"end" イベントを探してください
     。

   バージョン 3.4 で追加.


20.5.3.8. 例外
--------------

class xml.etree.ElementTree.ParseError

   解析に失敗した時、このモジュールの様々なメソッドから送出される XML
   解析エラーです。この例外のインスタンスが表す文字列は、ユーザフレン
   ドリなメッセージを含んでいます。その他に、以下の属性も利用できます:

   code

      expat パーザからの数値エラーコードです。エラーコードの一覧とそれ
      らの意味については、"xml.parsers.expat" のドキュメントを参照して
      ください。

   position

      エラーが発生した場所を示す *line* と *column* 番号のタプルです。

-[ 脚注 ]-

[1] XML 出力に含まれるエンコーディング文字列は適切な規格に従ってい
    なけ ればなりません。例えば、"UTF-8" は有効ですが、"UTF8" はそうで
    はあ りません。https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-
    EncodingDecl と https://www.iana.org/assignments/character-sets
    /character-sets.xhtml を参照してください。
