2016-05-06 14 views
2

Ich habe diese vereinfachen xml mit vielen A Elementen:Python XPath: Daten vergleichen

<root>  
    <A class="a" version="7"> 
     <details> 
      <dates> 
      <status date="2013-04-29T04:16:49.792-04:00">ACCEPTED</status> 
      <status date="2013-08-12T04:08:23.773-04:00">ACCEPTED</status> 
      </dates> 
     </details> 
    </A> 
    <A class="a" version="7"> 
    ... 
</root> 

Wie erhalte ich nur die A Elemente, dass das letzte Statusdatum größer als ein bestimmte Zeitpunkt ist lxml XPath .

Was ich bisher getan habe:

from lxml import etree 
tree = etree.parse("./my.xml") 
root = tree.getroot() 
res = root.xpath("A[./details/dates/status[last()]/@date > '2013-08-12T00:00:0.000-04:00' ]"); 

Aber das Problem mit diesem Code ist, dass der Vergleich liefert immer falsch aus irgendeinem Grunde, so die res ist immer leer.

Jede Hilfe oder Beratung wird geschätzt.

Antwort

2

Sie müssten als Zahlen übersetzen und vergleichen:

In [24]: x = """<root> 
    ....:  <A class="a" version="7"> 
    ....:  <details> 
    ....:   <dates> 
    ....:    <status date="2013-04-29T04:16:49.792-04:00">ACCEPTED</status> 
    ....:    <status date="2013-08-12T04:08:23.773-04:00">ACCEPTED</status> 
    ....:   </dates> 
    ....:  </details> 
    ....:  </A> 
    ....:  <A class="a" version="7"> 
    ....: </root>""" 

In [25]: from lxml import html 


In [26]: xml = html.fromstring(x) 


In [27]: print(xml.xpath("a[translate(./details/dates/status[last()]/@date,'-:T.','') > '201308120000000000400']")) 
[<Element a at 0x7fdb45bc8aa0>] 

es wird in Ordnung sein zu vergleichen, wenn Sie sind immer Daten mit der gleichen Vergleich Offset und Sie haben die gleiche Anzahl an Ziffern wie Ihre Daten im ISO8601-Format mit dem JJJJ-MM-TT-Format, so dass es sicher zu vergleichen ist, wenn Sie verschiedene Offsets oder eine Anzahl von Ziffern haben, dann müssen Sie als Datetime-Objekte vergleichen .

+0

Ich fürchte, das wird nicht funktionieren, wie erwartet, weil Off-Nummer Darstellung in Xpath/lxml (ass Fließkomma). Dies wird "2.01308120408e + 20" sein. Daher muss es ein komplexerer xapth sein (zum Beispiel das Vergleichen des Datums "substring-before (..., 'T')" und als die Zeit. –

1

In Xpath 1.0 gibt es keinen Datumstyp und Sie können Zeichenfolgen in Xpath 1.0 nicht mit anderen Operatoren als = und != vergleichen. Sie haben ein Paket, das einen Teil von XPath 2 in Python unterstützt, aber ich habe es nie probiert (siehe here). Es könnte ein Weg sein.

1

könnten Sie die datutil.parser:

from lxml import etree 
from datetime import datetime 
from dateutil.parser import parse 

a = '''<root>  
    <A class="a" version="7"> 
     <details> 
      <dates> 
      <status date="2013-04-29T04:16:49.792-04:00">ACCEPTED</status> 
      <status date="2013-08-12T04:08:23.773-04:00">ACCEPTED</status> 
      </dates> 
     </details> 
    </A> 
    <A class="b" version="8"> 
     <details> 
      <dates> 
      <status date="2012-04-29T04:16:49.792-04:00">ACCEPTED</status> 
      <status date="2012-08-12T04:08:23.773-04:00">ACCEPTED</status> 
      </dates> 
     </details> 
    </A> 
</root> ''' 

tree = etree.fromstring(a) 

# Set your begin time 
beginTime = parse('2013-08-12T00:00:0.000-04:00') 

# Loop through all A elements 
for A in tree.findall('A'): 
    # Get the last time of the A element 
    timeA = A.find('./details/dates/status[last()]') 

    # Parse the found date into a datetime element 
    date = parse(timeA.get('date')) 

    # Compare the beginTime with the found date 
    if beginTime < date: 

     # Do as you like 
     #print(date) 
+0

Danke, aber das ist ein langsamer Weg, um die Sache zu tun –