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

如何让PySpark的XPath查询返回含None的等长列表而非省略缺失值

问题

PySpark DataFrame某列存储XML字符串,使用绝对路径XPath提取数据时,返回的列表会省略缺失值,导致列表长度不一致。需要保持列表长度与对应父节点数量一致,在缺失数据处填充None。

示例数据与代码

data = [
    (1, """<root>
    <level1>
        <level2>
            <level3>
            <data2>Lion</data2>
                <level4>
                    <data>Apple</data>
                </level4>
            </level3>
        </level2>
        <level2>
            <level3>
                <level4>
                    <data>Banana</data>
                </level4>
            </level3>
        </level2>
        <level2>
            <level3>
            <data2>Tiger</data2>
                <level4>
                    <data>Cranberry</data>
                </level4>
            </level3>
        </level2>
    </level1>
</root>"""),
    (2, """<root>
    <level1>
        <level2>
            <level3>
            <data2>Lion</data2>
                <level4>
                    <data>Apple</data>
                </level4>
            </level3>
        </level2>
        <level2>
            <level3>
            <data2>Tiger</data2>
                <level4>
                    <data>Banana</data>
                </level4>
            </level3>
        </level2>
        <level2>
            <level3>
                <data2>Zebra</data2>
                <level4></level4>
            </level3>
        </level2>
    </level1>
</root>"""),
]

df = spark.createDataFrame(data, ["id", "xml_string"])

当前问题

原XPath查询:

  • 提取data:root/level1/level2/level3/level4/data
  • 提取data2:root/level1/level2/level3/data2

返回结果(列表长度不一致):

(1, ["Apple","Banana","Cranberry"], ["Lion","Tiger"])
(2, ["Apple","Banana"], ["Lion","Tiger","Zebra"])

期望结果

(1, ["Apple","Banana","Cranberry"], ["Lion", None, "Tiger"])
(2, ["Apple","Banana", None], ["Lion","Tiger","Zebra"])
解决方案

调整XPath逻辑

核心是基于父容器节点(level3)批量查询,确保每个父节点对应一个结果(存在则返回文本,不存在则返回空字符串),再将空字符串转为None。

调整后的XPath:

  • 提取data:root/level1/level2/level3/string(level4/data)
  • 提取data2:root/level1/level2/level3/string(data2)

string()函数会针对每个level3节点,返回其下目标子节点的文本;若子节点不存在,返回空字符串,这样结果列表长度与level3节点数量完全一致。

完整PySpark代码

from pyspark.sql import functions as F

# 提取data列表并转换空字符串为None
df = df.withColumn(
    "data_list",
    F.transform(
        F.expr("xpath(xml_string, 'root/level1/level2/level3/string(level4/data)')"),
        lambda x: F.when(x != "", x).otherwise(None)
    )
)

# 提取data2列表并转换空字符串为None
df = df.withColumn(
    "data2_list",
    F.transform(
        F.expr("xpath(xml_string, 'root/level1/level2/level3/string(data2)')"),
        lambda x: F.when(x != "", x).otherwise(None)
    )
)

# 查看最终结果
df.select("id", "data_list", "data2_list").show(truncate=False)

结果验证

执行后将得到符合期望的输出:

+---+--------------------------+--------------------------+
|id |data_list                 |data2_list                |
+---+--------------------------+--------------------------+
|1  |[Apple, Banana, Cranberry]|[Lion, null, Tiger]       |
|2  |[Apple, Banana, null]     |[Lion, Tiger, Zebra]      |
+---+--------------------------+--------------------------+

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:47:10