Извлечение элементов из записей XML с использованием Spark / Scala - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь извлечь элементы из записей XML, где каждый файл XML имеет много записей XML.Ниже приведен модифицированный код и пример xmls, который я использую.

Я ожидаю массив строк, в котором каждый элемент массива равен "user:id", но результат равен ":".Я ожидал, что XML.loadString проанализирует каждый файл, и результатом будут отдельные записи XML.То есть, если я возьму два примера файлов в качестве примера, я получу 4 записи XML.На самом деле это два.

После добавления println(d) после получения next я получаю всю строку, представляющую файл, что, вероятно, объясняет, почему функции getId и getUser не являютсяничего не возвращая.

Неправильно ли я обрабатываю нагрузку?

import org.apache.spark.{SparkConf, SparkContext}
import scala.xml._
import scala.collection.mutable.ArrayBuffer

object Details {

    def getDetails(xmlstring: String): Iterator[Node] = {
        val nodes = XML.loadString(xmlstring)
        nodes.toIterator
    }

    def getId(detail: Node): String = {
        (detail \ "id").text
    }

    def getUser(detail: Node): String = {
        (detail \ "user").text
    }

    def getDetailList(details: Iterator[Node]): Array[String] = {
        var list = ArrayBuffer[String]()
        while (details.hasNext) {
            val d = details.next
            val user = getUser(d)
            val id = getId(d)
            val formattedText = user + ":" + id
            list += formattedText
        }
        list.toArray
    }

    def main(args: Array[String]) {

        val conf = new SparkConf().setAppName("Details")
        val sc: SparkContext = new SparkContext(conf)

        val lines = sc.wholeTextFiles("file:///path/to/files/")
        val xmlStrings = lines.map(line => line._2)
        val detailsRecords = xmlStrings.map(getDetails)
        val detailsList = detailsRecords.map(getDetailList)

        spark.stop()
    }
}

И два файла с примерами ...

test.xml

<details>
  <detail>
    <user>Dan</user>
    <id>5555</id>
  </detail>
  <detail>
    <user>Mike</user>
    <id>6666</id>
  </detail>
</details>

test2.xml

<details>
  <detail>
    <user>John</user>
    <id>1234</id>
  </detail>
  <detail>
    <user>Joe</user>
    <id>5678</id>
  </detail>
</details>

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Это было на 4 месяца позже, но я думаю, что получил только ответ для вас.

Проблема заключается в функции getDetails().Вы должны сообщить Scala, что определено как «узел», в данном случае это <detail>.Поэтому просто измените ваш код, как показано ниже:

  def getDetails(xmlstring: String): Iterator[Node] = {
    val nodes = XML.loadString(xmlstring) \\ "detail"
    nodes.toIterator
  }

Добавление \\ "detail" в конце XML.loadString() - это все, что вам нужно, чтобы код работал так, как вы ожидаете.

Cheers,

0 голосов
/ 09 октября 2018

Вы должны использовать XML для Spark .

С этой библиотекой вы можете читать все ваши XML-файлы, например:

import org.apache.spark.sql.SQLContext

val sqlContext = new SQLContext(sc)

val df = sqlContext.read
   .format("com.databricks.spark.xml")
   .option("rowTag", "detail")
   .load("/home/path-with-xml-files")

Это генерирует DataFrame со схемой:

+----+----+
|  id|user|
+----+----+
|5555| Dan|
|6666|Mike|
|1234|John|
|5678| Joe|
+----+----+

. Затем получите массив из этого DF:

val id_users_array = df.collect

Этот массив имеет тип:

id_users_array: Array[org.apache.spark.sql.Row] = Array([5555,Dan], [6666,Mike], [1234,John], [5678,Joe])

Если выхочу печатать только идентификаторы:

id_users_array.map(r => r.get(0)).foreach(println)

выходы:

5555
6666
1234
5678

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...