ElementTreeモジュールで、ソースXMLファイルのいくつかの要素を見つけるために、"findall"のメソッドを使用したいと思います。
しかし、ソースXMLファイル(test.xml)には名前空間があります。サンプルとして、xmlファイルの一部を切り捨ててみました。
<?xml version="1.0" encoding="iso-8859-1"?>
<XML_HEADER xmlns="http://www.test.com">
<TYPE>Updates</TYPE>
<DATE>9/26/2012 10:30:34 AM</DATE>
<COPYRIGHT_NOTICE>All Rights Reserved.</COPYRIGHT_NOTICE>
<LICENSE>newlicense.htm</LICENSE>
<DEAL_LEVEL>
<PAID_OFF>N</PAID_OFF>
</DEAL_LEVEL>
</XML_HEADER>
Pythonコードのサンプルは以下の通りです。
from xml.etree import ElementTree as ET
tree = ET.parse(r"test.xml")
el1 = tree.findall("DEAL_LEVEL/PAID_OFF") # Return None
el2 = tree.findall("{http://www.test.com}DEAL_LEVEL/{http://www.test.com}PAID_OFF") # Return <Element '{http://www.test.com}DEAL_LEVEL/PAID_OFF' at 0xb78b90>
一応動作はするのですが、名前空間 "{http://www.test.com}" があるので、各タグの前に名前空間を追加するのは非常に不便です。
find"、"findall"などのメソッドを使うときに、名前空間を無視するにはどうしたらよいでしょうか。
xmlns属性を削除してからパースすると、ツリー内の各タグの先頭に名前空間が付かない。
import re
xmlstring = re.sub(' xmlns="[^"]+"', '', xmlstring, count=1)
これまでの回答では、namespaceの値をスクリプトに明示的に記述していました。より一般的な解決策としては、私はむしろxmlから名前空間を抽出することをお勧めします。
import re
def get_namespace(element):
m = re.match('\{.*\}', element.tag)
return m.group(0) if m else ''
そして、それをfindメソッドで使用します。
namespace = get_namespace(tree.getroot())
print tree.find('./{0}parent/{0}version'.format(namespace)).text