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

在Databricks中使用Scala保存XML时保留内部XML节点结构

我明白你现在遇到的问题了——Spark的XML Writer默认会把字符串内容里的XML特殊字符自动转义,导致<data>节点内的原始XML结构变成了&amp;lt;这类转义文本,而不是你想要保留的嵌套XML节点。下面是针对这个问题的解决思路和具体实现方案:

问题根源

com.databricks.spark.xml这个库的设计目标是将结构化的Spark DataFrame数据转换成标准XML,所以它会自动对字符串类型列中的<、>、&等XML特殊字符进行转义处理,确保输出的XML格式合法。但这恰好破坏了你想要保留的<data>节点内的原始XML结构。

解决方案:绕过自动转义,直接构建完整XML

既然需要保留<data>内的原始XML,我们可以跳过Spark的XML Writer,手动构建完整的XML字符串后直接写入文件。具体分两种场景处理:

场景1:数据量较小(可以拉到Driver节点处理)

如果你的数据集不大,可以直接将每行数据转换成XML片段,再拼接成完整的XML文档:

// 假设你的export DataFrame中有一列名为data,存储着原始XML字符串
val xmlContentRows = export.select("data").map { row =>
  // 直接拼接<content>节点,保留data列的原始XML内容
  val rawDataXml = row.getAs[String]("data")
  s"<content><data>$rawDataXml</data></content>"
}

// 收集所有行并拼接成完整的XML文档
val fullXml = s"<row>\n${xmlContentRows.collect().mkString("\n")}\n</row>"

// 将完整XML写入文件
import java.io.{File, PrintWriter}
val writer = new PrintWriter(new File("sample.xml"))
writer.write(fullXml)
writer.close()

场景2:数据量较大(分布式处理避免内存溢出)

如果数据量很大,collect()会把所有数据拉到Driver节点导致内存不足,我们可以先将XML片段分布式写入临时文件,再手动拼接根节点:

// 第一步:将每行数据转换成<content>节点的XML片段
val xmlContentRows = export.select("data").map { row =>
  val rawDataXml = row.getAs[String]("data")
  s"<content><data>$rawDataXml</data></content>"
}

// 第二步:将片段写入临时文本文件(coalesce(1)可选,根据你需要的文件数量调整)
xmlContentRows.coalesce(1).saveAsTextFile("temp_xml_fragments")

// 第三步:读取临时文件,拼接完整XML文档
import scala.io.Source
import java.io.PrintWriter
import org.apache.commons.io.FileUtils

// 读取临时目录下的part文件
val tempPartFiles = new File("temp_xml_fragments").listFiles().filter(_.getName.startsWith("part-"))
val xmlFragments = tempPartFiles.flatMap(file => Source.fromFile(file).getLines())

// 拼接根节点生成完整XML
val fullXml = s"<row>\n${xmlFragments.mkString("\n")}\n</row>"

// 写入最终文件
new PrintWriter("sample.xml").write(fullXml).close()

// 清理临时目录
FileUtils.deleteDirectory(new File("temp_xml_fragments"))

注意事项

  • 确保data列中的原始XML内容本身是合法的(比如标签闭合、没有未转义的特殊字符),否则最终生成的XML文档会无效。
  • 如果你的DataFrame还有其他列需要写入XML,只需要在拼接<content>节点时把其他列也加入进去即可,比如:
    s"<content><col1>${row.getAs[String]("col1")}</col1><data>$rawDataXml</data></content>"
    

内容的提问来源于stack exchange,提问作者R.Illa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:24:53