概要
PythonでXMLファイルの内容をXpathを使って読み取る場合にnamespace付きの場合は読み込むためにちょっとコツが必要だったのでその方法を記載します。
こちらのページを参考にやってみた内容を記載しています。
環境
- Python 3.7.9
- lxml 4.3.0
- lxmlについてはpipなどでインストールする必要があります。
処理方法
NameSpace付きのXML
特定検診・特定保健指導データの 特定健診(人間ドック)
のXMLを参考にやってみます。
こちらのXMLファイルの最初の部分に以下のような記述があります。
<ClinicalDocument xmlns="urn:hl7-org:v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:hl7-org:v3 ../XSD/hc08_V08.xsd">
このような xmlns~
のような部分があるとXpathを指定しただけでは読み取ることができません。
以下のコードを実行すると
from lxml import etree
tree = etree.parse('kensin_dokku_tokutei.xml')
root = tree.getroot()
root.tag
{urn:hl7-org:v3}ClinicalDocument
のように{urn:hl7-org:v3}
のnamespaceが設定されていることが確認できます。
この部分が邪魔をしてXpathを指定しただけでは取得できなくなっています。
一方MicrosoftのサンプルXMLのxmlを読み込んでみると
PurchaseOrder
とnamespaceの部分がないことが確認できます。
XMLの読み方
lxml
を使って xpath
を読むときにnamespaceを設定することで読み込むことができます。
以下のようにnamespaceを確認して
tree = etree.parse('kensin_dokku_tokutei.xml')
root = tree.getroot()
root.nsmap
{None: 'urn:hl7-org:v3', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
デフォルトのnamespaceに適当な値を設定します。
ここでは x
としています。
mynsmap={}
mynsmap['x'] = root.nsmap[None]
mynsmap['xsi'] = root.nsmap['xsi']
mynsmap
のdictを引数に渡すことで以下のように結果を確認できます。
tree.xpath("/x:ClinicalDocument/x:participant/x:associatedEntity/x:id/@extension", namespaces=mynsmap)
['18100001001']
Attribute を読むときは上記のように @
で属性を指定することで取得できます。
テキストの情報を取る時は text
を指定することで取得できます。
result=tree.xpath("/x:ClinicalDocument/x:component/x:structuredBody/x:component[1]/x:section/x:text/x:list/x:item[1]", namespaces=mynsmap)
result[0].text
'身長 162.3 cm'
XMLPathの確認方法
余談ですがXMLファイルのXpathの確認方法も記載しておきます。
- FireFoxでXMLファイルを開き
右クリック→調査
をクリックして調査用のウィンドウを開きます。 - Xpathを確認したい項目を探して
右クリック→コピー→Xpath
をクリックすることでクリップボードにコピーされます。 -
/
の部分を↑で指定したnamespaceの値に変更します。(上の例では/x:
) - attributeの部分は
/
のみにしておきます。