如何从 xml 或 tcx 文件中获取数据系列

Posted

技术标签:

【中文标题】如何从 xml 或 tcx 文件中获取数据系列【英文标题】:How can I grab data series from xml or tcx file 【发布时间】:2015-12-06 20:32:00 【问题描述】:

我想用 Python 处理特定标签之间的 .tcx 文件(xml 形式)中的数据。 文件格式如下。

 <Track>
      <Trackpoint>
        <Time>2015-08-29T22:04:39.000Z</Time>
        <Position>
          <LatitudeDegrees>37.198049426078796</LatitudeDegrees>
          <LongitudeDegrees>127.07204628735781</LongitudeDegrees>
        </Position>
        <AltitudeMeters>34.79999923706055</AltitudeMeters>
        <DistanceMeters>7.309999942779541</DistanceMeters>
        <HeartRateBpm>
          <Value>102</Value>
        </HeartRateBpm>
        <Cadence>76</Cadence>
        <Extensions>
          <TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2">
            <Watts>112</Watts>
          </TPX>
        </Extensions>
      </Trackpoint>
....Lots of <Trackpoint> ... </Trackpoint>
</Track>

最终,我将制作包含“纬度、海拔、...瓦特”列的数据表。 首先,我尝试使用 BeautifulSoup、xpath 等从标记数据(如 Watts ... /Watts)中创建一个列表。 但我是处理这些工具的新手。 如何使用 Python 在 xml 文件中的标签之间抓取数据?

【问题讨论】:

【参考方案1】:

您可以使用lxml 模块和XPathlxml 非常适合解析 XML/html、遍历元素树和返回元素文本/属性。您可以使用XPath 选择特定元素、元素集或元素属性。使用您的示例数据:

content = '''
<Track>
      <Trackpoint>
        <Time>2015-08-29T22:04:39.000Z</Time>
        <Position>
          <LatitudeDegrees>37.198049426078796</LatitudeDegrees>
          <LongitudeDegrees>127.07204628735781</LongitudeDegrees>
        </Position>
        <AltitudeMeters>34.79999923706055</AltitudeMeters>
        <DistanceMeters>7.309999942779541</DistanceMeters>
        <HeartRateBpm>
          <Value>102</Value>
        </HeartRateBpm>
        <Cadence>76</Cadence>
        <Extensions>
          <TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2">
            <Watts>112</Watts>
          </TPX>
        </Extensions>
      </Trackpoint>
....Lots of <Trackpoint> ... </Trackpoint>
</Track>
'''

from lxml import etree

tree = etree.XML(content)
time = tree.xpath('Trackpoint/Time/text()')

print(time)

输出

['2015-08-29T22:04:39.000Z']

【讨论】:

感谢您提供简单的解决方案。我得到了除瓦特以外的其他数据。也许 TPX "xmlns=..." 标签会导致问题。你能测试一下吗?【参考方案2】:

您甚至可以使用 lxml 模块将 XML 转换为 CSV(以便稍后导入数据框、电子表格或数据库表),并使用跨各种 XPath 的迭代 Python 列表。

注意最后一个 Watts 节点是一个特殊的、更长的 XPath,因为它转义了特殊的命名空间,xlmns 未在示例 XML 中注册。

import os, csv
import lxml.etree as ET

# SET DIRECTORY
cd = os.path.dirname(os.path.abspath(__file__))

# LOAD XML FILE
xmlfile = 'trackXML.xml'
dom = ET.parse(os.path.join(cd, xmlfile))

# DEFINING COLUMNS
columns = ['latitude', 'longitude', 'altitude', 'distance', 'watts']

# OPEN CSV FILE
with open(os.path.join(cd,'trackData.csv'), 'w') as m:
    writer = csv.writer(m)    
    writer.writerow(columns)

    nodexpath = dom.xpath('//Trackpoint')

    dataline = []   # FOR ONE-ROW CSV APPENDS
    datalines = []  # FOR FINAL OUTPUT 
    for j in range(1,len(nodexpath)+1):        
        dataline = []

        # LOCATE PATH OF EACH NODE VALUE
        latitudexpath = dom.xpath('//Trackpoint[0]/Position/LatitudeDegrees/text()'.format(j))
        dataline.append('') if latitudexpath == [] else dataline.append(latitudexpath[0])

        longitudexpath = dom.xpath('//Trackpoint[0]/Position/LongitudeDegrees/text()'.format(j))
        dataline.append('') if longitudexpath == [] else dataline.append(longitudexpath[0])

        altitudexpath = dom.xpath('//Trackpoint[0]/AltitudeMeters/text()'.format(j))
        dataline.append('') if altitudexpath == [] else dataline.append(altitudexpath[0])

        distancexpath = dom.xpath('//Trackpoint[0]/DistanceMeters/text()'.format(j))
        dataline.append('') if distancexpath == [] else dataline.append(distancexpath[0])

        wattsxpath = dom.xpath("//Trackpoint[0]/*[name()='Extensions']/*[name()='TPX']/*[name()='Watts']/text()".format(j))
        dataline.append('') if wattsxpath == [] else dataline.append(wattsxpath[0])

        datalines.append(dataline)
        writer.writerow(dataline)

print(datalines)

除了 CSV 文件,下面是选定列的数据线列表输出:

[['37.198049426078796', '127.07204628735781', '34.79999923706055', '7.309999942779541', '112']]

【讨论】:

你的解决方案就是我想要的!但它不起作用。错误信息是这样的。文件“xml2obj.py”,第 15 行,在 中,open(os.path.join(cd,'trackData.csv'), 'w', newline='') as m: TypeError: 'newline' is此函数的关键字参数无效 这是一个 Python 3 解决方案。您可能正在使用不将 newline 作为 open() 函数中的参数的 Python 2.7。只需将其删除。查看我的编辑。【参考方案3】:

Python 程序https://github.com/cast42/vpower/blob/master/vpower.py 迭代在命令行中指定的 TCX 文件,并为所有骑行活动的测量添加一个功率场。 它使用lxml 库来提高速度,因为它处理命名空间。在该程序的早期版本中,我使用了 xml.etree.ElementTree,但遇到了命名空间问题。

【讨论】:

以上是关于如何从 xml 或 tcx 文件中获取数据系列的主要内容,如果未能解决你的问题,请参考以下文章

如何仅从系列或列表中获取特定值[关闭]

从组合框中选择项目时,从 xml 文件中获取数据到文本框。如何做到这一点?

如何从存储在我的 PC 上的文件中获取 XML 数据并使用 javascript 填充 HTML 表格?

如何从 XML 文件中获取作为搜索条件结果的参数? [复制]

如何从 XML 文件中按编号获取子节点

如何从 php 中列出的数组中获取 xml 输出?