2015-09-10 5 views
6

Ich möchte Daten aus. TCX-Datei (XML-Formular) zwischen bestimmten Tags mit Python behandeln.
Dateiformat ist wie folgt.Wie kann ich Datenserien aus XML oder TCP-Datei greifen

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

Schließlich werde ich Datentabelle mit Spalten von 'Lattitude, Höhe, ... Watts' machen.
Zuerst habe ich versucht, mit BeautifulSoup, xpath usw. eine Liste aus Daten zu erstellen (wie Watts .../Watts). Aber ich bin ein Neuling, der sich mit diesen Werkzeugen beschäftigt. Wie kann ich Daten zwischen Tags in XML-Datei mit Python greifen?

Antwort

2

Sie könnten das Modul lxml zusammen mit XPath verwenden. lxml eignet sich zum Analysieren von XML/HTML, zum Durchlaufen von Elementbäumen und zum Zurückgeben von Elementtext/Attributen. Sie können bestimmte Elemente, Elementsätze oder Attribute von Elementen mit XPath auswählen. Verwenden Sie Ihre Beispieldaten:

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) 

Ausgabe

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

Danke für die einfache Lösung. Ich habe die anderen Daten außer den Watts. Vielleicht verursacht das TPX "xmlns = ..." - Tag ein Problem. Kannst du es testen? –

2

Sie auch lxml Modul XML zu konvertieren CSV (für den späteren Import in ein Datenrahmen, Tabellenkalkulations- oder Datenbanktabelle) unter Verwendung eines iterativen verwenden können Python-Liste über verschiedene XPaths.

Beachten Sie, dass der letzte Watts Knoten ein spezieller, längerer XPath ist, der dem speziellen Namespace xlmns entgeht, der in Beispiel-XML nicht registriert ist.

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) 

Neben CSV-Datei ist unter der Datenleitungen Liste Ausgabe ausgewählter Spalten:

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

Ihre Lösung ist, dass ich will! Aber es funktioniert nicht. Die Fehlermeldung ist so. Datei "xml2obj.py", Zeile 15, in mit geöffnetem (os.path.join (cd, 'trackData.csv'), 'w', newline = '') als m: TypeError: 'newline' ist ein ungültiges Schlüsselwort-Argument für diese Funktion –

+0

Dies ist eine Python 3-Lösung. Möglicherweise verwenden Sie Python 2.7, das 'newline' nicht als Argument in der 'open()' Funktion verwendet. Einfach entfernen. Siehe meine Bearbeitung. – Parfait

0

Die Python-Programm https://github.com/cast42/vpower/blob/master/vpower.py iteriert über die TCX-Datei in der Befehlszeile angegeben und ein Kraftfeld hinzu alle Messungen der Radfahraktivität. Es verwendet die lxml-Bibliothek für Geschwindigkeit und weil es Namespaces behandelt. In früheren Versionen dieses Programms habe ich xml.etree.ElementTree verwendet, hatte aber Probleme mit den Namespaces.

Verwandte Themen