转换XML到JSON前如何移除XML命名空间属性?
移除XML命名空间后转换为JSON
我在将XML文件转换为JSON时,发现XML中的命名空间属性(比如xmlns:xsi和xsi:nil)会被带入生成的JSON文件中,希望在转换前移除这些命名空间相关内容。
原始XML代码
<exta> <sure>This </signature> <begin_date>2019-07-12T09:41:48.187</begin_date> <ver>4</ver> <maiden_bc>1549</maiden_bc> <exta_id>12345</exta_id> <nps_max_price xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <exta_id>72723</exta_id> <extended_datetime>2018-11-20T11:01:29.040</extended_datetime> <event_ind>E</event_ind> <maiden>12345</maiden> <patient_id>123</patient_id> <boss_id>123LHF</boss_id> <template_name /> <end_date>2019-01-01T00:00:00</end_date> <UYI_AMN xsi:nil="true" /> <dedt_bef_ATS xsi:nil="true" /> <form>W</form> </exta>
期望处理后的XML代码
<exta> <sure>This </signature> <begin_date>2019-07-12T09:41:48.187</begin_date> <ver>4</ver> <maiden_bc>1549</maiden_bc> <exta_id>12345</exta_id> <nps_max_price> <exta_id>72723</exta_id> <extended_datetime>2018-11-20T11:01:29.040</extended_datetime> <event_ind>E</event_ind> <maiden>12345</maiden> <patient_id>123</patient_id> <boss_id>123LHF</boss_id> <template_name /> <end_date>2019-01-01T00:00:00</end_date> <UYI_AMN/> <dedt_bef_ATS/> <form>W</form> </exta>
当前Python转换代码
for datafile in bucket.objects.filter(Prefix="test/"): if "xml" in datafile.key: # converting xml to json xml_file = datafile.get()['Body'] print(datafile.get()['Body']) tree = ET.parse(xml_file) xml_data = tree.getroot() xmlstr = ET.tostring(xml_data, encoding='utf-8', method='xml') data_dict = dict(xmltodict.parse(xmlstr, attr_prifix='')) json_data = json.dumps(data_dict)
解决方案
方法一:遍历XML节点移除命名空间属性
通过ElementTree遍历所有节点,移除包含命名空间前缀的属性,同时清理xsi:nil标记,生成符合期望的XML后再转换为JSON。
修改后的代码:
import xml.etree.ElementTree as ET import xmltodict import json for datafile in bucket.objects.filter(Prefix="test/"): if "xml" in datafile.key: xml_file = datafile.get()['Body'] tree = ET.parse(xml_file) root = tree.getroot() # 定义需要移除的命名空间属性前缀 ns_prefixes = ('xmlns:', 'xsi:') # 递归遍历所有节点,清理命名空间属性 def clean_ns(node): # 移除当前节点的命名空间相关属性 attrs_to_delete = [key for key in node.attrib if key.startswith(ns_prefixes)] for key in attrs_to_delete: del node.attrib[key] # 处理子节点 for child in node: clean_ns(child) clean_ns(root) # 转换为XML字符串并解析为JSON xmlstr = ET.tostring(root, encoding='utf-8', method='xml') data_dict = xmltodict.parse(xmlstr, attr_prefix='') json_data = json.dumps(data_dict)
方法二:解析时直接过滤属性(简化版)
如果不需要保留处理后的XML文件,可在xmltodict解析过程中直接过滤命名空间属性,省去ElementTree遍历步骤。
修改后的代码:
import xmltodict import json for datafile in bucket.objects.filter(Prefix="test/"): if "xml" in datafile.key: xml_content = datafile.get()['Body'].read().decode('utf-8') # 自定义处理函数,过滤命名空间属性 def process_node(node): # 移除命名空间相关属性 if '@' in node: node['@'] = {k: v for k, v in node['@'].items() if not k.startswith(('xmlns:', 'xsi:'))} # 处理xsi:nil标记,转为空值 if '@xsi:nil' in node: node['#text'] = None del node['@xsi:nil'] return node data_dict = xmltodict.parse( xml_content, attr_prefix='', postprocessor=process_node ) json_data = json.dumps(data_dict)
说明
- 方法一适合需要先得到清理后的XML文件的场景,完全匹配期望的XML格式。
- 方法二更高效,直接在解析为字典的过程中处理属性,仅保留最终JSON结果时优先使用。
内容的提问来源于stack exchange,提问作者Sarath
相关产品推荐
相关产品推荐

