如何从XML或TCX文件中提取数据系列

6

我希望用Python处理.tc文件(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等工具从标记数据(如瓦特... /瓦特)中制作列表。但是我对这些工具的使用还是很新手。请问如何使用Python获取XML文件中标签之间的数据?

3个回答

2
您可以使用 lxml 模块以及 XPath 来处理相关的XML/HTML技术。 lxml 可以很好地解析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 = ...”标签会引起问题。你能测试一下吗? - Young Dong Kwon

2

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

请注意,最后一个Watts节点是一个特殊的、较长的XPath,因为在示例XML中未注册特殊命名空间xlmns

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']]

你的解决方案是我想要的!但它不起作用。错误信息如下。File "xml2obj.py", line 15, in <module> with open(os.path.join(cd,'trackData.csv'), 'w', newline='') as m: TypeError: 对于此函数,'newline' 是无效的关键字参数。 - Young Dong Kwon
这是一个Python 3的解决方案。你可能正在使用Python 2.7,它在open()函数中不接受newline作为参数。只需将其删除即可。请参阅我的编辑。 - Parfait

0
Python程序https://github.com/cast42/vpower/blob/master/vpower.py遍历命令行指定的TCX文件,并为所有骑行活动的测量值添加功率字段。它使用lxml库来提高速度并处理命名空间。在此程序的先前版本中,我使用了xml.etree.ElementTree,但遇到了命名空间问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接