You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含跳跃列索引的XML表格导入Databricks/Pandas DataFrame

解决XML表格数据导入Databricks/Pandas DataFrame的列对齐问题

你遇到的核心问题是XML中<Cell>的ss:Index属性未被正确解析,导致数据按Cell出现顺序填充列,而非按指定索引匹配表头列。以下是Pandas和Databricks(PySpark)两种环境下的正确实现方案:

一、Pandas 实现方案

使用Python内置的xml.etree.ElementTree解析XML,手动处理命名空间和Cell索引映射:

import xml.etree.ElementTree as ET
import pandas as pd

# 解析XML文件(如果是字符串则用ET.fromstring)
tree = ET.parse("your_file.xml")
root = tree.getroot()

# 处理XML命名空间
ns = {"ss": "urn:schemas-microsoft-com:office:spreadsheet"}

# 提取表头行(第一个<Row>),建立索引到列名的映射
header_row = root.find(".//ss:Worksheet/ss:Table/ss:Row[1]", ns)
col_map = {}
for cell in header_row.findall("ss:Cell", ns):
    idx = int(cell.attrib[f"{{{ns['ss']}}}Index"])
    col_name = cell.find("ss:Data", ns).text
    col_map[idx] = col_name

# 提取所有数据行(从第二个<Row>开始)
data_rows = root.findall(".//ss:Worksheet/ss:Table/ss:Row[position()>1]", ns)
data = []
for row in data_rows:
    row_data = {v: "" for v in col_map.values()}
    for cell in row.findall("ss:Cell", ns):
        idx = int(cell.attrib[f"{{{ns['ss']}}}Index"])
        if idx in col_map:
            col_name = col_map[idx]
            cell_data = cell.find("ss:Data", ns).text
            row_data[col_name] = cell_data
    data.append(row_data)

# 构建DataFrame
df = pd.DataFrame(data)
print(df.to_markdown(index=False))

二、Databricks(PySpark)实现方案

使用spark-xml库解析XML,配合自定义逻辑处理索引映射:

1. 先安装依赖

在Databricks工作区中,通过库页面安装com.databricks:spark-xml_2.12:0.16.0(版本需适配你的Spark版本)。

2. 实现代码

from pyspark.sql import SparkSession
from pyspark.sql.functions import udf, col
from pyspark.sql.types import MapType, StringType

# Databricks中可省略SparkSession初始化,直接使用内置spark对象
spark = SparkSession.builder.appName("XMLImport").getOrCreate()

# 读取XML,提取所有Row数据
xml_df = spark.read.format("xml")\
    .option("rowTag", "Row")\
    .option("namespace", "urn:schemas-microsoft-com:office:spreadsheet")\
    .option("attributePrefix", "ss_")\
    .load("/path/to/your/file.xml")

# 提取表头行,构建索引到列名的映射
header_row = xml_df.filter(col("ss_Index") == "1").collect()[0]
col_map = {}
for cell in header_row.Cell:
    cell_idx = str(cell.ss_Index)
    col_name = cell.Data._VALUE
    col_map[cell_idx] = col_name

# 定义UDF:根据Cell的ss_Index匹配列名,生成完整行的键值对
def process_row(cells):
    row_data = {v: "" for v in col_map.values()}
    for cell in cells:
        cell_idx = str(cell.ss_Index)
        if cell_idx in col_map:
            row_data[col_map[cell_idx]] = cell.Data._VALUE
    return row_data

process_row_udf = udf(process_row, MapType(StringType(), StringType()))

# 处理数据行,转换为结构化DataFrame
result_df = xml_df.filter(col("ss_Index") != "1")\
    .withColumn("row_map", process_row_udf(col("Cell")))\
    .select([col("row_map").getItem(c).alias(c) for c in col_map.values()])

# 展示结果
result_df.show()

问题原因说明

你之前的实现没有针对ss:Index属性做映射逻辑,默认按XML中<Cell>的出现顺序依次填充DataFrame的列,导致缺失Cell的位置被后续Cell占据(比如第一行数据的第5个Cell被填充到第3列)。上述方案通过建立索引-列名的映射关系,强制每个Cell数据匹配到对应列,从而实现正确的列对齐。

内容的提问来源于stack exchange,提问作者NWijaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:37