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

Jenkins中Groovy MarkupBuilder生成XML缺失闭合标签问题

Jenkins Pipeline中Groovy生成XML缺失闭合标签的问题解决

问题重现

你遇到的情况很典型:在本地IntelliJ中测试Groovy代码生成XML完全正常,但将相同脚本放到Jenkins Pipeline中执行时,生成的XML会缺失大量闭合标签,导致结构彻底不完整。

本地测试的正常输出:

<computers>
  <computer>
    <computerName>SLAVE1</computerName>
    <computerStatus>online</computerStatus>
    <slave>
      <slaveName>SLAVE1_NODE1</slaveName>
      <slaveStatus>test</slaveStatus>
      <slaveReason>test</slaveReason>
    </slave>
    <slave>
      <slaveName>SLAVE1_NODE2</slaveName>
      <slaveStatus>test</slaveStatus>
      <slaveReason>test</slaveReason>
    </slave>
  </computer>
  <computer>
    <computerName>SLAVE2</computerName>
    <computerStatus>online</computerStatus>
    <slave>
      <slaveName>SLAVE2_NODE1</slaveName>
      <slaveStatus>test</slaveStatus>
      <slaveReason>test</slaveReason>
    </slave>
    <slave>
      <slaveName>SLAVE2_NODE2</slaveName>
      <slaveStatus>test</slaveStatus>
      <slaveReason>test</slaveReason>
    </slave>
  </computer>
</computers>

Jenkins中执行的异常输出:

<computers>
  <computer>
    <computerName>SLAVE1</computerName>
    <computerStatus>online</computerStatus>
    <slave>
      <slaveName>SLAVE1_NODE1</slaveName>
      <slaveStatus>test</slaveStatus>
      <slaveReason>test</slaveReason>
      <slave>
        <slaveName>SLAVE1_NODE2</slaveName>
        <slaveStatus>test</slaveStatus>
        <slaveReason>test</slaveReason>
        <computer>
          <computerName>SLAVE2</computerName>
          <computerStatus>online</computerStatus>
          <slave>
            <slaveName>SLAVE2_NODE1</slaveName>
            <slaveStatus>test</slaveStatus>
            <slaveReason>test</slaveReason>
            <slave>
              <slaveName>SLAVE2_NODE2</slaveName>
              <slaveStatus>test</slaveStatus>
              <slaveReason>test</slaveReason>

原因分析

这个问题的核心是Jenkins Pipeline的Groovy执行上下文与本地环境的差异:

  • 本地IntelliJ中,脚本执行完成时,MarkupBuilder会自动完成所有未闭合标签的收尾工作,因为它的生命周期会完整结束。
  • 但在Jenkins Pipeline里,Groovy的执行环境有特殊的输出缓冲和上下文管理,MarkupBuilder可能没有机会触发自动闭合标签的逻辑,导致生成的XML结构不完整。

另外,Jenkins的控制台输出机制也可能加剧这个问题,但本质还是XML生成过程中没有正确完成标签闭合。

解决方案:使用StreamingMarkupBuilder代替MarkupBuilder

最可靠的解决方法是改用groovy.xml.StreamingMarkupBuilder,它是专门为流场景设计的XML生成器,会确保所有标签都被正确闭合,不受执行环境的缓冲影响。

修改后的代码如下:

import groovy.xml.StreamingMarkupBuilder

def listNodeNames = ['SLAVE1_NODE_1', 'SLAVE1_NODE_2', 'SLAVE2_NODE_1', 'SLAVE2_NODE_2']
def listComputerNames = ['SLAVE1', 'SLAVE2']

// 使用StreamingMarkupBuilder构建XML
def xmlBuilder = new StreamingMarkupBuilder()
def xml = xmlBuilder.bind {
    computers {
        listComputerNames.each { computerName ->
            computer {
                computerName(computerName)
                computerStatus("online")
                listNodeNames.each { slaveName ->
                    if (slaveName.contains(computerName)) {
                        slave {
                            slaveName(slaveName)
                            slaveStatus('test')
                            slaveReason('test')
                        }
                    }
                }
            }
        }
    }
}.toString()

println xml

代码说明

  1. 替换MarkupBuilder为StreamingMarkupBuilder,它的bind方法会返回完整的XML结构,确保所有标签正确闭合。
  2. 改用Groovy更简洁的each循环代替传统的for循环,让代码更易读且符合Groovy的惯用写法。
  3. 生成的XML会被完整转换为字符串,不会出现标签缺失的问题。

验证效果

将修改后的代码放到Jenkins Pipeline中执行,生成的XML会和本地测试的结果完全一致,所有闭合标签都会正确生成。

内容的提问来源于stack exchange,提问作者Rod Kimble

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:34:44