python - open - xml etree elementtree example
¿Cómo puedo tomar series de datos del archivo xml o tcx? (3)
Quiero tratar los datos del archivo .tcx (formato xml) entre etiquetas específicas con Python.
El formato de archivo es como sigue.
<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>
Eventualmente, haré una tabla de Datos con columnas de ''Lattitude, Altitude, ... Watts''.
Primero traté de hacer una lista a partir de datos modificados (como Watts ... / Watts) con BeautifulSoup, xpath, etc. Pero soy un novato para manejar estas herramientas. ¿Cómo puedo obtener datos entre las etiquetas en un archivo xml con Python?
Puede usar el módulo lxml
, junto con XPath
. lxml
es bueno para analizar XML / HTML, recorrer árboles de elementos y devolver texto / atributos de elementos. Puede seleccionar elementos particulares, conjuntos de elementos o atributos de elementos usando XPath
. Usando sus datos de ejemplo:
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)
Salida
[''2015-08-29T22:04:39.000Z'']
Incluso puede usar el módulo lxml
para convertir XML a CSV (para una posterior importación en un dataframe, hoja de cálculo o tabla de base de datos) utilizando una lista iterada de Python en varios XPaths.
Observe que el último nodo de Watts
es un XPath especial y más largo debido al escape del espacio de nombres especial, xlmns
no registrado en XML de muestra.
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)
Además del archivo CSV, a continuación se muestra el resultado de la lista de datos de las columnas seleccionadas:
[[''37.198049426078796'', ''127.07204628735781'', ''34.79999923706055'', ''7.309999942779541'', ''112'']]
El programa Python https://github.com/cast42/vpower/blob/master/vpower.py itera sobre el archivo TCX especificado en la línea de comando y agrega un campo de potencia para todas las mediciones de la actividad de ciclismo. Utiliza la biblioteca lxml para la velocidad y porque trata con espacios de nombres. En versiones anteriores de este programa utilicé xml.etree.ElementTree pero encontré problemas con los espacios de nombres.