使用spark-xml的from_xml函数解析XML列仅返回null值问题求助
根因分析
你遇到的解析全返回null的核心问题是XSD生成的Schema结构和rowTag配置冲突:
- 你用
XSDToSchema.read读取XSD后生成的Schema结构本身就包含最外层的note节点,结构为:root |-- note: struct (nullable = false) | |-- from: string (nullable = false) | |-- to: string (nullable = false) | |-- message: string (nullable = false) - 当你给
from_xml传入rowTag = "note"参数时,spark-xml会优先从XML字符串中提取所有<note>标签的内部内容作为解析根,此时解析出来的内容只有from、to、message三个子字段,没有外层的note字段,和你传入的Schema结构完全不匹配,因此解析结果全部为null。
另外你配置了mode = FAILFAST但没有抛出异常,也验证了不是XML格式错误,只是字段结构不匹配导致spark找不到对应字段返回了默认的null值。
解决方法
任选其一即可:
- 移除
from_xml参数中的"rowTag" -> "note"配置,让解析根为整个XML字符串,直接匹配XSD生成的Schema结构,解析逻辑保持不变即可正常取出parsed.note.from等字段。 - 保留
rowTag配置,调整传入from_xml的Schema,提取XSD生成Schema中note字段的子结构作为解析Schema:// 提取note节点的子结构作为解析Schema val schema = XSDToSchema.read("<the XSD as string>") .apply("note") .dataType .asInstanceOf[StructType] // 后续select时不用再嵌套取note,直接取parsed下的字段即可 .select($"value",$"parsed.from", $"parsed.to", $"parsed.message")
补充排查思路
如果按上述方法修改后仍有问题,可以按以下步骤验证:
- 先静态测试解析逻辑,排除流处理的干扰:
静态测试可以正常解析的话,再排查Kafka读取的内容是否有隐藏字符(比如BOM头、转义字符、多余的前后缀),可以先打印完整的val testXml = """<?xml version="1.0" encoding="UTF-8"?> <note> <from>Jani</from> <to>Tove</to> <message>Remember me this weekend</message> </note>""" val testDf = Seq(testXml).toDF("value") val parsedDf = testDf.withColumn("parsed", from_xml($"value", schema, Map( "mode" -> "FAILFAST", "nullValue"-> "", "ignoreSurroundingSpaces" -> "true" ))) parsedDf.show(false)value字段内容确认格式符合预期。 - 确认spark-xml 0.12.0和Spark 3.1.1的兼容性,也可以尝试升级到spark-xml 0.13.0版本,该版本对Spark 3.1.x的适配更稳定。
内容的提问来源于stack exchange,提问作者Alejandro Arévalo
相关产品推荐
相关产品推荐

