2017-07-27 180 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信息。