子标签上的XML解析

时间:2017-07-27 13:09:22

标签: python 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。所以输出会重复出现。

我想要的输出(仅适用于状态=&#34;失败&#34;)

测试名称:登录检查

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

状态:失败

消息:返回错误

以下是我的代码:

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

2 个答案:

答案 0 :(得分: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")))

希望这有帮助

再见
戴夫

答案 1 :(得分: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信息。