PySpark DataFrame解析XML列:提取属性生成列表列方案求助
解决PySpark提取XML列中
<goal>属性为列表列的问题 我来帮你搞定这个XML属性提取的问题!其实不用在UDF上卡壳,这里有两种实用的方案,一种是利用PySpark官方支持的XML处理工具,另一种是写出正确的自定义UDF,都能完美满足你的需求:
方案一:使用spark-xml库(推荐,更简洁高效)
首先得确保你的Spark环境能用上spark-xml依赖——本地开发可以直接用pip install spark-xml,集群环境启动Spark时加--packages com.databricks:spark-xml_2.12:0.16.0(版本号根据你的Spark版本调整)。这个库能直接解析DataFrame里的XML字符串列,不用手动写复杂的遍历逻辑。
步骤示例:
导入依赖并定义XML结构Schema
我们需要先明确XML对应的结构化格式:每个<goal>是一个包含三个属性的结构体,整个<goals>是这些结构体的数组:from pyspark.sql import SparkSession from pyspark.sql.functions import from_xml from pyspark.sql.types import StructType, StructField, StringType, ArrayType # 单个<goal>节点的结构 goal_schema = StructType([ StructField("id", StringType(), nullable=True), StructField("name", StringType(), nullable=True), StructField("sex", StringType(), nullable=True) ]) # 整个<goals>的结构:数组类型,元素是单个goal的结构 goals_schema = StructType([ StructField("goals", ArrayType(goal_schema), nullable=True) ])解析XML列并提取属性列表
假设你的DataFrame叫df,存储XML的列是xml_content,用from_xml解析后直接提取数组中的属性即可:# 解析XML列 parsed_df = df.withColumn("parsed_goals", from_xml(df.xml_content, goals_schema)) # 生成三个目标列表列 result_df = parsed_df.select( "xml_content", parsed_df.parsed_goals.goals.id.alias("id_list"), parsed_df.parsed_goals.goals.name.alias("name_list"), parsed_df.parsed_goals.goals.sex.alias("sex_list") ) result_df.show(truncate=False)
方案二:自定义UDF结合xml.etree.ElementTree
如果不想引入额外依赖,也可以写出正确的UDF来实现。之前你可能是返回类型或者解析逻辑没处理对,这里给你正确的写法:
步骤示例:
编写解析函数和UDF
我们写一个函数,输入XML字符串后遍历所有<goal>节点,收集三个属性的列表,返回一个包含这三个列表的元组,同时定义对应的返回Schema:import xml.etree.ElementTree as ET from pyspark.sql.functions import udf from pyspark.sql.types import StructType, StructField, ArrayType, StringType def parse_goals(xml_str): try: root = ET.fromstring(xml_str) ids, names, sexes = [], [], [] # 遍历所有<goal>节点 for goal in root.findall("goal"): ids.append(goal.get("id")) names.append(goal.get("name")) sexes.append(goal.get("sex")) return (ids, names, sexes) except Exception as e: # 处理XML格式错误的情况,返回空列表避免任务失败 return ([], [], []) # 定义UDF的返回结构:包含三个数组列的结构体 udf_return_schema = StructType([ StructField("id_list", ArrayType(StringType()), nullable=True), StructField("name_list", ArrayType(StringType()), nullable=True), StructField("sex_list", ArrayType(StringType()), nullable=True) ]) parse_goals_udf = udf(parse_goals, udf_return_schema)应用UDF并拆分结果列
把UDF应用到XML列后,拆分工结构体得到三个单独的列表列:result_df = df.withColumn("extracted", parse_goals_udf(df.xml_content)) \ .select( "xml_content", "extracted.id_list", "extracted.name_list", "extracted.sex_list" ) result_df.show(truncate=False)
测试验证
如果你的测试DataFrame是这样的:
spark = SparkSession.builder.appName("XMLParse").getOrCreate() data = [("""<?xml version="1.0" encoding="utf-8"?> <goals> <goal id="445" name="xxxy" sex="F" /> <goal id="2468" name="qwerzui" sex="F" /> <goal id="4334" name="foo" sex="M" /> <goal id="15" name="fooh" sex="F" /> </goals>""",)] df = spark.createDataFrame(data, ["xml_content"])
运行代码后会得到你想要的结果:
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+----------------------------+----------------+ |xml_content |id_list |name_list |sex_list | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+----------------------------+----------------+ |<?xml version="1.0" encoding="utf-8"?> <goals> <goal id="445" name="xxxy" sex="F" /> <goal id="2468" name="qwerzui" sex="F" /> <goal id="4334" name="foo" sex="M" /> <goal id="15" name="fooh" sex="F" /> </goals>|[445, 2468, 4334, 15]|[xxxy, qwerzui, foo, fooh]|[F, F, M, F]| +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+----------------------------+----------------+
内容的提问来源于stack exchange,提问作者Meiiso
相关产品推荐
相关产品推荐

