2017-07-27 2 views
0

Unten ist das Beispiel von meinem XML. Es gibt viele ähnliche Fälle.XML Parsing auf Kind-Tags

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

Meine Forderung: Pass durch die XML-Protokolle, beachten Sie die Tests, Testfälle und den Testfall-Status. Wenn der Status fehlgeschlagen ist, wird angezeigt, für welchen Testfall und welche Testsuite es zusammen mit anderen relevanten Nachrichten fehlgeschlagen ist.

Problem, mit dem ich konfrontiert bin: Ich wiederhole den Test und sammle den Status und Status aller Untertests. Wenn tC# 2 im folgenden Code fehlgeschlagen ist, gibt Ausgabe für tc1 aus, während ich für tc1 iteriere, indem ich den gesamten Status in der Liste sammle. Also wird die Ausgabe wiederholt.

Meine gewünschte Ausgabe (Nur für Status = "FAIL")

Testname:

Testfall prüfen Login: Ungültiger Benutzername & Passwort

Status: fehlschlagen

Nachrichten: Zurück Fehler

Unten ist mein Code:

# !/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

Können Sie in zwei Codebausteinen Ihre gewünschte Ausgabe und Ihre aktuelle Ausgabe posten? – Harrichael

Antwort

0

Weiß nicht, ob ich richtig verstanden ... aber mit einer rekursiven Funktion wie diese versuchen:

# !/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"))) 

hoffe, das hilft

Bye
Dave

+0

@Dave, es funktioniert perfekt. danke dir – Yadunandana

+0

Froh hab ich geholfen :) wenn es dich nicht stört akzeptiere die antwort;) – mastro35

0

Ich empfehle mit XPath Ausdrücke:

Hinweis: In meinem Beispiel arbeite ich nur mit einem einzigen suite Element, so dass ich es als root bezeichnen - In Ihrer Implementierung werden Sie durch alle suite Elemente iterieren wollen, also root wird sich unterscheiden, z. Die Linie tests = root.findall('.//tc') würde tests = s.findall('.//tc') werden. Ich habe die Zeilen auskommentiert, von denen ich glaube, dass Sie sie verwenden würden.

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

Ausgang:

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 

Zusätzlich gibt es auch XPath Informationen innerhalb xml.etree.ElementTree Dokumentation Python.