Grails中如何使用XMLSlurper的setKeepIgnorableWhiteSpace()保留XML格式?
Grails中XmlSlurper保留XML空白格式的正确用法
问题背景
现有一段Grails代码,用于下载XML文件、解析修改后重新写入,代码运行正常但生成的文件丢失所有空白格式:
def xmlFile = simpleSftpService.downloadFile('theFile.xml') def rootNode = new XmlSlurper().parse(xmlFile) rootNode.someThing.each(){ it.thingy='It should be this' } def fileName="MyNew.xml" File writer = File.createTempFile('tempFile', '.xml') def builder = new StreamingMarkupBuilder() writer << builder.bind { mkp.yield rootNode } InputStream inputStream = new BufferedInputStream(new FileInputStream(writer)) def storeFile = simpleSftpService.uploadFile(inputStream, fileName)
尝试使用setKeepIgnorableWhiteSpace(true)解决时,以下写法返回null:
def rootNode= new XmlSlurper() rootNode.setKeepIgnorableWhiteSpace(true) rootNode.parse(xmlFile)
链式调用写法则抛出空指针异常:
def rootNode=XmlSlurper()setKeepIgnorableWhiteSpace(true).parse(xmlFile)
错误信息:
java.lang.NullPointerException: Cannot invoke method parse() on null object
解决方案
1. 正确设置XmlSlurper的空白保留属性
问题根源:
- 第一种写法没有将
parse()的结果赋值给rootNode,变量实际存储的是XmlSlurper实例,而非解析后的XML节点; - 第二种链式调用语法错误,
XmlSlurper()不是合法的实例创建方式,需用new XmlSlurper(),且方法调用需正确拼接。
正确的XmlSlurper初始化写法:
def xmlSlurper = new XmlSlurper() xmlSlurper.setKeepIgnorableWhiteSpace(true) def rootNode = xmlSlurper.parse(xmlFile)
或者简洁的链式调用写法:
def rootNode = new XmlSlurper().setKeepIgnorableWhiteSpace(true).parse(xmlFile)
2. 配置StreamingMarkupBuilder格式化输出
仅保留解析时的空白还不够,StreamingMarkupBuilder默认会压缩输出,需设置其formatting属性为Formatting.INDENT来保留缩进格式:
def builder = new StreamingMarkupBuilder() builder.formatting = Formatting.INDENT // 需导入groovy.xml.StreamingMarkupBuilder$Formatting writer << builder.bind { mkp.yield rootNode }
完整修正后的代码
import groovy.xml.StreamingMarkupBuilder$Formatting def xmlFile = simpleSftpService.downloadFile('theFile.xml') // 正确初始化XmlSlurper并保留空白 def rootNode = new XmlSlurper().setKeepIgnorableWhiteSpace(true).parse(xmlFile) rootNode.someThing.each(){ it.thingy='It should be this' } def fileName="MyNew.xml" File writer = File.createTempFile('tempFile', '.xml') def builder = new StreamingMarkupBuilder() builder.formatting = Formatting.INDENT // 开启缩进格式化 writer << builder.bind { mkp.yield rootNode } InputStream inputStream = new BufferedInputStream(new FileInputStream(writer)) def storeFile = simpleSftpService.uploadFile(inputStream, fileName)
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

