首页 > 解决方案 > 嵌套 XML 数据 AWS Glue

问题描述

我们有一些这种格式的数据:

<doc>
  <event timestamp="20200529032100">
    <row attr="test" id="3">data</row>
    <row attr="gfds" id="6">data</row>
    <row attr="sadf" id="8">data</row>
  </event>
</doc>

我们要提取每一行的数据,但要同时提取时间戳。我们正在尝试使用 AWS ETL 作业和 CSV 作为输出来做到这一点。

我们试图为 添加一个分类器row,但是我们没有得到时间戳。当我们尝试为 添加分类器时event,我们得到了时间戳,但是在 etl 作业之后,从行中提取的字段仅显示其中只有一个条目的事件row。对于具有多个条目的那些,row生成的 CSV 中只有一行,我们尝试从中提取的字段row是空的,而不是获得相同数量的 csv 行,因为有row条目,这是我们想要的。

这是否可以使用 AWS Glue 解决,还是我们必须自己创建?

标签: amazon-web-servicesaws-glue

解决方案


我们遇到了类似的情况,无法仅使用自定义分类器来构建表格。我们编写了一个作业,使用我们指定的模式将 XML 读入数据帧,然后使用 explode 方法将嵌套元素转换为它们自己的行。

请注意,您需要按照https://towardsdatascience.com/use-aws-glue-and-中的说明将 spark_xml jar 添加为您的工作(或开发端点,如果您在笔记本中开发)的依赖 jar或-databricks-spark-xml-to-process-xml-data-21eaef390fda

您应该在工作中尝试的大致内容:

  1. 为元素结构定义一个模式,该模式表示您最初将读入数据框中的行。在您的示例中,如果您希望每个事件一行,请为您的事件元素定义一个架构,其中包含行元素作为数组类型。就像是:
    mySchema = StructType(
        [StructField('_timestamp',LongType(),True),
         StructField('row', ArrayType(StructType([StructField('_VALUE', StringType(), True),
                                      StructField('_attr', StringType(), True),
                                      StructField('_id', LongType(), True)]), True), True)])
  1. 使用架构将 XML 文件读入数据框
    spark_df = spark.read.format("xml").options(rowTag="event").options(nullValue="").schema(mySchema).load("s3://bucket/path/to/xml")
  1. 使用explode 创建一个新的数据框,每行标签一行
    row_df = spark_df.withColumn('eachrow', explode(col('row')))

这将为您提供如下所示的数据框:

+--------------+--------------------+-------------+
|    _timestamp|                 row|      eachrow|
+--------------+--------------------+-------------+
|20200529032100|[[data,test,3], [...|[data,test,3]|
|20200529032100|[[data,test,3], [...|[data,gfds,6]|
|20200529032100|[[data,test,3], [...|[data,sadf,8]|
+--------------+--------------------+-------------+
  1. 选择时间戳属性和行属性/值。
final_df = row_df.select(col('_timestamp').alias('timestamp'), col('eachrow._VALUE').alias('row_value')...)

然后,您可以以您需要的任何格式写出数据框。


推荐阅读