web-dev-qa-db-ja.com

ElementTree XPath-属性に基づいて要素を選択

ElementTreeで属性XPath Selectorを使用する際に問題があります。これは Documentation に従って実行できるはずです。

ここにいくつかのサンプルコードがあります

[〜#〜] xml [〜#〜]

<root>
 <target name="1">
    <a></a>
    <b></b>
 </target>
 <target name="2">
    <a></a>
    <b></b>
 </target>
</root>

Python

def parse(document):
    root = et.parse(document)
    for target in root.findall("//target[@name='a']"):
        print target._children

次の例外が発生します。

expected path separator ([)
42
Nick Stinemates

使用しようとしている構文は、ElementTree 1.の新機能です。

このようなバージョンは、Python 2.7以降に同梱されています。 Python 2.6以下の場合は、ElementTree 1.2.6以下があります。

34
Florian Bösch

このコードにはいくつかの問題があります。

  1. PythonのビルトインElementTree(略してET)には、実際のXPATHサポートはありません。限られたサブセットのみ例として、_//target_のようなfind-from-root式はサポートされていません。

    注意: documentation は「//」について言及していますが、子供のみを対象としています。つまり、_.//target_としての式は有効; _//..._はそうではありません!

    別の実装があります: lxml これはよりリッチです。組み込みコードのためにドキュメントが使用されているのは継ぎ目です。それは一致/動作しません。

  2. _@name_表記は、xml-attributes;を選択します。 xml-tag内の_key=value_式。

    そのため、指定されたドキュメントで何かを選択するには、name-valueを1または2にする必要があります。または、子を持つターゲットを検索できますelement 'a':_target[a]_ (番号 @)。

与えられたドキュメントについて、組み込みのElementTree(v1.3)を使用してルートに解析すると、次のコードが正しく機能しています。

  • root.findall(".//target")両方のターゲットを検索
  • root.findall(".//target/a") 2つのa要素を見つける
  • root.findall(".//target[a]")両方にa要素があるため、これにより両方のtarget要素が再び検出されます
  • root.findall(".//target[@name='1']")firstターゲットのみを検索します。 1前後の引用符が必要であることに注意してください。それ以外の場合はSyntaxErrorが発生します
  • root.findall(".//target[a][@name='1']")も有効です。そのターゲットを見つける
  • root.findall(".//target[@name='1']/a") 1つのa要素のみを検索します。 ...
19
Albert