web-dev-qa-db-ja.com

Python:ElementTree、要素の名前空間文字列を取得

このXMLファイルの名前は_example.xml_です。

_<?xml version="1.0"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/maven-v4_0_0.xsd">

  <modelVersion>14.0.0</modelVersion>
  <groupId>.com.foobar.flubber</groupId>
  <artifactId>uberportalconf</artifactId>
  <version>13-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>Environment for UberPortalConf</name>
  <description>This is the description</description>    
  <properties>
      <birduberportal.version>11</birduberportal.version>
      <promotiondevice.version>9</promotiondevice.version>
      <foobarportal.version>6</foobarportal.version>
      <eventuberdevice.version>2</eventuberdevice.version>
  </properties>
  <!-- A lot more here, but as it is irrelevant for the problem I have removed it -->
</project>
_

Example.xmlをロードしてElementTreeで解析すると、名前空間が_http://maven.Apache.org/POM/4.0.0_であることがわかります。

_>>> from xml.etree import ElementTree
>>> tree = ElementTree.parse('example.xml')
>>> print tree.getroot()
<Element '{http://maven.Apache.org/POM/4.0.0}project' at 0x26ee0f0>
_

Elementのstr(an_element)を解析せずに、Elementから名前空間のみを取得するために呼び出すメソッドを見つけていません。もっと良い方法があるはずだ。

23
Deleted

名前空間は Element.tag 「実際の」タグの直前:

>>> root = tree.getroot()
>>> root.tag
'{http://maven.Apache.org/POM/4.0.0}project'

名前空間の詳細については、 ElementTree:Working with Namespaces and Qualified Names を参照してください。

23
Rik Poggi

これは 正規表現 に最適なタスクです。

import re

def namespace(element):
    m = re.match(r'\{.*\}', element.tag)
    return m.group(0) if m else ''
15
Mark Ransom

これがxml.etreeで可能かどうかはわかりませんが、lxml.etreeでこれを行う方法を次に示します。

>>> from lxml import etree
>>> tree = etree.parse('example.xml')
>>> tree.xpath('namespace-uri(.)')
'http://maven.Apache.org/POM/4.0.0'
12
Jakub Roztocil

正規表現を使用しない場合:

>>> root
<Element '{http://www.google.com/schemas/sitemap/0.84}urlset' at 0x2f7cc10>

>>> root.tag.split('}')[0].strip('{')
'http://www.google.com/schemas/sitemap/0.84'
8
Lorcan

属性を確認する方が簡単だと思います。

>>> root.attrib
{'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation':
   'http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/maven-v4_0_0.xsd'}
1
jcollado

短い答えは:

ElementTree._namspace_map[ElementTree._namspace_map.values().index('')]

しかし、あなたが電話をしてきた場合のみ

ElementTree.register_namespace(prefix,uri)

の結果を繰り返し処理中に受信したすべてのevent == "start-ns"に応答して

ET.iterparse(...) 

"start-ns"に登録しました

「デフォルトの名前空間は何ですか?」という質問への回答として、2つの点を明確にする必要があります。

(1)XML仕様では、デフォルトの名前空間は必ずしもツリー全体でグローバルである必要はなく、デフォルトの名前空間はルートの下の任意の要素で再宣言でき、別のデフォルトの名前空間の再宣言を満たすまで下方に継承されます。

(2)ElementTreeモジュールは、ルートのデフォルト名前空間を持たないXMLのようなドキュメントを(事実上)処理できます。 (*より厳密でない条件がある場合があります。たとえば、「if」であり、必ずしも「iff」ではありません)。

また、「何のために欲しいのか」についても検討する価値があります。 XMLファイルは意味的には同等であるが、構文的には非常に異なる可能性があることを考慮してください。たとえば、次の3つのファイルは意味的に同等ですが、A.xmlにはデフォルトの名前空間宣言が1つあり、B.xmlには3つあり、C.xmlには何もありません。

A.xml:
<a xlmns="http://A" xlmns:nsB0="http://B0" xlmns:nsB1="http://B1">
     <nsB0:b/>
     <nsB1:b/>
</a>

B.xml:
<a xlmns="http://A">
     <b xlmns="http://B0"/>
     <b xlmns="http://B1"/>
</a>

C.xml:
<{http://A}a>
     <{http://B0}b/>
     <{http://B1}b/>
</a>

C.xmlファイルは、ElementTree検索関数に提示される正規の拡張された構文表現です。

名前空間の衝突がないことが事前にわかっている場合は、解析中に要素タグを変更して、ここで説明するように解析できます。 Python ElementTreeモジュール:メソッドの使用時にXMLファイルの名前空間を無視して一致する要素を見つける方法「検索」、「検索」

1
Craig Hicks

lxml.xtreeライブラリの要素には、現在のタグスコープで使用されているすべての名前空間を示すnsmapという辞書があります。

>>> item = tree.getroot().iter().next()
>>> item.nsmap
{'md': 'urn:oasis:names:tc:SAML:2.0:metadata'}
1
Cypher

上記の答えのいくつかを組み合わせて、私は最短のコードは

theroot = tree.getroot()
theroot.attrib[theroot.keys()[0]]
0
user8874906