gpt4 book ai didi

python : How to navigate XML sub-nodes efficiently?

转载 作者:行者123 更新时间:2023-12-01 08:00:53 27 4
gpt4 key购买 nike

我正在尝试从 XML 中提取某些数据点,并尝试了两种选择...

  1. 使用 ElementTree 处理 XML 格式
  2. 使用 xmltodict 处理字典

这是我到目前为止所得到的,

代码

# Packages
# --------------------------------------
import xml.etree.ElementTree as ET

# XML Data
# --------------------------------------
message_xml = \
'<ClinicalDocument> \
<code code="34133-9" displayName="Summarization of Episode Note"/> \
<title>Care Summary</title> \
<recordTarget> \
<patientRole> \
<id assigningAuthorityName="LOCAL" extension="L123456"/> \
<id assigningAuthorityName="SSN" extension="788889999"/> \
<id assigningAuthorityName="GLOBAL" extension="G123456"/> \
<addr use="HP"> \
<streetAddressLine>1000 N SOME AVENUE</streetAddressLine> \
<city>BIG CITY</city> \
<state>NA</state> \
<postalCode>12345-1010</postalCode> \
<country>US</country> \
</addr> \
<telecom nullFlavor="NI"/> \
<patient> \
<name use="L"> \
<given>JANE</given> \
<given>JOE</given> \
<family>DOE</family> \
</name> \
</patient> \
</patientRole> \
</recordTarget> \
</ClinicalDocument>'

# Get Tree & Root
# --------------------------------------
tree = ET.ElementTree(ET.fromstring(message_xml))
root = tree.getroot()

# Iterate
# --------------------------------------
for node in root:

tag = node.tag
attribute = node.attrib

# Get ClinicalDocument.code values
if tag == 'code':
document_code_code = attribute.get('code')
document_code_name = attribute.get('displayName')

else:
pass

# Get ClinicalDocument.recordTarget values
if tag == 'recordTarget':

for child in node.iter():

# Multiple <id> tags
record_target_local = ??
record_target_ssn = ??
record_target_global = ??

# Multiple <given> tags
record_target_name_first = ??
record_target_name_middle = ??
record_target_name_last = ??

else:
pass

预期输出

document_code,document_name,id_local,id_ssn,id_global,name_first, name_middle,name_last
34133-9,Summarization of Episode Note,L123456,788889999,G123456,JANE,JOE,DOE

可接受的输出

document_code,document_name,id_type,id,name_first,name_middle,name_last
34133-9,Summarization of Episode Note,LOCAL,L123456,JANE,JOE,DOE
34133-9,Summarization of Episode Note,SSN,788889999,JANE,JOE,DOE
34133-9,Summarization of Episode Note,GLOBAL,G123456,JANE,JOE,DOE

问题

  1. 如何高效地导航下有多个子节点的子节点?
  2. 如何处理重复标签(例如: <id><given> )?

最佳答案

How to efficiently navigate child-nodes with multiple child-nodes under them?

导航 XML 的一个好方法是使用 XPath 。 ElementTree 有 limited XPath support ,但它看起来足以满足您的需要。如果您最终需要使用更复杂的 XPath,我建议使用 XPath in lxml

How to handle duplicate tags (ex: <id>, <given>)?

这取决于您需要如何处理这些元素。例如,如果您希望每个 id 元素都有单独的行,则需要迭代每个元素(使用 ElementTree 中的 findall() 或 lxml 中的 xpath())。

如果您只需要一个值(文本或属性值),则需要将其范围缩小到 XPath 中的单个元素。

例如,id 元素的 assigningAuthorityName 属性值等于 LOCAL 将是 id[@assigningAuthorityName='LOCAL']

given 元素有点棘手;你怎么知道一个是名字,一个是中间名?我能看到的唯一方式就是位置;第一个 given ( given[1] ) 是第一个名称,第二个 given ( given[2] ) 是第二个名称。您保证始终有两个 given 元素吗?如果没有,您可能需要执行一些检查或 try/except 语句才能获得所需的输出。

此外,由于您正在创建 csv 输出,我建议使用 csv module ;特别是 DictWriter

这将允许您将 XML 中的值存储在字典中以写入行。您可以为新行创建字典的新副本,同时维护通用值(例如 document_codedocument_name )。

以下示例将为每个 recordTarget 创建一个新行。

XML 输入 (input.xml)

<ClinicalDocument> 
<code code="34133-9" displayName="Summarization of Episode Note"/>
<title>Care Summary</title>
<recordTarget>
<patientRole>
<id assigningAuthorityName="LOCAL" extension="L123456"/>
<id assigningAuthorityName="SSN" extension="788889999"/>
<id assigningAuthorityName="GLOBAL" extension="G123456"/>
<addr use="HP">
<streetAddressLine>1000 N SOME AVENUE</streetAddressLine>
<city>BIG CITY</city>
<state>NA</state>
<postalCode>12345-1010</postalCode>
<country>US</country>
</addr>
<telecom nullFlavor="NI"/>
<patient>
<name use="L">
<given>JANE</given>
<given>JOE</given>
<family>DOE</family>
</name>
</patient>
</patientRole>
</recordTarget>
</ClinicalDocument>

Python

import csv
import xml.etree.ElementTree as ET
from copy import deepcopy

values_template = {"document_code": "", "document_name": "", "id_local": "", "id_ssn": "",
"id_global": "", "name_first": "", "name_middle": "", "name_last": ""}

with open("output.csv", "w", newline="") as csvfile:
csvwriter = csv.DictWriter(csvfile, delimiter=",", quoting=csv.QUOTE_MINIMAL,
fieldnames=[name for name in values_template])
csvwriter.writeheader()

tree = ET.parse('input.xml')

values_template["document_code"] = tree.find("code").get("code")
values_template["document_name"] = tree.find("code").get("displayName")

for target in tree.findall("recordTarget"):

values = deepcopy(values_template)

values["id_local"] = target.find("patientRole/id[@assigningAuthorityName='LOCAL']").get("extension")
values["id_ssn"] = target.find("patientRole/id[@assigningAuthorityName='SSN']").get("extension")
values["id_global"] = target.find("patientRole/id[@assigningAuthorityName='GLOBAL']").get("extension")
values["name_first"] = target.find("patientRole/patient/name/given[1]").text
values["name_middle"] = target.find("patientRole/patient/name/given[2]").text
values["name_last"] = target.find("patientRole/patient/name/family").text

csvwriter.writerow(values)

CSV 输出 (output.csv)

document_code,document_name,id_local,id_ssn,id_global,name_first,name_middle,name_last
34133-9,Summarization of Episode Note,L123456,788889999,G123456,JANE,JOE,DOE

这是另一个示例,将为每个 recordTarget/patentRole/id 创建一个新行...

Python

import csv
import xml.etree.ElementTree as ET
from copy import deepcopy

values_template = {"document_code": "", "document_name": "", "id": "",
"name_first": "", "name_middle": "", "name_last": ""}

with open("output.csv", "w", newline="") as csvfile:
csvwriter = csv.DictWriter(csvfile, delimiter=",", quoting=csv.QUOTE_MINIMAL,
fieldnames=[name for name in values_template])
csvwriter.writeheader()

tree = ET.parse('input.xml')

values_template["document_code"] = tree.find("code").get("code")
values_template["document_name"] = tree.find("code").get("displayName")

for target in tree.findall("recordTarget"):

values = deepcopy(values_template)

values["name_first"] = target.find("patientRole/patient/name/given[1]").text
values["name_middle"] = target.find("patientRole/patient/name/given[2]").text
values["name_last"] = target.find("patientRole/patient/name/family").text

for role_id in target.findall("patientRole/id"):
values["id"] = role_id.get("extension")
csvwriter.writerow(values)

CSV 输出 (output.csv)

document_code,document_name,id,name_first,name_middle,name_last
34133-9,Summarization of Episode Note,L123456,JANE,JOE,DOE
34133-9,Summarization of Episode Note,788889999,JANE,JOE,DOE
34133-9,Summarization of Episode Note,G123456,JANE,JOE,DOE

关于 python : How to navigate XML sub-nodes efficiently?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55737318/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com