2

我有这个包含很多A元素的简化 xml:

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

但是这段代码的问题是由于某种原因比较总是返回falseres ,所以总是为的。

任何帮助或建议表示赞赏。

4

3 回答 3

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

一旦您总是比较具有相同偏移量的日期并且您具有相同数量的数字,因为您的日期采用 iso8601 格式和 yyyy-mm-dd 格式,因此比较可以安全地进行比较偏移量或位数,那么您将不得不将其作为日期时间对象进行比较。

于 2016-05-06T10:34:22.840 回答
1

xpath 1.0 中没有日期类型,您无法将 xpath 1.0 中的字符串与=and以外的运算符进行比较!=。你有一个包,它支持 python 中的 xpath 2 的一部分,但我从未尝试过(见这里)。这可能是一条路要走。

于 2016-05-06T10:17:42.000 回答
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)
于 2016-05-06T10:27:38.723 回答