spark读取嵌套xml必须使用databricks的spark-xml包,原生不支持;需正确配置rowtag、valuetag、attributeprefix等参数解析嵌套结构、属性和混合内容,大文件应分片处理避免oom。

Spark读取嵌套XML必须用spark-xml第三方包
Spark原生不支持XML,spark.read.format("xml")会直接报错java.lang.ClassNotFoundException: Failed to find data source: xml。必须显式引入Databricks维护的com.databricks:spark-xml_2.12(注意Scala版本要匹配)。Maven坐标不能漏掉_2.12或_2.13后缀,否则运行时找不到类。
嵌套结构需靠rowTag和valueTag准确定位
XML嵌套层级深时,rowTag决定哪一层作为DataFrame的行记录;若不设,默认只解析顶层标签,所有子节点被塞进一个_VALUE字段里,失去结构。遇到含<item><name>A</name><price>10</price></item>这种结构,必须设rowTag="item"。如果某字段值本身是文本(如<title>Spark Guide</title>),还要加valueTag="title",否则内容会变成空或null。
-
rowTag必须是唯一可枚举的“记录级”标签名,不能是root或data这类泛化名 - 多个同名嵌套标签(如
<order><item>...</item><item>...</item></order>)会自动展开为多行,无需额外flatten - 若XML有命名空间(
xmlns="http://example.com/ns"),spark-xml默认不识别,得先用XSLT预处理或改用XmlInputFormat+ RDD方式
复杂类型(数组、属性、混合内容)要主动配置解析策略
默认情况下,XML属性(如<book id="123"></book>)不会自动转成列,必须设attributePrefix="@@";而混合内容(文本+子标签共存)容易导致字段丢失,需配合valueTag和ignoreSurroundingSpaces=true清理空白。
df = spark.read.format("xml") \
.option("rowTag", "book") \
.option("attributePrefix", "@@") \
.option("valueTag", "_VALUE") \
.option("ignoreSurroundingSpaces", "true") \
.load("books.xml")
这样<book id="123"><title>Spark</title>Intro</book>才会生成三列:@@id、title、_VALUE。漏掉valueTag,Intro就没了。
超大XML文件慎用wholeFile=True,优先分片+流式解析
spark-xml底层依赖javax.xml.parsers.SAXParser,单文件超过2GB极易OOM。不要设wholeFile=True(这是为小文件设计的),而是把XML按rowTag切分成多个小文件,或用spark.read.text()逐行扫描+正则提取关键段落再组装。另外,compression="gzip"仅支持已压缩的单文件,不解压流式读取——意味着必须先解压到磁盘再读,无法节省IO。
真正难啃的是跨文件的嵌套逻辑(比如<order></order>分散在多个XML中),这时候Spark已不是最优解,该换Flink或专用XML流处理器。










