You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何提取含XML处理指令的非标准XML中的完整坐标数据?

问题描述

我用Python从非标准XML文件提取坐标数据,部分<coordinates>标签里包含XML处理指令,示例XML如下:

<?xml version="1.0" encoding="UTF-8"?>
<kml>
    <Document>
        <Folder>
            <Placemark id="CAR1">
            <coordinates>
                28.236931382585154893,36.380279408060658852,200<?AtTime 0.000000?>
                28.236862947306430982,36.380324400967296583,200<?AtTime 2.333333?>
                28.236862521767100986,36.380323843439811071,200<?AtTime 2.500000?>
            </coordinates>
                </Placemark>
        <Placemark id="CAR2">
            <coordinates>
                28.236931382585154893,36.380279408060658852,200
                28.236862947306430982,36.380324400967296583,200
                28.236862521767100986,36.380323843439811071,200
            </coordinates>
        </Placemark>
       </Folder>
    </Document>
</kml>

我的测试代码:

from xml.dom import minidom
myFile = "test.xml"
mydoc = minidom.parse(myFile)
items = mydoc.getElementsByTagName('Placemark')
for elem in items:
    print("coordinates ",elem.attributes['id'].value)
    coorTag = elem.getElementsByTagName('coordinates')
    if len(coorTag) > 0:
        for elem in coorTag:
            theData = elem.firstChild.nodeValue
            print(theData)

当前输出:

coordinates  CAR1

                28.236931382585154893,36.380279408060658852,200
coordinates  CAR2

                28.236931382585154893,36.380279408060658852,200
                28.236862947306430982,36.380324400967296583,200
                28.236862521767100986,36.380323843439811071,200

期望输出:

coordinates  CAR1

                28.236931382585154893,36.380279408060658852,200<?AtTime 0.000000?>
                28.236862947306430982,36.380324400967296583,200<?AtTime 2.333333?>
                28.236862521767100986,36.380323843439811071,200<?AtTime 2.500000?>
coordinates  CAR2

                28.236931382585154893,36.380279408060658852,200
                28.236862947306430982,36.380324400967296583,200
                28.236862521767100986,36.380323843439811071,200

请问如何获取包含XML处理指令的<coordinates>标签内的完整坐标数据?这是否是minidom的问题,有没有更合适的Python替代库?


解决方案

1. 修复minidom的处理逻辑

minidom会把XML处理指令(PI)识别为独立节点,而非文本节点的一部分,所以只取firstChild.nodeValue只能拿到第一个文本节点的内容,后续的处理指令和文本节点都会被忽略。

要获取<coordinates>内的完整内容,需要遍历该标签下的所有子节点,根据节点类型拼接内容:

  • 文本节点(nodeType == Node.TEXT_NODE):直接取nodeValue
  • 处理指令节点(nodeType == Node.PROCESSING_INSTRUCTION_NODE):拼接成<?target data?>格式的字符串

修改后的代码:

from xml.dom import minidom
from xml.dom.minidom import Node

myFile = "test.xml"
mydoc = minidom.parse(myFile)
items = mydoc.getElementsByTagName('Placemark')

for elem in items:
    print("coordinates ", elem.attributes['id'].value)
    coorTag = elem.getElementsByTagName('coordinates')
    if len(coorTag) > 0:
        for coor_elem in coorTag:
            full_content = []
            for child in coor_elem.childNodes:
                if child.nodeType == Node.TEXT_NODE:
                    full_content.append(child.nodeValue)
                elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
                    pi_str = f"<?{child.target} {child.data}?>"
                    full_content.append(pi_str)
            print(''.join(full_content))

这段代码会遍历<coordinates>下的所有子节点,将文本和处理指令完整拼接,得到预期结果。

2. 更合适的替代库

如果经常处理这类非标准XML,推荐使用lxml库,它对XML节点的处理更灵活,能直接获取节点原始内容:

安装lxml

pip install lxml

使用lxml的代码示例

from lxml import etree

myFile = "test.xml"
tree = etree.parse(myFile)
placemarks = tree.xpath('//Placemark')

for pm in placemarks:
    pm_id = pm.get('id')
    print(f"coordinates  {pm_id}")
    coor_elem = pm.find('coordinates')
    if coor_elem is not None:
        full_content = etree.tostring(coor_elem, encoding='unicode', method='text')
        print(full_content)

lxml的etree.tostring方法通过method='text'参数,可直接提取节点内的所有内容(包括处理指令),无需手动遍历节点,代码更简洁。

另外,BeautifulSoup也可将XML当作HTML解析处理,但lxml在XML领域的专业性更强。


内容的提问来源于stack exchange,提问作者Peter Lawrence

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:30:54