You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python的xml.etree.ElementTree检测XML标签存在性

问题:解析XML筛选含failure的testcase并格式化输出

我用Python的xml.etree.ElementTree解析了一个XML测试报告,结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
    <testsuite name="force.apex" timestamp="2022-08-01T11:13:33.672Z" hostname="***" tests="192" failures="21"  errors="0"  time="371.30">
<testcase name="wavewrapTest" classname="SVC_WaveInsightGeneratorDatasetVerTest" time="0.10">
        </testcase>
        <testcase name="testSVC_UpdateLastTransactionDateTest" classname="SVC_UpdateLastTransactionDateTest" time="2.65">
        </testcase>
        <testcase name="wavewrapTest" classname="SVC_WaveInsightJSONResponseHandlerTest" time="0.10">
        </testcase>
        <testcase name="testFeedComment" classname="DataMaskFeedItemTest" time="2.05">
            <failure message="System.NullPointerException: Argument cannot be null."><![CDATA[Class.SVC_AccountQueueableHashedId.execute: line 15, column 1]]></failure>
        </testcase>
        <testcase name="testFeedItem" classname="DataMaskFeedItemTest" time="0.76">
            <failure message="System.NullPointerException: Argument cannot be null."><![CDATA[Class.SVC_AccountQueueableHashedId.execute: line 15, column 1]]></failure>
        </testcase>
        <testcase name="schedulerTest" classname="pi_scheduleBirthdayTaskTest" time="0.09">
            <failure message="System.QueryException: List has no rows for assignment to SObject"><![CDATA[Class.pi_scheduleBirthdayTaskTest.schedulerTest: line 19, column 1]]></failure>
        </testcase>
        <testcase name="testDefaultSchedule" classname="SVC_AMLBatchTest" time="0.15">
            <failure message="System.AsyncException: Based on configured schedule, the given trigger 'SCHEDULED_APEX_JOB_TYPE.000000000000000' will never fire."><![CDATA[Class.SVC_AMLBatchTest.testDefaultSchedule: line 228, column 1]]></failure>
        </testcase>
    </testsuite>
</testsuites>

需要筛选出包含带message属性的failure标签的testcase,并按格式Class <classname> failed with message <message>输出,跳过没有failure标签的testcase。

我尝试过以下代码,但都无法得到正确结果:

第一个尝试的代码:

for item in root.findall(".//testcase"):
    failure = item.find('failure')
    if failure is None:
        continue
    failures = failure.text
    for item1 in root.findall(".//testcase/failure"):
        children = item1.get('message')
    print("Class: {} failed with message: {}".format(failures, children))

第二个尝试的代码:

for item in root.iter('testcase'):
    for item1 in root.iter('failure'):
        print(item.attrib['classname'], item1.attrib['message'])

正确解决方案

你的代码问题在于:

  1. 第一个代码错误获取了failure的文本内容(CDATA部分)而非testcase的classname,且内层循环遍历所有failure标签后,children只会保留最后一个failure的message,导致匹配错误。
  2. 第二个代码的嵌套循环会将每个testcase与所有failure标签组合输出,结果重复且对应关系混乱。

正确思路是:遍历每个testcase,找到其内部的failure标签,若存在则提取当前testcase的classname和failure的message属性,按要求格式输出。

完整代码如下:

import xml.etree.ElementTree as ET

# 解析XML文件(如果是本地文件,替换为以下两行)
# tree = ET.parse('test_report.xml')
# root = tree.getroot()

for testcase in root.findall(".//testcase"):
    # 查找当前testcase下的failure标签
    failure = testcase.find("failure")
    if failure is not None:
        # 获取属性值
        classname = testcase.attrib.get("classname")
        error_msg = failure.attrib.get("message")
        if classname and error_msg:
            print(f"Class {classname} failed with message {error_msg}")

执行后输出结果:

Class DataMaskFeedItemTest failed with message System.NullPointerException: Argument cannot be null.
Class DataMaskFeedItemTest failed with message System.NullPointerException: Argument cannot be null.
Class pi_scheduleBirthdayTaskTest failed with message System.QueryException: List has no rows for assignment to SObject
Class SVC_AMLBatchTest failed with message System.AsyncException: Based on configured schedule, the given trigger 'SCHEDULED_APEX_JOB_TYPE.000000000000000' will never fire.

内容的提问来源于stack exchange,提问作者Andrei Deacu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:39:07