Почему мой фрейм данных загружается пустыми значениями при чтении XML с использованием spark.xml?(Python / Databricks) - PullRequest
0 голосов
/ 06 декабря 2018

Я читаю XML-файл, используя spark.xml в Python, и столкнулся с, казалось бы, очень специфической проблемой.
Мне удалось сузить область XML, которая вызывает проблему, но не выяснил, почемупроисходит.

Вот код для чтения в XML-файле:

src = sqlContext.read.format("com.databricks.spark.xml").options(rowTag="root").load("file.xml")

Вот схема, считанная из XML с использованием библиотеки spark.xml, с rowTag = "root":

    root
 |-- AID: long (nullable = true)
 |-- RID: long (nullable = true)
 |-- XmlData: struct (nullable = true)
 |    |-- NC: struct (nullable = true)
 |    |    |-- RS: struct (nullable = true)
 |    |    |    |-- RD: struct (nullable = true)
 |    |    |    |    |-- CR: struct (nullable = true)
 |    |    |    |    |    |-- Addr1: string (nullable = true)
 |    |    |    |    |    |-- Addr2: string (nullable = true)
 |    |    |    |    |    |-- City: string (nullable = true)
 |    |    |    |    |    |-- InFile: string (nullable = true)
 |    |    |    |    |    |-- Name: string (nullable = true)
 |    |    |    |    |    |-- Phone: long (nullable = true)
 |    |    |    |    |    |-- State: string (nullable = true)
 |    |    |    |    |    |-- Zip: long (nullable = true)
 |    |    |    |    |-- SC: struct (nullable = true)
 |    |    |    |    |    |-- Class: string (nullable = true)
 |    |    |    |    |    |-- ClassType: string (nullable = true)
 |    |    |    |    |    |-- Message: string (nullable = true)
 |    |    |    |    |    |-- SC: long (nullable = true)
 |    |    |    |    |-- NC: long (nullable = true)
 |    |    |    |    |-- CRR: string (nullable = true)
 |    |    |    |    |-- RM: struct (nullable = true)
 |    |    |    |    |    |-- Addr1: string (nullable = true)
 |    |    |    |    |    |-- City: string (nullable = true)
 |    |    |    |    |    |-- MemberNo: string (nullable = true)
 |    |    |    |    |    |-- Name: string (nullable = true)
 |    |    |    |    |    |-- State: string (nullable = true)
 |    |    |    |    |    |-- Zip: long (nullable = true)
 |    |    |    |    |-- TL: array (nullable = true)
 |    |    |    |    |    |-- element: struct (containsNull = true)
 |    |    |    |    |    |    |-- _AvgDays: long (nullable = true)
 |    |    |    |    |    |    |-- _Comment: string (nullable = true)
 |    |    |    |    |    |    |-- _Current: long (nullable = true)
 |    |    |    |    |    |    |-- _HC: long (nullable = true)
 |    |    |    |    |    |    |-- _IndType: string (nullable = true)
 |    |    |    |    |    |    |-- _LS: long (nullable = true)
 |    |    |    |    |    |    |-- _OpenDate: long (nullable = true)
 |    |    |    |    |    |    |-- _PD120Day: long (nullable = true)
 |    |    |    |    |    |    |-- _PD30Day: long (nullable = true)
 |    |    |    |    |    |    |-- _PD60Day: long (nullable = true)
 |    |    |    |    |    |    |-- _PD90Day: long (nullable = true)
 |    |    |    |    |    |    |-- _Region: string (nullable = true)
 |    |    |    |    |    |    |-- _ReportDate: string (nullable = true)
 |    |    |    |    |    |    |-- _SourceID: long (nullable = true)
 |    |    |    |    |    |    |-- _TD: long (nullable = true)
 |    |    |    |    |    |    |-- _VALUE: string (nullable = true)
 |    |    |    |    |-- Trends: array (nullable = true)
 |    |    |    |    |    |-- element: struct (containsNull = true)
 |    |    |    |    |    |    |-- _CurrentPct: double (nullable = true)
 |    |    |    |    |    |    |-- _LineCnt: long (nullable = true)
 |    |    |    |    |    |    |-- _PD120DayPct: double (nullable = true)
 |    |    |    |    |    |    |-- _PD30DayPct: double (nullable = true)
 |    |    |    |    |    |    |-- _PD60DayPct: double (nullable = true)
 |    |    |    |    |    |    |-- _PD90DayPct: double (nullable = true)
 |    |    |    |    |    |    |-- _PD: string (nullable = true)
 |    |    |    |    |    |    |-- _TD: long (nullable = true)
 |    |    |    |    |    |    |-- _VALUE: string (nullable = true)

В этой схеме есть что-то еще, но по какой-то причине синтаксический анализатор XML не достигает этой точки.Я думаю, что есть проблема с тегом ' Trends ' в XML, но я не могу его найти.

Вот пример записи тега 'Trends':

<Trends PD="4205" LineCnt="0" TD="0" CurrentPct="0" PD30DayPct="0" PD60DayPct="0" PD90DayPct="0" PD120DayPct="0" />

Я понимаю, что закрытый тег, такой как этот, не мог быть прочитан в предыдущих версиях анализатора XML, но он прекрасно работает при использовании его в Databricks, а другие мои файлы с закрытыми тегами читаются правильно.

Вот окончательный результат для дальнейшего пояснения того, что я объясняю (у меня есть 13 записей в моем XML):

+---------+--------+-------+
|AID      |RID     |XmlData|
+---------+--------+-------+
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
|     null|    null|   null|
+---------+--------+-------+

(Это представление верхнего уровня в порядке - мой код позже повторяется поструктуры / массивы в «XMLData» - но это необходимо заполнить в первую очередь, конечно)

Кто-нибудь знает, почему это может привести к прекращению загрузки схемы до завершения при разборе?

Обратите вниманиечто я не могу явно определить схему.Это противоречило бы цели проекта, над которым я работаю - я должен иметь возможность выводить схему динамически.Что, опять же, отлично работает для других файлов, которые я использую.

1 Ответ

0 голосов
/ 18 июня 2019

Причина:

Итак, я смог понять, почему это произошло.Вы, вероятно, столкнетесь с этой проблемой, когда XML-файл, который вы пытаетесь преобразовать в фрейм данных, имеет несовместимые значения.Например, что-то вроде ниже будет иметь эту проблему:

<?xml version="1.0"?>
<Company>
  <Employee id="1">
      <Email>tp@xyz.com</Email>
      <Measures id="id32" type="AttributesInContext">
<Dimensions value="7in" title="Height"></Dimensions>
<Dimensions value="" title="Weight"></Dimensions></Measures>
  </Employee>
  <Employee id="2">
      <Email>tp@xyz.com</Email>
      <Measures id="id33" type="AttributesInContext">
<Dimensions value="6in" title="Height"></Dimensions>
<Dimensions value="" title="Weight"></Dimensions></Measures>
  </Employee>
  <Employee id="3">
      <Email>tp@xyz.com</Email>
      <Measures id="id34" type="AttributesInContext">
<Dimensions value="4in" title="Height"></Dimensions>
<Dimensions value="" title="Weight"></Dimensions></Measures>
  </Employee>
</Company>

Здесь, так как у вас есть значение = "" в каждой записи rowTag, мы, вероятно, получим нулевое значение в кадре данных для всех строктак как он не может вывести тип данных.Однако, если вы замените все value="" поля на какое-то фактическое значение, вы увидите, что эта проблема не возникает.

Решение:

Согласно ссылка на базы данных , эта проблема может быть решена с помощью опции option("nullValue", "") при чтении XML-файла.Таким образом, ваша команда будет выглядеть так (я пробовал это в Scala, должно быть похоже на Python):

var xmldf = sparkSession.read.format("com.databricks.spark.xml")
        .option("rowTag", rootTag).option("nullValue", "").load("/path/to/xml")
...