【问题标题】:Parsing xml files with scala用scala解析xml文件
【发布时间】:2018-05-08 15:53:38
【问题描述】:

我正在尝试使用 scala 和 spark 处理 xml 文件。

我有这个架构:

root
 |-- IdKey: long (nullable = true)
 |-- Value: string (nullable = true)
 |-- CDate: date (nullable = true)

我想处理这个xml文件:

<Item>
    <CDate>2018-05-08T00:00::00</CDate>
    <ListItemData>
        <ItemData>
            <IdKey>2</IdKeyData>
            <Value>1</Value>
        </ItemData>
        <ItemData>
            <IdKey>61</IdKeyData>
            <Value>2</Value>
        </ItemData>
    <ListItemData>
</Item>

我正在使用此代码:

sqlContext.read.format("com.databricks.spark.xml") .option("rowTag", "Item") .schema(schema) .load(xmlFile)

但我的结果是一个没有 CDate 列的表格:

+------------+
IdKey         |Value    | CDate |
+------------+
|61           |1        | null
|2            |2        | null

是否可以使用此架构解析 xml 文件?我想获得这个值:

+------------+
IdKey         |Value    | CDate |
+------------+
|61           |1        | 2018-05-08T00:00::00
|2            |2        | 2018-05-08T00:00::00

谢谢

【问题讨论】:

  • 您的 xml 数据是有效的 xml 吗?我认为它不是有效的 xml 数据
  • 我忘记关闭标签了。但是xml原件是正确的。谢谢!

标签: xml scala parsing apache-spark


【解决方案1】:

我可以将您的 xml 视为无效 在您的情况下,有效的 xml 应该如下所示

<Item>
    <CDate>2018-05-08T00:00::00</CDate>
    <ListItemData>
    <ItemData>
        <IdKey>2</IdKey>
        <Value>1</Value>
    </ItemData>
    <ItemData>
        <IdKey>61</IdKey>
        <Value>2</Value>
    </ItemData>
    </ListItemData>
</Item>

如果你有这个更正的xml 数据,那么你可以创建一个schema

val innerSchema = StructType(
  StructField("ItemData",
    ArrayType(
      StructType(
        StructField("IdKey",LongType,true)::
          StructField("Value",LongType,true)::Nil
      )
    ),true)::Nil
)
val schema = StructType(
  StructField("CDate",StringType,true)::
  StructField("ListItemData", innerSchema, true):: Nil
)

应用此schema 读取xml 文件

val df = spark.sqlContext.read.format("com.databricks.spark.xml")
  .option("rowTag", "Item")
  .schema(schema)
  .load(xmlFile)
  //Selecy nested field and explode to get the flattern result
  .withColumn("ItemData", explode($"ListItemData.ItemData"))
  .select("CDate", "ItemData.*") // select required column

现在你可以获得所需的输出

+--------------------+-----+-----+
|CDate               |IdKey|Value|
+--------------------+-----+-----+
|2018-05-08T00:00::00|2    |1    |
|2018-05-08T00:00::00|61   |2    |
+--------------------+-----+-----+

你可以让spark自己推断schema会得到同样的结果

val df = spark.sqlContext.read.format("com.databricks.spark.xml")
  .option("rowTag", "Item")
  //.schema(schema)
  .load(xmlFile)
  .withColumn("ItemData", explode($"ListItemData.ItemData"))
  .select("CDate", "ItemData.*")

希望这会有所帮助!

【讨论】:

  • 谢谢@Shankar 我正在测试这个解决方案。这似乎是正确的。
  • 你知道是否可以配置多个rowTag?对于具有不同 xml 标签的情况。
  • 我不确定这是否可以做到,您可以在此处查看选项。 github.com/databricks/spark-xml#features
【解决方案2】:
you can do something like this this will output //( 2018-05-08T00:00::00   2 1   61 2   ,2018-05-08T00:00::00)
then you can format as you want i think, it will help.

  object XMLDemo extends App {
  val xmlElem: Elem = <Item>
  <CDate>2018-05-08T00:00::00</CDate>
  <ListItemData>
  <ItemData>
  <IdKeyData>2</IdKeyData>
  <Value>1</Value>
  </ItemData>
  <ItemData>
  <IdKeyData>61</IdKeyData>
  <Value>2</Value>
  </ItemData>
  </ListItemData>
  </Item>

  val lb: ListBuffer[String] = ListBuffer()
  val date: NodeSeq = xmlElem \\ "CDate"

  val r: immutable.Seq[String] = xmlElem.map {
    x => x.text
  }

  println(r.mkString(" ").replaceAll(" ","").replaceAll("\n"," "), date.text)
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    • 2014-08-23
    相关资源
    最近更新 更多