Python解析带命名空间嵌套XML:提取mfgr值生成零件号字典
解决带命名空间XML解析问题并生成零件-厂商字典
场景与需求
通过API查询零件号后,返回带命名空间的嵌套XML(精简结构如下),需要将每个零件号作为键,对应<mfgr>元素的文本作为值,生成格式类似{"samplepart1": "manufacturer1", "samplepart2": "manufacturer2"}的字典。
XML示例:
<ArrayOfitem xmlns="WhereDataComesFrom.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <item> <associateditem_swap/> <bulk>false</bulk> <category>Memory</category> <clei>false</clei> <createddate>5/11/2021 7:34:58 PM</createddate> <description>sample description</description> <heci/> <imageurl/> <item_swap/> <itemid>1640</itemid> <itemnumber>**sample part number**</itemnumber> <listprice>0.0000</listprice> <manufactureritem/> <maxavailable>66</maxavailable> <mfgr>**sample manufacturer**</mfgr> <minreorderqty>0</minreorderqty> <noninventory>false</noninventory> <primarylocation/> <reorderpoint>0</reorderpoint> <rep>AP</rep> <type>Memory </type> <updateddate>2/4/2022 2:22:51 PM</updateddate> <warehouse>MAIN</warehouse> </item> </ArrayOfitem>
现有API请求代码
当前用于循环请求API的Python代码:
import http.client import xml.etree.ElementTree as etree pn_list = ["samplepart1", "samplepart2"] api_key = "**redacted lol**" def getMFGR(): global raw_xml for part_number in pn_list: conn = http.client.HTTPSConnection("api.website.com") payload = '' headers = { 'session-token': api_key, # 原代码误写为字符串'api_key',此处修正为变量 'Cookie': 'firstpartofmycookie; secondpartofmycookie' } conn.request("GET", f"/webapi.svc/MI/XML/GetItemsByItemNumber?ItemNumber={part_number}", payload, headers) res = conn.getresponse() data = res.read() raw_xml = data.decode("utf-8") print(raw_xml) print() getMFGR()
遇到的解析错误
尝试的解析代码放入循环后出现列表索引越界错误,核心原因是XML路径定位错误:<mfgr>元素并非直接在根节点<ArrayOfitem>下,而是嵌套在<item>节点内,且未正确遍历层级。
root = etree.fromstring(raw_xml) my_ns = {'root': 'WhereDataComesFrom.com'} mfgr = root.findall('root:mfgr', my_ns)[0].text # 错误路径:根节点下无直接的mfgr元素
修正后的完整解决方案
以下是整合请求与解析逻辑的代码,解决命名空间定位问题并生成目标字典:
import http.client import xml.etree.ElementTree as etree pn_list = ["samplepart1", "samplepart2"] api_key = "**redacted lol**" part_manufacturer_dict = {} # 存储最终结果的字典 NS = {'ns': 'WhereDataComesFrom.com'} # 定义命名空间别名 def get_mfgr_for_parts(): for part_number in pn_list: conn = http.client.HTTPSConnection("api.website.com") payload = '' headers = { 'session-token': api_key, 'Cookie': 'firstpartofmycookie; secondpartofmycookie' } # 用f-string拼接URL更简洁易读 url = f"/webapi.svc/MI/XML/GetItemsByItemNumber?ItemNumber={part_number}" conn.request("GET", url, payload, headers) res = conn.getresponse() data = res.read().decode("utf-8") # 解析XML root = etree.fromstring(data) # 按层级定位mfgr:先找item节点,再在其下找mfgr mfgr_element = root.find('ns:item/ns:mfgr', NS) # 处理元素不存在的情况,避免索引越界 if mfgr_element is not None and mfgr_element.text is not None: part_manufacturer_dict[part_number] = mfgr_element.text.strip() else: part_manufacturer_dict[part_number] = "Unknown Manufacturer" # 也可根据需求设为None # 输出最终字典 print(part_manufacturer_dict) get_mfgr_for_parts()
关键修正点:
- 命名空间路径修正:使用
ns:item/ns:mfgr的层级路径,正确定位嵌套在<item>下的<mfgr>元素 - 避免索引越界:改用
find()而非findall()[0],直接返回单个元素,通过判断元素是否存在处理异常情况 - 代码规范优化:移除全局变量
raw_xml,改用字典直接存储结果;修正原代码中session-token值的错误;用f-string拼接URL提升可读性 - 文本处理:用
strip()去除<mfgr>文本可能存在的多余空格
内容的提问来源于stack exchange,提问作者Wes Graham
相关产品推荐
相关产品推荐

