2017-07-27 97 views
0

以下是我的XML示例。有很多这种类似的情况。XML解析子标签

<suite name="regression_1"> 
<test name="Login check" id="s1-t1"> 
    <tc name="Valid Username & Password"> 
     <message level="INFO" timestamp="20170726 14:25:39.778">Return: None</message> 
     <status starttime="20170726 14:25:39.740" status="PASS"/> 
    </tc> 
    <tc name="Invalid Username or Password"> 
     <message level="INFO" timestamp="20170726 14:25:39.779">Return error</message> 
     <tc name="Invalid password" library="avi_lib"> 
      <message level="TRACE" timestamp="20170726 14:25:47.769">Return error</message> 
      <status starttime="20170726 14:25:39.779" status="FAIL"/> 
     </tc> 
     <status starttime="20170726 14:25:39.738" status="FAIL"/> 
    </tc> 
<status status="FAIL"/> 
</test> 

</suite> 

我的要求: 通过XML日志,记下测试,测试用例和测试案例状态。如果状态失败,则显示哪个测试用例和测试套件失败以及其他相关消息。

问题我正在面临:我正在迭代测试,收集所有的子测试状态和状态。在下面的代码中,如果tc#2失败,则输出为tc1提供,因为我通过收集列表中的所有状态来迭代tc1。所以输出重复。

我的期望输出(仅适用于状态= “失败”)

测试名称:登录检查

测试用例:无效的用户名&密码

状态:失败

消息:返回错误

以下是我的代码:

# !/usr/bin/python 

from xml.dom.minidom import parse 
import xml.dom.minidom 
import time 

DOMTree = xml.dom.minidom.parse("output.xml") 
collection = DOMTree.documentElement 
tc_entry = collection.getElementsByTagName("suite") 


for tc in tc_entry: 
    if tc.hasAttribute("name"): 
     print ("Suite name: {}".format(tc.getAttribute("name"))) 
    tests = tc.getElementsByTagName('test') 
    for test in tests: 
     testcases = test.getElementsByTagName('tc') 
     for tc_name in testcases: 
      status = tc_name.getElementsByTagName('status') 
      for state in status: 
       if state.getAttribute("status") != "PASS": 
        print("Failed") 
        print("Test name: {}".format(test.getAttribute("name"))) 
        print("Test case name: {}".format(tc_name.getAttribute("name"))) 
        print("Status: {}".format(state.getAttribute("status"))) 
+0

你可以在两个代码块中发布你想要的输出和你当前的输出吗? – Harrichael

回答

0

不知道我的理解正确的......然而,尝试用递归函数是这样的:

# !/usr/bin/python 

from xml.dom.minidom import parse 
import xml.dom.minidom 
import time 


def getStatusForNode(tc): 
    status_to_be_returned = [] 
    is_just_father = False 

    for child in tc.childNodes: 
     if child.nodeName == "tc": 
      is_just_father = True 
      status_to_be_returned.append(getStatusForNode(child)[0]) 

    if not is_just_father: 
     status = tc.getElementsByTagName('status') 
     return [(tc, status)] 

    return status_to_be_returned 


DOMTree = xml.dom.minidom.parse("output.xml") 
collection = DOMTree.documentElement 
tc_entry = collection.getElementsByTagName("suite") 


for tc in tc_entry: 
    if tc.hasAttribute("name"): 
     print("Suite name: {}".format(tc.getAttribute("name"))) 
    tests = tc.getElementsByTagName('test') 
    for test in tests: 

     for child in test.childNodes: 
      if child.nodeName == "tc": 
       children_status = getStatusForNode(child) 
       for (tc_name, status) in children_status: 
        for state in status: 
         if state.getAttribute("status") != "PASS": 
          print("---") 
          print("Test name: {}".format(test.getAttribute("name"))) 
          print("Test case name: {}".format(tc_name.getAttribute("name"))) 
          print("Status: {}".format(state.getAttribute("status"))) 

希望这有助于

再见
戴夫

+0

@Dave,它完美的工作。谢谢你 – Yadunandana

+0

很高兴有帮助:)如果它不打扰你接受答案;) – mastro35

0

我建议使用XPath表达式:

注意:在我的示例中,我只使用一个suite元素,所以我将其称为root - 在您的实现中,您将希望遍历所有suite元素,因此root将有所不同,例如,该行tests = root.findall('.//tc')将变成tests = s.findall('.//tc')。我已经评论了我认为你会使用的几行。

import xml.etree.ElementTree as et 

tree = et.parse('some_file.xml') 
root = tree.getroot() 

# suites = root.findall('.//suite') 

# for s in suites: 

tests = root.findall('.//tc') # Grab all 'tc' elements within a 'suite' element 
test_name = root.find('test').attrib['name'] 

for tc in tests: 
    status = tc.find('status').attrib['status'].lower() 

    if 'fail' in status: 
     tc_name = tc.attrib['name'] 
     msg = tc.find('message').text 

     print("Test Name: {}\nTest Case: {}\nStatus: {}\nMessage: {}\n".format(
      test_name, tc_name, status.capitalize(), msg 
     )) 

输出:

Test Name: Login check 
Test Case: Invalid Username or Password 
Status: Fail 
Message: Return error 

Test Name: Login check 
Test Case: Invalid password 
Status: Fail 
Message: Return error 

此外,还有Python的xml.etree.ElementTree文档中的XPath信息。