如何使用 Python 将数组值附加到 xml 文件属性?
How to append xml file attribute with array value using Python?
我有一个 xml 文件。
<?xml version='1.0' encoding='utf-8'?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string" />
<value type="None" />
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string" />
<value type="None" />
</id>
</process>
</systemdata>
我想将此数组附加到上面的 XML 文件中。
memorys = []
for mem in wmiquery.Win32_PhysicalMemory():
sysmem = {}
sysmem['location'] = mem.DeviceLocator
sysmem['banklabel'] = mem.BankLabel
sysmem['cap'] = mem.Capacity
memorys.append(sysmem)
for m in memorys:
print(m)
m
的值是这样的:
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '8589934592'}
{'location': 'DIMM2', 'banklabel': 'ChannelA', 'cap': '8589934592'}
我想将这些数组附加到我的 XML。所以我的期望基于上面的数组,我将追加 2 个新元素。如果数组有 4,则创建新的 4 元素。
这是我的预期输出:
<?xml version='1.0' encoding='utf-8'?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string" />
<value type="None" />
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string" />
<value type="None" />
</id>
</process>
<!-- memory -->
<unitmemory>
<!-- data -->
<module location="DIMM1">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">8589934592</value>
</cap>
</module>
<module location="DIMM2">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">8589934592</value>
</cap>
</module>
</unitmemory>
</systemdata>
任何人都可以给我任何想法吗?
有几种方法可以实现它,但我个人更喜欢这种方法:
from lxml import etree
sd = """your xml above"""
memos = [[{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '8589934592'}],
[{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '123456'}]]
#I changed the second list a bit just to make the example clearer
doc = etree.XML(sd.encode())
destination = doc.xpath('//process')[0]
parent = """<unitmemory>"""
for mem in memos:
attr_vals = [list(m.values()) for m in mem][0]
new_child = f"""<module location="{attr_vals[0]}">
<banklabel tool="banklabel">
<value type="string">{attr_vals[1]}</value>
</banklabel>
<cap tool="cap">
<value type="string">{attr_vals[2]}</value>
</cap>
</module>"""
parent+=new_child
parent += """</unitmemory>"""
new_node = etree.fromstring(parent)
destination.addnext(new_node)
print(etree.tostring(doc).decode())
输出是您的预期输出。
Jack 的方法似乎更简单,这是另一种方法,包括您需要的评论:
- 使用解析器读取您的文件以保留注释
- 使用
ET.Comment()
插入评论
- 遍历字典列表并将子元素添加到 xml
- 使用
toprettyxml()
将 xml 转换为格式化字符串,但这会添加不必要的换行符
- 使用列表推导删除多余的换行符和
strip()
- 将编码信息添加到 xml 声明
- 写入原始文件
import xml.etree.ElementTree as ET
import xml.dom.minidom
memorys = [
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '100'},
{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '200'}
]
m_encoding = 'utf-8'
parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True))
tree = ET.parse('sampleXml.xml', parser=parser)
root = tree.getroot()
root.insert(1, ET.Comment('memory'))
unit_mem = ET.SubElement(root, 'unitmemory')
unit_mem.insert(0, ET.Comment('data'))
for mem in memorys:
m_module = ET.SubElement(unit_mem, 'module ')
m_module.set('location', mem['location'])
b_label = ET.SubElement(m_module, 'banklabel ')
m_cap = ET.SubElement(m_module, 'cap ')
b_value = ET.SubElement(b_label, 'value ')
c_value = ET.SubElement(m_cap, 'value ')
m_module.set('location', mem['location'])
b_label.set('tool', 'banklabel')
m_cap.set('tool', 'cap')
b_value.set('type', 'string')
c_value.set('type', 'string')
b_value.text = mem['banklabel']
c_value.text = mem['cap']
dom = xml.dom.minidom.parseString(ET.tostring(root))
xml_string = dom.toprettyxml()
xml_string = '\n'.join([line for line in xml_string.splitlines() if line.strip()])
part1, part2 = xml_string.split('?>')
with open("sampleXml.xml", 'w') as xfile:
xfile.write(part1 + 'encoding=\"{}\"?>\n'.format(m_encoding) + part2)
xfile.close()
我的输入
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '100'}
{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '200'}
我的输出
<?xml version="1.0" encoding="utf-8"?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string"/>
<value type="None"/>
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string"/>
<value type="None"/>
</id>
</process>
<!--memory-->
<unitmemory>
<!--data-->
<module location="DIMM1">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">100</value>
</cap>
</module>
<module location="DIMM2">
<banklabel tool="banklabel">
<value type="string">ChannelB</value>
</banklabel>
<cap tool="cap">
<value type="string">200</value>
</cap>
</module>
</unitmemory>
</systemdata>
我有一个 xml 文件。
<?xml version='1.0' encoding='utf-8'?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string" />
<value type="None" />
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string" />
<value type="None" />
</id>
</process>
</systemdata>
我想将此数组附加到上面的 XML 文件中。
memorys = []
for mem in wmiquery.Win32_PhysicalMemory():
sysmem = {}
sysmem['location'] = mem.DeviceLocator
sysmem['banklabel'] = mem.BankLabel
sysmem['cap'] = mem.Capacity
memorys.append(sysmem)
for m in memorys:
print(m)
m
的值是这样的:
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '8589934592'}
{'location': 'DIMM2', 'banklabel': 'ChannelA', 'cap': '8589934592'}
我想将这些数组附加到我的 XML。所以我的期望基于上面的数组,我将追加 2 个新元素。如果数组有 4,则创建新的 4 元素。 这是我的预期输出:
<?xml version='1.0' encoding='utf-8'?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string" />
<value type="None" />
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string" />
<value type="None" />
</id>
</process>
<!-- memory -->
<unitmemory>
<!-- data -->
<module location="DIMM1">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">8589934592</value>
</cap>
</module>
<module location="DIMM2">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">8589934592</value>
</cap>
</module>
</unitmemory>
</systemdata>
任何人都可以给我任何想法吗?
有几种方法可以实现它,但我个人更喜欢这种方法:
from lxml import etree
sd = """your xml above"""
memos = [[{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '8589934592'}],
[{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '123456'}]]
#I changed the second list a bit just to make the example clearer
doc = etree.XML(sd.encode())
destination = doc.xpath('//process')[0]
parent = """<unitmemory>"""
for mem in memos:
attr_vals = [list(m.values()) for m in mem][0]
new_child = f"""<module location="{attr_vals[0]}">
<banklabel tool="banklabel">
<value type="string">{attr_vals[1]}</value>
</banklabel>
<cap tool="cap">
<value type="string">{attr_vals[2]}</value>
</cap>
</module>"""
parent+=new_child
parent += """</unitmemory>"""
new_node = etree.fromstring(parent)
destination.addnext(new_node)
print(etree.tostring(doc).decode())
输出是您的预期输出。
Jack 的方法似乎更简单,这是另一种方法,包括您需要的评论:
- 使用解析器读取您的文件以保留注释
- 使用
ET.Comment()
插入评论
- 遍历字典列表并将子元素添加到 xml
- 使用
toprettyxml()
将 xml 转换为格式化字符串,但这会添加不必要的换行符 - 使用列表推导删除多余的换行符和
strip()
- 将编码信息添加到 xml 声明
- 写入原始文件
import xml.etree.ElementTree as ET
import xml.dom.minidom
memorys = [
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '100'},
{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '200'}
]
m_encoding = 'utf-8'
parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True))
tree = ET.parse('sampleXml.xml', parser=parser)
root = tree.getroot()
root.insert(1, ET.Comment('memory'))
unit_mem = ET.SubElement(root, 'unitmemory')
unit_mem.insert(0, ET.Comment('data'))
for mem in memorys:
m_module = ET.SubElement(unit_mem, 'module ')
m_module.set('location', mem['location'])
b_label = ET.SubElement(m_module, 'banklabel ')
m_cap = ET.SubElement(m_module, 'cap ')
b_value = ET.SubElement(b_label, 'value ')
c_value = ET.SubElement(m_cap, 'value ')
m_module.set('location', mem['location'])
b_label.set('tool', 'banklabel')
m_cap.set('tool', 'cap')
b_value.set('type', 'string')
c_value.set('type', 'string')
b_value.text = mem['banklabel']
c_value.text = mem['cap']
dom = xml.dom.minidom.parseString(ET.tostring(root))
xml_string = dom.toprettyxml()
xml_string = '\n'.join([line for line in xml_string.splitlines() if line.strip()])
part1, part2 = xml_string.split('?>')
with open("sampleXml.xml", 'w') as xfile:
xfile.write(part1 + 'encoding=\"{}\"?>\n'.format(m_encoding) + part2)
xfile.close()
我的输入
{'location': 'DIMM1', 'banklabel': 'ChannelA', 'cap': '100'}
{'location': 'DIMM2', 'banklabel': 'ChannelB', 'cap': '200'}
我的输出
<?xml version="1.0" encoding="utf-8"?>
<systemdata>
<process>
<number code="hsfg" class="hgdgf" tool="gagfa">
<value type="string"/>
<value type="None"/>
</number>
<!-- ID -->
<id code="hsfg" class="gfdg" tool="fadg">
<value type="string"/>
<value type="None"/>
</id>
</process>
<!--memory-->
<unitmemory>
<!--data-->
<module location="DIMM1">
<banklabel tool="banklabel">
<value type="string">ChannelA</value>
</banklabel>
<cap tool="cap">
<value type="string">100</value>
</cap>
</module>
<module location="DIMM2">
<banklabel tool="banklabel">
<value type="string">ChannelB</value>
</banklabel>
<cap tool="cap">
<value type="string">200</value>
</cap>
</module>
</unitmemory>
</systemdata>