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

除XmlSlurper与XmlParser外,Jenkins Pipeline还有哪些XML解析方法?

无XmlSlurper/XmlParser时Jenkins Pipeline解析XML的替代方法

你有如下结构的Servers.xml文件:

<Servers>
    <Environment id="1" name="Jenkins">
        <Server id="1" ip="192.168.0.1" />
        <Server id="2" ip="10.21.22.30" />
    </Environment>

    <Environment id="2" name="Pipe">
        <Server id="1" ip="192.10.2.77" />
        <Server id="2" ip="122.30.45.99" />
    </Environment>

</Servers>

需要根据Environment标签的name属性修改对应Server节点的ip值,但XmlSlurper和XmlParser在Jenkins Pipeline中被禁止,且无法申请签名批准或安装插件,以下是两种可行的替代方案:

方案1:正则表达式(适合结构固定的XML)

因为你的XML结构规则明确,用正则匹配替换是最直接的方式,无需依赖任何XML解析工具:

// 配置参数
def xmlFilePath = "Servers.xml"
def targetEnvName = "Jenkins"
def targetServerId = "1"
def newIpAddress = "192.168.0.100"

// 读取原XML内容
def originalContent = readFile xmlFilePath
// 构造正则,匹配指定Environment下目标Server的ip属性
def replaceRegex = /(<Environment[^>]+name="${targetEnvName}"[^>]*>\s*<Server[^>]+id="${targetServerId}"[^>]+ip=")[^"]+(")/
// 执行替换
def updatedContent = originalContent.replaceAll(replaceRegex, "\$1${newIpAddress}\$2")

// 将修改后的内容写回文件
writeFile file: xmlFilePath, text: updatedContent

注意:这种方法仅适用于XML结构稳定的场景,如果后续XML标签排版、属性顺序发生变化,正则可能失效,但对你当前的需求完全适用。

方案2:Java原生XML API(功能更稳定)

Groovy可以直接调用Java自带的XML处理API,通过@NonCPS注解避开Pipeline的序列化限制(方法内仅处理字符串和Java对象,不调用Pipeline步骤):

@NonCPS
def updateServerIp(String xmlContent, String envName, String serverId, String newIp) {
    // 初始化XML解析器
    def docFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance()
    def docBuilder = docFactory.newDocumentBuilder()
    def xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlContent.getBytes("UTF-8")))

    // 遍历所有Environment节点
    def envNodes = xmlDoc.getElementsByTagName("Environment")
    for (int i = 0; i < envNodes.getLength(); i++) {
        def currentEnv = envNodes.item(i)
        if (currentEnv.getAttribute("name") == envName) {
            // 遍历当前Environment下的Server节点
            def serverNodes = currentEnv.getElementsByTagName("Server")
            for (int j = 0; j < serverNodes.getLength(); j++) {
                def currentServer = serverNodes.item(j)
                if (currentServer.getAttribute("id") == serverId) {
                    currentServer.setAttribute("ip", newIp)
                    break
                }
            }
            break
        }
    }

    // 将修改后的XML文档转换为字符串
    def transformer = javax.xml.transform.TransformerFactory.newInstance().newTransformer()
    transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes")
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4")
    def stringWriter = new StringWriter()
    transformer.transform(new javax.xml.transform.dom.DOMSource(xmlDoc), new javax.xml.transform.stream.StreamResult(stringWriter))
    return stringWriter.toString()
}

// 调用示例
def xmlFilePath = "Servers.xml"
def originalContent = readFile xmlFilePath
def updatedContent = updateServerIp(originalContent, "Pipe", "2", "122.30.45.100")
writeFile file: xmlFilePath, text: updatedContent

这种方法能处理更复杂的XML结构,稳定性更强,即使XML排版变化也不影响解析。

内容的提问来源于stack exchange,提问作者Meng Xiangrui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:55:22