2016-05-06 95 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

谢谢,但这是一个缓慢的方式做事 –