2016-05-06 98 views
2

我有很多A元素的這種簡化的xml:蟒蛇的XPath:比較日期

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

如何獲得只有那些A元素的最後狀態日期比使用lxml的XPath的特定時間點更大。

我迄今所做的:

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' ]"); 

但這段代碼的問題是比較總是返回出於某種原因,所以res總是

任何幫助或建議表示讚賞。

回答

2

您需要翻譯和比較的數字:

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

會被罰款比較一旦你總是以同樣的比較日期偏移並且您的日期位數等於您的日期採用yyyy-mm-dd格式的iso8601格式,因此可以安全地進行比較,如果您有不同的偏移量或數字位數,那麼您將必須將其作爲日期時間對象進行比較。

+0

我擔心這不會如預期的那樣工作,因爲關閉xpath/lxml(屁點浮點數)表示形式。這將是'2.01308120408e + 20.'因此它需要更復雜的xapth(例如,比較日期'substring-before(...,'T')'和時間。 –

1

xpath 1.0中沒有日期類型,您無法將xpath 1.0中的字符串與=!=以外的其他運算符進行比較。你有一個軟件包支持Python中的xpath 2的一部分,但我從來沒有嘗試過(見here)。這可能是一條路要走。

1

您可以使用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

謝謝,但這是一個緩慢的方式做事 –