2015-12-04 13 views
5

ElementTreeにXMLファイルの名前空間を無視するように指示するにはどうすればよいですか?Python:xml.etree.ElementTreeの名前空間を無視しますか?

たとえば、{http://maven.apache.org/POM/4.0.0}modelVersion(ステートメント2のように)ではなく、modelVersion(ステートメント1のように)を照会することをお勧めします。

pom=""" 
<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>4.0.0</modelVersion> 
</project> 
""" 

from xml.etree import ElementTree 
ElementTree.register_namespace("","http://maven.apache.org/POM/4.0.0") 
root = ElementTree.fromstring(pom) 

print 1,root.findall('modelVersion') 
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion') 

1 [] 
2 [<Element '{http://maven.apache.org/POM/4.0.0}modelVersion' at 0x1006bff10>] 
+1

AFAIK簡単な方法ではないo特に、複数の名前空間を扱う可能性がある場合は特にそうではありません。重複した質問があるように見えますが(http://stackoverflow.com/q/13412496/20670)、それらのアプローチがあなたのためには機能しないと言ったら、私はデュエルハマーを使わないでしょう私に汚れたハックのように見える)。 –

+0

また、['lxml'は調べる価値があるかもしれません](http://stackoverflow.com/q/14853243/20670)、標準ライブラリの一部ではありません。 –

+1

悲しいことに、私はlxmlをインストールできない人にこれを送っています。私は、標準の図書館がいつかそれを組み込むことを願っています。私は私がプロのプログラマーであることを私の母に話しました。 : -/ –

答えて

0

単純な経路がないように見えるので、find呼び出しを単純に囲みます。

from xml.etree import ElementTree as ET 

POM = """ 
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://maven.apache.org/POM/4.0.0"> 
    <modelVersion>4.0.0</modelVersion> 
</project> 
""" 

NSPS = {'foo' : "http://maven.apache.org/POM/4.0.0"} 

# sic! 
def findall(node, tag): 
    return node.findall('foo:' + tag, NSPS) 

root = ET.fromstring(POM) 
print(map(ET.tostring, findall(root, 'modelVersion'))) 

出力:

['<ns0:modelVersion xmlns:ns0="http://maven.apache.org/POM/4.0.0">4.0.0</ns0:modelVersion>\n'] 
0

は、ここで私が現在やっているものだ、より良い方法があることを私は信じられないほど自信を持ってます。

$ cat pom.xml | 
    tr '\n' ' ' | 
    sed 's/<project [^>]*>/<project>/' | 
    myprogram | 
    sed 's/<project>/<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">/' 
+0

パイプでsed'ingの代わりに、Pythonスクリプトでxml文字列を修正するか、ダミーの名前空間とラッパー関数を作成することができます(下のpls。c私の答え) –

+0

私はパイプcoz私の実際のプログラムはきちんとしています。将来私はより良いxmlパッケージに切り替えることができますが、私はラッパーにそのものを落とすことができます。 –

+0

あなたのパイプに既に満足しているなら、正確に何を話しているのですか?:) –

0

無視するのではなく、別のアプローチは、ツリー内の名前空間を削除することですので、彼らがいないがあるので、「無視」する必要はありません - この質問への九角形の答え(およびその私の拡張を参照してくださいは、属性に名前空間を含める):Python ElementTree module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

0

ここでは、シェルを使用しない同等の解決策があります。基本的な考え方:

  • <project junk...>
  • <project>にを変換するには、名前空間
  • を気にすることなく、 "クリーン" な処理を実行するバック<project junk...>新しいコードで

から<project>を翻訳:

pom=""" 
<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>4.0.0</modelVersion> 
</project> 
""" 
short_project="""<project>""" 
long_project="""<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">""" 

import re,sys 
from xml.etree import ElementTree 

# eliminate namespace specs 
pom=re.compile('<project [^>]*>').sub(short_project,pom) 

root = ElementTree.fromstring(pom) 
ElementTree.dump(root) 
print 1,root.findall('modelVersion') 
print 2,root.findall('{http://maven.apache.org/POM/4.0.0}modelVersion') 
mv=root.findall('modelVersion') 

# restore the namespace specs 
pom=ElementTree.tostring(root) 
pom=re.compile(short_project).sub(long_project,pom) 
関連する問題