使用Python从XML文档提取数据并写入另一个XML文档

0 投票
2 回答
714 浏览
提问于 2025-04-18 15:53

我尝试了很久想要做到这一点。

基本上,我有一个XML文档,格式如下(里面包含了我需要的信息 - 一些点的ID和坐标):

<root>
    <!-- Title element missing here -->
    <Table>
        <Point>
            <ID>Point1</ID>
            <latitude>numbers</latitude>
            <longitude>numbers</longitude>
        </Point>
    </Table>            <!-- This line should be eliminated -->
    <Table>             <!-- This line should be eliminated -->
        <Point>
            <ID>Point2</ID>
            <latitude>numbers</latitude>
            <longitude>numbers</longitude>
        </Point>
    </Table>
</root>

我需要做的是把这个文档转换成另一种格式(就像我在上面展示的那样,原始的XML文件),而不改变原来的XML文件。

为此,我写了以下代码,但我遇到了瓶颈,可以说是卡住了。我对Python也还比较陌生。

from lxml import etree
import xml.etree.ElementTree as ET
doc=etree.parse('test2.xml')
root=doc.getroot()
elements=root.findall(".//Point")

root=ET.Element('root')
title=ET.SubElement(root,'Title')
title.text="Title"
table=ET.SubElement(root,'Table')
for element in elements:
    point=ET.SubElement(table,'Point')
    elem=ET.SubElement(point,'ID')
    elem.text="Name"
    elem2=ET.SubElement(point,'latitude')
    elem2.text="coords"
    elem3=ET.SubElement(point,'longitude')
    elem3.text="coords"
ET.dump(root)  # using ET.dump just to display the output in the python SHELL

上面的代码在SHELL中给了我以下输出,这正是我需要的。

<root>
    <Title>Title</Title>
    <Table>
        <Point>
            <ID>Name</ID>
            <latitude>coords</latitude>
            <longitude>coords</longitude>
        </Point>
        <Point>
            <ID>Name</ID>
            <latitude>coords</latitude>
            <longitude>coords</longitude>
        </Point>
    </Table>
</root>

我的问题在于,我需要从原始的XML文件中提取IDlatitudelongitude的值,并把整个新文档写入一个新的XML文件中,同时使用pretty_print,这样更容易阅读。我就是搞不明白该怎么做。如果能给我一些建议就太好了。

2 个回答

0

你可以使用 ET.write()xml.dom.minidom 来实现你想要的功能。 (这里假设我们不使用 lxml,只用标准的 Python 的 ElementTree)

下面是对你代码的扩展:

import xml.etree.ElementTree as ET
import xml.dom.minidom
doc=ET.parse('test2.xml')
root=doc.getroot()
elements=root.findall(".//Point")

root=ET.Element('root')
title=ET.SubElement(root,'Title')
title.text="Title"
table=ET.SubElement(root,'Table')
for element in elements:
    point=ET.SubElement(table,'Point')
    elem=ET.SubElement(point,'ID')
    elem.text="Name"
    elem2=ET.SubElement(point,'latitude')
    elem2.text="coords"
    elem3=ET.SubElement(point,'longitude')
    elem3.text="coords"
ET.dump(root)  # using ET.dump just to display the output in the python SHELL

tree = ET.ElementTree(root)
tree.write('test3.xml') # This is enough but not yet pretty-print

# Using xml.dom.minidom to parse the non-pretty file to make it pretty
a = xml.dom.minidom.parse('test3.xml')
pretty_xml_as_string = a.toprettyxml()
with open('test3.xml', 'w') as f:
    f.write(pretty_xml_as_string) # Write again in pretty-print format
0

如果你只是想从原始的XML中复制Point元素,你可以直接这样做:

from copy import deepcopy
for element in elements:
    table.append(deepcopy(element))

如果你想对这些值进行一些操作,你可以遍历这个元素:

point=ET.SubElement(table,'Point')
for subelement in element:
    elem = ET.SubElement(point, subelement.tag)
    if elem.tag == 'ID':
        elem.text = dowhatyouwantwith(subelement.text)
    elif ....

另外,你真的需要同时使用lxml.etreexml.etree吗?为什么不选择其中一个来使用呢?

撰写回答