在Databricks中使用Scala保存XML时保留内部XML节点结构
我明白你现在遇到的问题了——Spark的XML Writer默认会把字符串内容里的XML特殊字符自动转义,导致<data>节点内的原始XML结构变成了&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
相关产品推荐
相关产品推荐

