2009-11-23 5 views
55

Es fällt mir schwer, ein gutes, grundlegendes Beispiel für das Parsen von XML in Python mit dem Elementbaum zu finden. Von dem, was ich finden kann, scheint dies die einfachste Bibliothek für die Analyse von XML zu sein. Hier ist ein Beispiel der XML mit Ich arbeite:Parsing von XML in Python mit ElementTree Beispiel

<timeSeriesResponse> 
    <queryInfo> 
     <locationParam>01474500</locationParam> 
     <variableParam>99988</variableParam> 
     <timeParam> 
      <beginDateTime>2009-09-24T15:15:55.271</beginDateTime> 
      <endDateTime>2009-11-23T15:15:55.271</endDateTime> 
     </timeParam> 
    </queryInfo> 
    <timeSeries name="NWIS Time Series Instantaneous Values"> 
     <values count="2876"> 
      <value dateTime="2009-09-24T15:30:00.000-04:00" qualifiers="P">550</value> 
      <value dateTime="2009-09-24T16:00:00.000-04:00" qualifiers="P">419</value> 
      <value dateTime="2009-09-24T16:30:00.000-04:00" qualifiers="P">370</value> 
      ..... 
     </values> 
    </timeSeries> 
</timeSeriesResponse> 

Ich bin in der Lage zu tun, was ich brauche, eine hartcodierte Methode. Aber ich brauche meinen Code etwas dynamischer. Hier ist, was funktioniert hat:

tree = ET.parse(sample.xml) 
doc = tree.getroot() 

timeseries = doc[1] 
values = timeseries[2] 

print child.attrib['dateTime'], child.text 
#prints 2009-09-24T15:30:00.000-04:00, 550 

Hier sind ein paar Dinge, die ich versucht habe, keiner von ihnen arbeitete, berichten, dass sie nicht Zeitreihen finden konnten (oder etwas anderes habe ich versucht):

tree = ET.parse(sample.xml) 
tree.find('timeSeries') 

tree = ET.parse(sample.xml) 
doc = tree.getroot() 
doc.find('timeSeries') 

Grundsätzlich möchte ich die XML-Datei laden, nach dem timeSeries-Tag suchen und die value-Tags durchlaufen, wobei dateTime und der Wert des Tags selbst zurückgegeben werden. alles, was ich im obigen Beispiel mache, aber nicht hart, die Abschnitte von XML, an denen ich interessiert bin, zu kodieren. Kann mir jemand auf einige Beispiele hinweisen oder mir einige Vorschläge geben, wie ich das durcharbeiten soll?


Vielen Dank für die Hilfe. Bei der Verwendung der beiden unten aufgeführten Vorschläge für die von mir bereitgestellte Beispieldatei wurde jedoch nicht an der vollständigen Datei gearbeitet. Hier ist der Fehler, den ich aus der realen Datei, wenn ich Ed Carrel Methode verwenden:

(<type 'exceptions.AttributeError'>, AttributeError("'NoneType' object has no attribute 'attrib'",), <traceback object at 0x011EFB70>) 

Ich dachte, es war etwas in der realen Datei ihm nicht gefallen, so dass ich inkrementell Dinge entfernt, bis es funktionierte. Hier sind die Linien, die ich geändert:

originally: <timeSeriesResponse xsi:schemaLocation="a URL I removed" xmlns="a URL I removed" xmlns:xsi="a URL I removed"> 
changed to: <timeSeriesResponse> 

originally: <sourceInfo xsi:type="SiteInfoType"> 
changed to: <sourceInfo> 

originally: <geogLocation xsi:type="LatLonPointType" srs="EPSG:4326"> 
changed to: <geogLocation> 

die Attribute entfernen, in denen ‚xsi: ...‘ das Problem behoben. Ist das 'xsi: ...' kein gültiges XML? Es wird schwer für mich sein, diese programmatisch zu entfernen. Irgendwelche vorgeschlagenen Arbeitsumgebungen?

Hier ist die vollständige XML-Datei: http://www.sendspace.com/file/lofcpt


Als ich ursprünglich diese Frage gestellt, ich war von Namespaces in XML nicht bewusst. Nun, da ich weiß, was passiert, muss ich die "xsi" -Attribute, die die Namespace-Deklarationen sind, nicht entfernen. Ich füge sie nur in meine XPath-Suchen ein. Weitere Informationen zu Namespaces in Lxml finden Sie unter this page.

+0

Könnte ich vorschlagen, dass Sie das 'etree jathanism

+0

Ich ging mit lxml, da es ein wenig einfacher war, mit zu arbeiten, aber ich habe immer noch das oben skizzierte Problem. Für eine Problemumgehung scanne ich vorher die XML-Datei und entferne alle Instanzen von "xsi: type". Die in den Antworten unten beschriebenen Methoden funktionieren dann gut. – Casey

Antwort

40

So habe ich ElementTree 1.2.6 auf meine Box jetzt und lief den folgenden Code für das XML-Chunk Sie auf dem Laufenden:

import elementtree.ElementTree as ET 

tree = ET.parse("test.xml") 
doc = tree.getroot() 
thingy = doc.find('timeSeries') 

print thingy.attrib 

und bekam folgende zurück:

{'name': 'NWIS Time Series Instantaneous Values'} 

Es scheint, das timeSeries-Element gefunden haben, ohne numerische Indizes verwenden zu müssen.

Was jetzt nützlich wäre, ist zu wissen, was Sie meinen, wenn Sie sagen "es funktioniert nicht." Da es bei gleicher Eingabe für mich funktioniert, ist es unwahrscheinlich, dass ElementTree auf eine offensichtliche Weise unterbrochen wird. Aktualisieren Sie Ihre Frage mit Fehlermeldungen, Rückverfolgungen oder anderen Informationen, die Sie uns zur Verfügung stellen können.

+28

Für die neuen Python-Versionen hat sich der Import geändert zu: import xml.etree.ElementTree als ET – Louis

+0

@Louis: was meinst du mit 'den neuen Python-Versionen'? –

+0

@Monica Heddneck: Da dieser Kommentar über sechs Jahre alt ist, sollte ich sagen, dass jeder Python über 2,3 ... – Louis

18

Wenn ich verstehe Ihre Frage richtig:

for elem in doc.findall('timeSeries/values/value'): 
    print elem.get('dateTime'), elem.text 

oder wenn Sie bevorzugen (und wenn es nur ein Vorkommen von timeSeries/values ist:

values = doc.find('timeSeries/values') 
for value in values: 
    print value.get('dateTime'), elem.text 

Die findall() Methode gibt eine Liste aller passenden Elemente , während find() nur das erste übereinstimmende Element zurückgibt.Das erste Beispiel führt eine Schleife über alle gefundenen Elemente, die zweite Schleife über die untergeordneten Elemente des Elements values, in diesem Fall zu demselben Ergebnis.

Ich sehe nicht, wo das Problem mit nicht finden timeSeries kommt jedoch von. Vielleicht hast du gerade den Anruf getroot() vergessen? (Beachten Sie, dass Sie es nicht wirklich brauchen, weil Sie auch vom elementtree selbst arbeiten können, wenn Sie den Pfadausdruck ändern, zum Beispiel /timeSeriesResponse/timeSeries/values oder //timeSeries/values)

+0

Es funktioniert super. Ich habe es mit dem Modul 'from lxml import etree' verwendet. 'doc = etree.parse ('test.xml')' –