如何将含多Row标签的XML文件转换为DataFrame?
搞定Spark-XML解析多重复节点XML转DataFrame的问题
嘿,我之前也碰到过类似的情况——一开始以为spark-xml只能处理单Row标签的XML,后来才发现它其实支持解析嵌套的重复节点,只要配置对参数就行!针对你给出的XML结构,我给你整理两种实用的处理方案:
1. 先搞定依赖
首先确保你的Spark项目里引入了spark-xml的依赖,以Scala的Maven配置为例(版本对应你的Spark版本就行):
<dependency> <groupId>com.databricks</groupId> <artifactId>spark-xml_2.12</artifactId> <version>0.15.0</version> </dependency>
2. 两种处理方案
方案一:单独提取每个重复节点为独立DataFrame
如果你的需求是把不同类型的重复节点(比如CONTACT、COVERAGE)分别做成单独的DataFrame,直接指定rowTag就行,注意要加上根标签和命名空间的配置,避免解析出错:
比如读取所有CONTACT节点:
import org.apache.spark.sql.SparkSession val spark = SparkSession.builder() .appName("XMLToDF") .master("local[*]") .getOrCreate() val contactDF = spark.read .format("com.databricks.spark.xml") .option("rowTag", "CONTACT") // 指定要作为行的标签 .option("rootTag", "generic") // 绑定根标签,防止解析混乱 .option("namespace", "http://xactware.com/generic.xsd") // 处理XML的命名空间 .load("/path/to/your/xml/file.xml") contactDF.show()
用同样的方式,把rowTag换成COVERAGE就能读取所有保险覆盖项的数据,非常直接。
方案二:读取全量XML后拆解嵌套数组
如果需要把整个XML的结构整合起来,先读入全量数据,再用Spark的explode函数展开嵌套的重复数组:
val fullXMLDF = spark.read .format("com.databricks.spark.xml") .option("rowTag", "generic") .option("namespace", "http://xactware.com/generic.xsd") .option("inferSchema", "true") // 自动推断Schema,也可以手动指定 .load("/path/to/your/xml/file.xml") // 先看看整体的Schema结构,方便后续拆解 fullXMLDF.printSchema() // 展开CONTACTS里的重复CONTACT节点 val expandedContacts = fullXMLDF.select( $"transactionId", // 保留根节点的标识字段,方便关联 explode($"COVERSHEET.CONTACTS.CONTACT").alias("contact_info") ).select( $"transactionId", $"contact_info._type".alias("contact_type"), $"contact_info._name".alias("contact_name") ) expandedContacts.show() // 同样的方式展开COVERAGES下的COVERAGE节点 val expandedCoverages = fullXMLDF.select( $"transactionId", explode($"COVERAGES.COVERAGE").alias("coverage_info") ).select( $"transactionId", $"coverage_info._coverageName".alias("coverage_name"), $"coverage_info._coverageType".alias("coverage_type"), $"coverage_info._id".alias("coverage_id") ) expandedCoverages.show()
3. 避坑提示
你的XML带有命名空间xmlns="http://xactware.com/generic.xsd",一定要加上namespace配置项,不然spark-xml会把命名空间拼到列名里,导致你找不到对应的字段!
另外,rowTag其实支持嵌套路径,比如你也可以直接写COVERSHEET.CONTACTS.CONTACT作为rowTag,直接读取这个层级的节点,省去后续拆解的步骤。
这样就能把你XML里的多个重复节点都转换成规范的DataFrame了,两种方案根据你的需求选就行~
内容的提问来源于stack exchange,提问作者LUZO
相关产品推荐
相关产品推荐

