如何在Ballerina中去除XML无关空白及正确使用xml:strip?
Ballerina XML格式化问题
原代码及输出
以下是一段可运行的Ballerina程序,通过XML模板创建XML结构并执行两次打印:
import ballerina/io; public function main() { xml x = xml`<root > <foo> <bar>BAR</bar> </foo> </root >`; io:println(x); io:println(xml:strip(x)); }
两次打印的输出完全一致:
<root> <foo> <bar>BAR</bar> </foo> </root>
问题一:生成紧凑格式XML输出
需求是生成无缩进、无换行的紧凑XML输出:
<root><foo><bar>BAR</bar></foo></root>
且不能直接压缩XML模板(如下写法不适用于实际场景):
// 该方式在实际场景中不具备扩展性 xml x = xml`<root ><foo><bar>BAR</bar></foo></root >`;
解决方案
可以通过自定义递归函数遍历XML节点,移除所有仅含空白字符的文本节点,直接拼接元素内容。实现示例如下:
import ballerina/io; import ballerina/lang.xml; // 递归处理XML节点,生成紧凑格式字符串 function compactXml(xml xmlVal) returns string { string result = ""; if xmlVal is xml:Element { // 拼接元素开始标签 result += "<" + xmlVal.name.localName; // 处理元素属性 foreach [string key, string val] in xmlVal.attributes { result += " " + key + "=\"" + val + "\""; } result += ">"; // 递归处理子节点 foreach xml child in xmlVal.children { result += compactXml(child); } // 拼接元素结束标签 result += "</" + xmlVal.name.localName + ">"; } else if xmlVal is xml:Text { // 仅保留非空白文本内容 string text = xmlVal.value.trim(); if text != "" { result += text; } } // 忽略注释、处理指令等非核心节点 return result; } public function main() { xml x = xml`<root > <foo> <bar>BAR</bar> </foo> </root >`; io:println(compactXml(x)); }
运行后将输出预期的紧凑格式XML。
问题二:xml:strip()的作用与正确使用
为什么xml:strip()看似无作用?
根据官方文档描述:
移除XML值中无意义的部分。
注释项、处理指令项被视为无意义内容。移除注释和处理指令后,文本会被合并为最大可能的块(即只有元素会将文本分割为多个块),如果整个块都是空白字符,则该块被视为无意义内容。
实际运行中xml:strip()未生成紧凑XML的原因是:xml:strip()仅负责移除无意义的空白文本节点,但Ballerina的io:println()方法在打印XML时,会自动为元素添加缩进和换行格式,而非直接输出XML节点的原始结构。也就是说,xml:strip()确实完成了节点清理,但最终的格式化是由输出逻辑导致的。
能否用xml:strip()解决问题一?
xml:strip()本身无法直接生成紧凑输出,因为它仅修改XML节点结构,不控制输出格式。但可以结合xml:strip()和自定义字符串转换实现需求:先用xml:strip()移除空白节点、注释和处理指令,再将处理后的XML转换为无格式字符串。
正确使用xml:strip()的示例
示例代码如下(复用上述compactXml函数):
import ballerina/io; import ballerina/lang.xml; public function main() { xml x = xml`<root > <!-- 这是一段注释 --> <foo> <bar>BAR</bar> </foo> <?pi test?> </root >`; xml strippedXml = xml:strip(x); // 此时strippedXml已移除注释、处理指令和空白节点,再转换为紧凑字符串 io:println(compactXml(strippedXml)); } // 复用紧凑XML转换函数 function compactXml(xml xmlVal) returns string { string result = ""; if xmlVal is xml:Element { result += "<" + xmlVal.name.localName; foreach [string key, string val] in xmlVal.attributes { result += " " + key + "=\"" + val + "\""; } result += ">"; foreach xml child in xmlVal.children { result += compactXml(child); } result += "</" + xmlVal.name.localName + ">"; } else if xmlVal is xml:Text { string text = xmlVal.value.trim(); if text != "" { result += text; } } return result; }
内容的提问来源于stack exchange,提问作者user272735
相关产品推荐
相关产品推荐

