XML读取python中文件的最后一个条目

XML读取python中文件的最后一个条目,python,xml,parsing,Python,Xml,Parsing,我想读取xml文件的最后一个条目并获取其值。这是我的xml文件 <TestSuite> <TestCase> <name>tcname1</name> <total>1</total> <totalpass>0</totalpass> <totalfail>0</totalfail> <totalerror>1</t

我想读取xml文件的最后一个条目并获取其值。这是我的xml文件

<TestSuite>
  <TestCase>
    <name>tcname1</name>
    <total>1</total>
    <totalpass>0</totalpass>
    <totalfail>0</totalfail>
    <totalerror>1</totalerror>
  </TestCase>
  <TestCase>
    <name>tcname2</name>
    <total>1</total>
    <totalpass>0</totalpass>
    <totalfail>0</totalfail>
    <totalerror>1</totalerror>
  </TestCase>
</TestSuite>
这适用于xml文件中包含2个或多个testcase标记的xml,但对于仅包含一个testcase标记的文件,此操作失败

Traceback (most recent call last):
  File "HTMLReportGenerationFromXML.py", line 52, in <module>
    tp=doc['TestSuite']['TestCase'][length-1]['totalpass']
KeyError: 4 .
回溯(最近一次呼叫最后一次):
文件“HTMLReportGenerationFromXML.py”,第52行,在
tp=doc['TestSuite']['TestCase'][length-1]['totalpass']
关键错误:4。

因为它不使用计数,而是使用子标记(etc值作为长度)。请帮我解决这个问题。

我为什么不先做他的呢!使用xpath

第一个示例涉及仅使用一个TestCase元素处理xml文件,第二个示例使用其中两个元素。关键点是使用xpath
last
选择器

>>> from lxml import etree
>>> tree = etree.parse('temp.xml')
>>> last_TestCase = tree.xpath('.//TestCase[last()]')[0]
>>> for child in last_TestCase.iterchildren():
...     child.tag, child.text
... 
('name', 'tcname2')
('total', '1')
('totalpass', '0')
('totalfail', '0')
('totalerror', '1')
>>> 
>>> tree = etree.parse('temp_2.xml')
>>> last_TestCase = tree.xpath('.//TestCase[last()]')[0]
>>> for child in last_TestCase.iterchildren():
...     child.tag, child.text
... 
('name', 'tcname1')
('reason', 'reason')
('total', '2')
('totalpass', '0')
('totalfail', '0')
('totalerror', '2')

为什么我一开始不做他的!使用xpath

第一个示例涉及仅使用一个TestCase元素处理xml文件,第二个示例使用其中两个元素。关键点是使用xpath
last
选择器

>>> from lxml import etree
>>> tree = etree.parse('temp.xml')
>>> last_TestCase = tree.xpath('.//TestCase[last()]')[0]
>>> for child in last_TestCase.iterchildren():
...     child.tag, child.text
... 
('name', 'tcname2')
('total', '1')
('totalpass', '0')
('totalfail', '0')
('totalerror', '1')
>>> 
>>> tree = etree.parse('temp_2.xml')
>>> last_TestCase = tree.xpath('.//TestCase[last()]')[0]
>>> for child in last_TestCase.iterchildren():
...     child.tag, child.text
... 
('name', 'tcname1')
('reason', 'reason')
('total', '2')
('totalpass', '0')
('totalfail', '0')
('totalerror', '2')

错误的原因是使用
xmltidict
doc['TestSuite']['TestCase']
是一个仅用于长XML的列表

>>> type(doc2['TestSuite']['TestCase']) # here doc2 is more than one-entry long XML file 
>>> list
但它只是一种针对一个条目长文件的字典:

>>> type(doc['TestSuite']['TestCase']) # doc is one-entry long 
>>> collections.OrderedDict
这就是原因。您可以尝试通过以下方式管理此问题:

 import xmltodict
 with open(filename) as fd:
    doc = xmltodict.parse(fd.read())

    if type(doc['TestSuite']['TestCase']) == list:    
        tp=doc['TestSuite']['TestCase'][length-1]['totalpass']

        tf=doc['TestSuite']['TestCase'][length-1]['totalfail']

        te=doc['TestSuite']['TestCase'][length-1]['totalerror']

        total=doc['TestSuite']['TestCase'][length-1]['total']

   else: # you have just a dict here
        tp=doc['TestSuite']['TestCase']['totalpass']

        tf=doc['TestSuite']['TestCase']['totalfail']

        te=doc['TestSuite']['TestCase']['totalerror']

        total=doc['TestSuite']['TestCase']['total']
否则,您可以使用另一个库进行XML解析


…如果有帮助,请告诉我

错误的原因是,使用
xmltidict
doc['TestSuite']['TestCase']
是一个仅用于长XML的列表

>>> type(doc2['TestSuite']['TestCase']) # here doc2 is more than one-entry long XML file 
>>> list
但它只是一种针对一个条目长文件的字典:

>>> type(doc['TestSuite']['TestCase']) # doc is one-entry long 
>>> collections.OrderedDict
这就是原因。您可以尝试通过以下方式管理此问题:

 import xmltodict
 with open(filename) as fd:
    doc = xmltodict.parse(fd.read())

    if type(doc['TestSuite']['TestCase']) == list:    
        tp=doc['TestSuite']['TestCase'][length-1]['totalpass']

        tf=doc['TestSuite']['TestCase'][length-1]['totalfail']

        te=doc['TestSuite']['TestCase'][length-1]['totalerror']

        total=doc['TestSuite']['TestCase'][length-1]['total']

   else: # you have just a dict here
        tp=doc['TestSuite']['TestCase']['totalpass']

        tf=doc['TestSuite']['TestCase']['totalfail']

        te=doc['TestSuite']['TestCase']['totalerror']

        total=doc['TestSuite']['TestCase']['total']
否则,您可以使用另一个库进行XML解析


…如果有帮助,请告诉我

我已经试过了这对我很有效

import xml.etree.ElementTree as ET
import sys
tree = ET.parse('temp.xml')
root = tree.getroot()
print root
total=[]
totalpass=[]
totalfail=[]
totalerror=[]
for test in root.findall('TestCase'):
    total.append(test.find('total').text)
    totalpass.append(test.find('totalpass').text)
    totalfail.append(test.find('totalfail').text)
    totalerror.append(test.find('totalerror').text)
length=len(total)
print total[length-1],totalpass[length-1],totalfail[length-1],totalerror[length-1]

这个对我有用我试过这个对我有用

import xml.etree.ElementTree as ET
import sys
tree = ET.parse('temp.xml')
root = tree.getroot()
print root
total=[]
totalpass=[]
totalfail=[]
totalerror=[]
for test in root.findall('TestCase'):
    total.append(test.find('total').text)
    totalpass.append(test.find('totalpass').text)
    totalfail.append(test.find('totalfail').text)
    totalerror.append(test.find('totalerror').text)
length=len(total)
print total[length-1],totalpass[length-1],totalfail[length-1],totalerror[length-1]

这一个对我有效

因为您只想要最后一个,所以可以使用负索引来检索它:

import xml.etree.ElementTree as et

tree = et.parse('test.xml')

# collect all the test cases
test_cases = [test_case for test_case in tree.findall('TestCase')]

# Pull data from the last one
last = test_cases[-1]
total = last.find('total').text
totalpass = last.find('totalpass').text
totalfail = last.find('totalfail').text
totalerror = last.find('totalerror').text

print total,totalpass,totalfail,totalerror

因为您只需要最后一个,所以可以使用负索引来检索它:

import xml.etree.ElementTree as et

tree = et.parse('test.xml')

# collect all the test cases
test_cases = [test_case for test_case in tree.findall('TestCase')]

# Pull data from the last one
last = test_cases[-1]
total = last.find('total').text
totalpass = last.find('totalpass').text
totalfail = last.find('totalfail').text
totalerror = last.find('totalerror').text

print total,totalpass,totalfail,totalerror

谢谢你,比尔。但是它仍然失败,因为xml只有一个这样的标记。tcname1原因2 0 0 2现在我明白了(我想)。我认为问题在于
doc['TestSuite']['TestCase']
的类型。它可以是一个
列表
,也可以是一个
OrderedDict
@floatingpurr:没错。太可怕了。是的,很奇怪。谢谢比尔。但是它仍然失败,因为xml只有一个这样的标记。tcname1原因2 0 0 2现在我明白了(我想)。我认为问题在于
doc['TestSuite']['TestCase']
的类型。它可以是一个
列表
,也可以是一个
OrderedDict
@floatingpurr:没错。太可怕了。是的,太奇怪了!:)如果你喜欢的话,请随意接受这个答案!:)好!:)如果你喜欢的话,请随意接受这个答案!:)