Groovy怎么解析和生成XML XmlSlurper和XmlParser

XmlSlurper适合读取查询,支持GPath惰性求值;XmlParser适合修改结构,返回标准DOM对象;生成XML首选MarkupBuilder。

Groovy 提供了两种主流的 XML 处理方式:XmlSlurper(面向读取、动态、简洁)和 XmlParser(面向修改、结构化、严格)。它们底层都基于 Java 的 SAX 或 DOM,但 API 设计风格差异明显——选哪个取决于你主要想“查数据”还是“改结构”。

XmlSlurper:快速读取和遍历 XML

XmlSlurper 更适合解析 XML 并以直观方式提取内容,支持 GPath 表达式,返回的是惰性求值的代理对象(不是原始 DOM 节点),不能直接修改源树,但写法极简。

常见用法:

  • 解析字符串或文件:def xml = new XmlSlurper().parseText('AB')
  • 用 GPath 提取内容:xml.item*.@id → 返回 ['1', '2']xml.item[0].text() → 返回 'A'
  • 支持命名空间(需显式声明):def ns = new Namespace('http://example.com', 'ex'); xml.'ex:tag'
  • 注意:默认忽略空白文本节点;若需保留,构造时传 true, falsenew XmlSlurper(false, false)(关闭验证 + 保留空白)

XmlParser:安全修改和生成 XML

XmlParser 返回标准

W3C Document 对象(DOM),可增删改节点、设置属性、序列化回字符串,适合需要构建或深度编辑 XML 的场景。

常见用法:

  • 解析:def doc = new XmlParser().parseText('1')
  • 添加子节点:doc.appendNode('b').setValue('2')
  • 修改属性:doc.a.@id = 'new-id'
  • 生成字符串:def writer = new StringWriter(); new XmlNodePrinter(writer).print(doc); writer.toString()
  • 注意:不支持直接用 GPath 赋值(如 doc.'**'.find{ it.name() == 'a' }.@id = 'x' 可能失败),推荐用 getElementsByTagName 或递归遍历配合 setNode

生成 XML:用 MarkupBuilder 最自然

Groovy 原生推荐用 MarkupBuilder(或线程安全的 StreamingMarkupBuilder)来生成 XML,比手动拼接或 DOM 构建更清晰、不易出错。

示例:

def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.root {
item(id: '1') { name('Alice') }
item(id: '2') { name('Bob') }
}

输出:AliceBob

如需格式化缩进,可用 new StreamingMarkupBuilder().bind{...}.toString() 配合 XmlNodePrinter,但通常直接生成紧凑 XML 更高效。

选型建议与避坑提示

简单判断逻辑:

  • 只读 + 查询为主 → 优先 XmlSlurper(代码少、易懂、性能好)
  • 要增删改节点 + 需精确控制结构 → 用 XmlParser + DOM 操作
  • 从零生成 XML → 用 MarkupBuilder(别硬写字符串)
  • 处理大文件?XmlSlurper 默认是惰性加载,但深层嵌套可能内存高;超大 XML 建议用 SAX 或 StAX(Groovy 也支持,但需手动写 Handler)
  • 遇到解析失败?检查是否含 BOM、编码不匹配(建议统一用 UTF-8)、或 XML 不良(如未闭合标签)——XmlParser 默认校验严格,XmlSlurper 默认宽松但可能跳过错误