У нас была похожая ситуация, и мы не смогли построить таблицу, используя только собственный классификатор. Мы написали задание, которое считывает XML в фрейм данных, используя указанную нами схему, а затем использует метод explode для поворота вложенных элементов в их собственные строки.
Обратите внимание, что вам нужно добавить искру_ xml jar в качестве зависимого jar-файла для вашей работы (или конечной точки разработчика, если вы разрабатываете в блокноте), как описано в https://towardsdatascience.com/use-aws-glue-and-or-databricks-spark-xml-to-process-xml-data-21eaef390fda.
Примерный план того, что вы должны попробовать в вашем задании:
- Определите схему для структуры элемента, представляющего строки, которые вы сначала считываете во фрейм данных. В вашем примере, если вам нужна одна строка для каждого события, определите схему для вашего элемента события, которая включает элемент строки как тип массива. Что-то вроде:
mySchema = StructType(
[StructField('_timestamp',LongType(),True),
StructField('row', ArrayType(StructType([StructField('_VALUE', StringType(), True),
StructField('_attr', StringType(), True),
StructField('_id', LongType(), True)]), True), True)])
Прочитать файл XML в фрейм данных, используя схему
spark_df = spark.read.format("xml").options(rowTag="event").options(nullValue="").schema(mySchema).load("s3://bucket/path/to/xml")
Используйте разнесение для создания нового фрейма данных с одной строкой на тег строки
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]|
+--------------+--------------------+-------------+
Выберите атрибут отметки времени и атрибут / значения строки.
final_df = row_df.select(col('_timestamp').alias('timestamp'), col('eachrow._VALUE').alias('row_value')...)
Затем вы можете записать фрейм данных в любом нужном вам формате.