Используйте рекурсивную подстановку для извлечения XML-документов в виде строк в pyspark

Цель состоит в том, чтобы извлечь XML-документы по заданному выражению XPath из группы текстовых файлов в виде строк. Сложность заключается в разнообразии форм, в которых могут находиться текстовые файлы. Это может быть:

  • один файл zip / tar с 100 файлами, каждый 1 документ XML
  • один файл со 100 XML-документами (совокупный документ)
  • один файл zip / tar с различными уровнями каталогов, с отдельными записями XML в виде файлов и агрегированных файлов XML

Мне казалось, что я нашел решение с помощью библиотеки Databrick Spark Spark-XML, так как она обрабатывает рекурсивные подстановки. при чтении файлов. Это было потрясающе. Может делать такие вещи, как:

# read directory of loose files
df = sqlContext.read.format('com.databricks.spark.xml').options(rowTag='mods:mods').load('file:///tmp/combine/qs/mods/*.xml')

# recursively discover and parse
df = sqlContext.read.format('com.databricks.spark.xml').options(rowTag='mods:mods').load('file:///tmp/combine/qs/**/*.xml')

# even read archive files without additional work
df = sqlContext.read.format('com.databricks.spark.xml').options(rowTag='mods:mods').load('file:///tmp/combine/mods_archive.tar')

Проблема в том, что эта библиотека ориентирована на анализ записей XML в столбцах DataFrame, где моя цель — получить только документы XML в виде строк для хранения.

Моя scala недостаточно сильна, чтобы легко взломать библиотеку Spark-XML, чтобы использовать рекурсивную подстановку и захват XPath документов, но пропускает синтаксический анализ и вместо этого сохраняет всю запись XML в виде строки.

Библиотека поставляется с возможностью сериализации DataFrames в XML, но сериализация явно отличается от ввода (что в некоторой степени ожидаемо). Например, текстовые значения элемента становятся атрибутами элемента. Учитывая следующий исходный XML:

<mods:role>
    <mods:roleTerm authority="marcrelator" type="text">creator</mods:roleTerm>
</mods:role>

чтение, а затем сериализация с возвратом Spark-XML:

<mods:role>
    <mods:roleTerm VALUE="creator" authority="marcrelator" type="text"></mods:roleTerm>
</mods:role>

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

Любое понимание будет оценено.


person ghukill    schedule 18.05.2018    source источник


Ответы (1)


Найдено решение этой проблемы Databricks Spark-XML:

xml_rdd = sc.newAPIHadoopFile('file:///tmp/mods/*.xml','com.databricks.spark.xml.XmlInputFormat','org.apache.hadoop.io.LongWritable','org.apache.hadoop.io.Text',conf={'xmlinput.start':'<mods:mods>','xmlinput.end':'</mods:mods>','xmlinput.encoding': 'utf-8'})

Ожидал 250 записей, а получил 250 записей. Простой RDD со всей записью XML в виде строки:

In [8]: xml_rdd.first()
Out[8]: 
(4994,
 '<mods:mods xmlns:mets="http://www.loc.gov/METS/" xmlns:xl="http://www.w3.org/1999/xlink" xmlns:mods="http://www.loc.gov/mods/v3" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.openarchives.org/OAI/2.0/" version="3.0">\n\n\n               <mods:titleInfo>\n\n\n                  <mods:title>Jessie</mods:title>\n\n\n...
...
...

Спасибо мейнтейнеру(ам) Spark-XML за замечательную библиотеку и внимательное отношение к проблемам.

person ghukill    schedule 21.05.2018