PySpark解析嵌套XML仅识别首个item标签无法读取数据如何解决
PySpark解析多结构XML数据解决方案
问题核心原因
- 你提供的原始XML存在语法错误:第二个
<item>标签错误使用自闭合语法,导致后续<batters>节点不属于任何item,是无法读取第二个item完整内容的核心原因之一 - 默认情况下Spark XML仅使用第一条记录推断Schema,若不同item结构不一致,仅采样第一条会遗漏后续item的独有字段
步骤1:修正XML语法
确保所有item节点包裹在根节点<items>内,修正后的标准XML示例:
<items> <item name="Cake" ppu="0.55"> <venue place="Bangalore" day="Friday"> <batters> <batter name="Regular"/> <batter name="Chocolate"/> <batter name="Blueberry"/> </batters> <topping id="5001">None</topping> <topping id="5002">Glazed</topping> <topping id="5005">Sugar</topping> <topping id="5006">Sprinkles</topping> <topping id="5003">Chocolate</topping> <topping id="5004">Maple</topping> </venue> </item> <item name="pizza" ppu="0.56"> <batters> <batter place="Bangalore" name="Regular"/> </batters> </item> </items>
步骤2:临时方案(自动推断全量Schema)
如果数据量小,可开启全量采样让Spark扫描所有记录推断Schema:
df = spark.read\ .format("com.databricks.spark.xml")\ .option("rowTag", "item")\ .option("inferSchema", "true")\ .option("samplingRatio", "1.0") # 采样所有记录推断Schema,避免遗漏字段 .load("File.xml")
注意:samplingRatio设为1.0会扫描全量数据,大数据量场景下性能极低,仅适合小数据测试使用
步骤3:生产方案(自定义嵌套Schema)
手动定义Schema可兼容不同结构的item节点,同时提升读取性能,完整实现代码:
from pyspark.sql.types import * # 定义最内层嵌套结构 batter_type = StructType([ StructField("_name", StringType(), True), StructField("_place", StringType(), True) ]) batters_type = StructType([ StructField("batter", ArrayType(batter_type), True) ]) topping_type = StructType([ StructField("_id", StringType(), True), StructField("_VALUE", StringType(), True) # 标签内的文本值默认存储在_VALUE字段 ]) venue_type = StructType([ StructField("_place", StringType(), True), StructField("_day", StringType(), True), StructField("batters", batters_type, True), StructField("topping", ArrayType(topping_type), True) ]) # 定义完整的item结构,兼容两种不同嵌套形式的item item_schema = StructType([ StructField("_name", StringType(), True), StructField("_ppu", DoubleType(), True), StructField("venue", venue_type, True), StructField("batters", batters_type, True) ]) # 读取时指定自定义Schema df = spark.read\ .format("com.databricks.spark.xml")\ .option("rowTag", "item")\ .schema(item_schema)\ .load("File.xml") # 验证结果 df.show(truncate=False) df.printSchema()
XML标签的属性会默认加
_前缀作为字段名,符合Spark XML的默认解析规则。
内容的提问来源于stack exchange,提问作者Jim Macaulay
相关产品推荐
相关产品推荐

