首页 > 解决方案 > 使用 Python 实时解析 XML 字符串

问题描述

我正在尝试使用 TCP 服务器-客户端 API 实现对来自眼动仪的 XML 字符串的实时解析,用于:1)将它们存储为 .csv 或其他格式以进行离线分析。2)在屏幕上显示注视坐标。

一小部分 xml 字符串示例如下所示:

    <REC FPOGX="0.68449" FPOGY="0.81953" FPOGS="1789.73828" FPOGD="0.77747" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />
    <REC FPOGX="0.68449" FPOGY="0.81953" FPOGS="1789.73828" FPOGD="0.77747" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />
    <REC FPOGX="0.68449" FPOGY="0.81953" FPOGS="1789.73828" FPOGD="0.77747" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />
    <REC FPOGX="0.68405" FPOGY="0.81942" FPOGS="1789.73828" FPOGD="0.80640" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />
    <REC FPOGX="0.68405" FPOGY="0.81942" FPOGS="1789.73828" FPOGD="0.80640" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />
    <REC FPOGX="0.68405" FPOGY="0.81942" FPOGS="1789.73828" FPOGD="0.80640" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />

眼动仪每 6.6 毫秒发送一个样本(如上图)。我看过的大部分内容都是获取静态 xml 文件并进行解析。但是,就我而言,我想实时执行此操作,以便我可以读取 X、Y 凝视坐标(例如 FPOGX 和 FPOGY)并将它们显示在屏幕上(为此我将使用实验设计软件)。关于如何做到这一点的任何想法?

非常感谢。

标签: pythonxmlparsing

解决方案


如果您将它作为 xml 字符串接收,您可以简单地ET.fromstring(<xml_string>).attrib为您的数据结构做:

import xml.etree.ElementTree as ET 

def parse_xml(xml_string):
    tree = ET.fromstring(xml_string) # et.parse if you are receiving a file
    return tree.attrib

my_xml = '<REC FPOGX="0.68295" FPOGY="0.82154" FPOGS="1789.73828" FPOGD="0.83740" FPOGID="4894" FPOGV="1" CX="0.95781" CY="0.39074" CS="0" />'

data = parse_xml(my_xml)

print(data)

输出:

{'FPOGX': '0.68295', 'FPOGY': '0.82154', 'FPOGS': '1789.73828', 'FPOGD': '0.83740', 'FPOGID': '4894', 'FPOGV': '1', 'CX': '0.95781', 'CY': '0.39074', 'CS': '0'}

对于 csv 部分,您可以使用此append_csv_dict功能(我使用的标准功能):

def append_csv_dict(path, data):
    '''
    Append a csv with a dictionary keys as column headers
    Args:
        path (str): Path to the csv file
        data (dict or list): Dictionary or list(dict) with keys as 
                             column  headers and values as column data
    '''
    with open(path, 'a') as file:
        # set the field names to the keys of the dictionary or keys of the first item
        fieldnames = list(data.keys()) if isinstance(data, dict) else data[0].keys()
        writer = csv.DictWriter(file, fieldnames=fieldnames, lineterminator='\n')
        # write the header if the file is new
        if file.tell() == 0:
            writer.writeheader()
        if isinstance(data, dict):
            # write the row
            writer.writerow(data)
        elif isinstance(data, list):
            # write the rows if it is a list
            writer.writerows(data)
            
# append 10 times to show how it works
for i in range(10):
    append_csv_dict('./data.csv', data)

输出(数据.csv):

FPOGX,FPOGY,FPOGS,FPOGD,FPOGID,FPOGV,CX,CY,CS
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0
0.68295,0.82154,1789.73828,0.83740,4894,1,0.95781,0.39074,0

推荐阅读