Jenkins流水线中为现有XML添加新节点报错求助
问题:为XML的testcase节点添加properties子节点并修复Jenkins流水线脚本错误
原始XML文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <testsuites> <testsuite name="xray" tests="2" failure="0" timestamp="2023-07-07T05:25:33.339Z" skipped="0" failure-evaluating="0"> <testcase name="SPT-4323" classname="testim.io.test" time="52.597" ownedBy="Staysure Automation" ownerEmail="automationteam@staysure.co.uk"> </testcase> <testcase name="SPT-4331" classname="testim.io.test" time="20.823" ownedBy="Automation Team" ownerEmail="nipunam@intervest.lk"> </testcase> </testsuite> </testsuites>
需求
为每个testcase节点添加对应的properties子节点,其中property的test_key值与testcase的name属性一致,最终每个testcase结构如下:
<testcase name="SPT-4323" classname="testim.io.test" time="52.597" ownedBy="Staysure Automation" ownerEmail="automationteam@staysure.co.uk"> <properties> <property name="test_key" value="SPT-4323" /> </properties> </testcase>
原尝试脚本及问题
原Jenkins流水线脚本存在XML格式错误、API使用不当等问题,导致执行报错:
stage('Update_XML') { try { def File = readFile "${env.WORKSPACE}/testim-tests-report.xml" echo "${File}" def xml = new XmlSlurper().parseText(File) def xrayIDs = xml.testsuite.testcase.collect { it.@name } echo "Xray IDs are ${xrayIDs}" def toadd = '' '<properties> < property name = "test_key" value = "SPT-4323" / > < /properties>''' fragmentToAdd = new XmlSlurper(false, true).parseText(toadd) xml.testsuite.testcase.appendNode(fragmentToAdd) String outxml = groovy.xml.XmlUtil.serialize(xml) echo "Output XML ${outxml}" } catch (Exception) { build_status = false echo Exception.toString() } };
原脚本错误点
toadd变量的XML片段格式完全混乱:存在多余换行、空格和语法错误,导致XmlSlurper解析时抛出XML格式异常。- 使用XmlSlurper进行修改操作:XmlSlurper返回的是只读的GPathResult视图,不适合直接修改XML结构。
- 硬编码
test_key值:无法为每个testcase设置对应的key。 - 未将修改后的XML写回文件:仅输出内容,未保存到原文件。
- 异常处理不规范:未给Exception变量命名,无法输出详细错误信息。
正确解决方案
使用XmlParser直接操作XML节点,动态为每个testcase添加对应properties节点,完整Jenkins流水线脚本如下:
stage('Update_XML') { steps { script { boolean build_status = true try { // 读取原始XML文件内容 def xmlContent = readFile "${env.WORKSPACE}/testim-tests-report.xml" echo "原始XML内容:\n${xmlContent}" // 使用XmlParser解析XML,便于修改节点 def xml = new XmlParser().parseText(xmlContent) // 遍历每个testcase节点,添加对应properties xml.testsuite.testcase.each { testcase -> def testKey = testcase.@name // 创建properties节点 def propertiesNode = new Node(null, "properties") // 创建带属性的property节点 new Node(propertiesNode, "property", [name: "test_key", value: testKey]) // 将properties节点追加到当前testcase下 testcase.append(propertiesNode) } // 格式化输出修改后的XML def writer = new StringWriter() new XmlNodePrinter(new PrintWriter(writer)).print(xml) def outXml = writer.toString() echo "修改后的XML内容:\n${outXml}" // 将修改后的XML写回原文件 writeFile file: "${env.WORKSPACE}/testim-tests-report.xml", text: outXml } catch (Exception e) { build_status = false echo "执行出错: ${e.toString()}" throw e // 可选:抛出异常标记构建失败 } finally { if (!build_status) { currentBuild.result = 'FAILURE' } } } } }
方案说明
- 采用XmlParser:返回可修改的Node对象,直接操作XML结构更可靠。
- 动态生成节点:遍历每个testcase时,根据其name属性设置test_key的值,保证每个节点对应正确的key。
- 规范XML格式化:使用XmlNodePrinter输出格式化后的XML,避免结构混乱。
- 完整流程:包含读取文件、修改、输出、写回文件的完整流程,同时规范异常处理,设置构建状态。
内容的提问来源于stack exchange,提问作者Nipuna Madusanka
相关产品推荐
相关产品推荐

