Apache spark Spark中的Xml处理

Apache spark Spark中的Xml处理,apache-spark,Apache Spark,情景: 我的输入将是多个小XML,我应该将这些XML作为RDD读取。执行与另一个数据集的连接,形成RDD并将输出作为XML发送 是否可以使用spark读取XML,将数据作为RDD加载?如果可能,如何读取XML 示例XML: <root> <users> <user> <account>1234<\account> <name>name_1<

情景: 我的输入将是多个小XML,我应该将这些XML作为RDD读取。执行与另一个数据集的连接,形成RDD并将输出作为XML发送

是否可以使用spark读取XML,将数据作为RDD加载?如果可能,如何读取XML

示例XML:

<root>
    <users>
        <user>
              <account>1234<\account>
              <name>name_1<\name>
              <number>34233<\number>
         <\user>
         <user>
              <account>58789<\account>
              <name>name_2<\name>
              <number>54697<\number>
         <\user>    
    <\users>
<\root>

1234
姓名1
34233
58789
姓名2
54697

如何将其加载到RDD中?

是的,这是可能的,但具体细节将根据您采取的方法而有所不同

  • 如前所述,如果文件很小,最简单的解决方案是使用
    SparkContext.wholeTextFiles
    加载数据。它以
    RDD[(String,String)]
    的形式加载数据,其中第一个元素是路径,第二个是文件内容。然后像在本地模式中一样单独解析每个文件
  • 对于较大的文件,您可以使用。
    • 如果结构简单,您可以使用
      textinputformat.record.delimiter
      拆分记录。你可以找到一个简单的例子。输入不是XML,但您应该告诉您如何继续
    • 否则,Mahout提供
  • 最后,可以使用
    SparkContext.textFile
    读取文件,并在以后调整分区之间的记录跨度。从概念上讲,这意味着类似于创建滑动窗口或:

    • 使用
      mapPartitionsWithIndex
      partitions来识别分区之间断开的记录,收集断开的记录
    • 使用第二个
      mapPartitionsWithIndex
      修复损坏的记录
编辑

还有一个相对较新的软件包,允许您按标签提取特定记录:

val df = sqlContext.read
  .format("com.databricks.spark.xml")
   .option("rowTag", "foo")
   .load("bar.xml")

下面是使用
HadoopInputFormats
在spark中读取XML数据的方法,如@zero323所述

输入数据:

<root>
    <users>
        <user>
            <account>1234<\account>
            <name>name_1<\name>
            <number>34233<\number>
        <\user>
        <user>
            <account>58789<\account>
            <name>name_2<\name>
            <number>54697<\number>
        <\user>
    <\users>
<\root>
+-------+------+------+
|account|  name|number|
+-------+------+------+
|   1234|name_1| 34233|
|  58789|name_2| 54697|
+-------+------+------+
代码:

objecttester\u加载程序{
案例类用户(帐户:字符串,名称:字符串,编号:字符串)
def main(参数:数组[字符串]):单位={
val sparkHome=“/usr/big_data_tools/spark-1.5.0-bin-hadoop2.6/”
val sparkMasterUrl=”spark://SYSTEMX:7077"
var jars=新数组[字符串](3)
jars(0)=“/home/hduser/Offload\u Data\u Warehouse\u Spark.jar”
jars(1)=“/usr/big_data_tools/jars/Spark_jar/avro/Spark-avro_2.10-2.0.1.jar”
val conf=new SparkConf().setAppName(“XML读取”)
conf.set(“spark.serializer”、“org.apache.spark.serializer.KryoSerializer”)
.setMaster(“本地”)
.set(“spark.cassandra.connection.host”,“127.0.0.1”)
.setSparkHome(斯巴克霍姆)
.set(“spark.executor.memory”,“512m”)
.set(“spark.default.deployCores”,“12”)
.set(“火花芯最大值”,“12”)
.setJars(jars)
val sc=新的SparkContext(配置)
val sqlContext=新的sqlContext(sc)
导入sqlContext.implicits_
//----从XML加载用户
//调用函数1.1
val pages=readFile(“src/input_data”、“”、“”、sc)
val xmlUserDF=pages.map{tuple=>
{
val account=extractField(元组,“account”)
val名称=提取字段(元组,“名称”)
val编号=提取字段(元组,“编号”)
用户(帐户、名称、号码)
}
}.toDF()
println(xmlUserDF.count())
xmlUserDF.show()
}
职能:

def readFile(路径:String,开始标签:String,结束标签:String,
sc:SparkContext)={
val conf=新配置()
conf.set(XmlInputFormat.START\u标记\u键,START\u标记)
conf.set(XmlInputFormat.END_标记_键,END_标记)
val rawXmls=sc.newapiHadoop文件(
路径,classOf[XmlInputFormat],classOf[LongWritable],
类别[Text],conf)
map(p=>p._2.toString)
}
def extractField(元组:字符串,标记:字符串)={
var value=tuple.replaceAll(“\n”和“)。replace(这将帮助您

package packagename;

import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.SparkSession;

import com.databricks.spark.xml.XmlReader;

public class XmlreaderSpark {
    public static void main(String arr[]){
    String localxml="file path";
    String booksFileTag = "user";

    String warehouseLocation = "file:" + System.getProperty("user.dir") + "spark-warehouse";
   System.out.println("warehouseLocation" + warehouseLocation);
    SparkSession spark = SparkSession
              .builder()
              .master("local")
              .appName("Java Spark SQL Example")
              .config("spark.some.config.option", "some-value").config("spark.sql.warehouse.dir", warehouseLocation)
              .enableHiveSupport().config("set spark.sql.crossJoin.enabled", "true")
              .getOrCreate();
    SQLContext sqlContext = new SQLContext(spark);

    Dataset<Row> df = (new XmlReader()).withRowTag(booksFileTag).xmlFile(sqlContext, localxml);
    df.show();

    }
}
packagename;
导入org.apache.spark.sql.Dataset;
导入org.apache.spark.sql.Row;
导入org.apache.spark.sql.SQLContext;
导入org.apache.spark.sql.SparkSession;
导入com.databricks.spark.xml.XmlReader;
公共类XmlreaderSpark{
公共静态void main(字符串arr[]{
字符串localxml=“文件路径”;
字符串booksFileTag=“user”;
String warehouseLocation=“文件:”+System.getProperty(“user.dir”)+“spark warehouse”;
System.out.println(“仓库位置”+仓库位置);
火花会话火花=火花会话
.builder()
.master(“本地”)
.appName(“Java Spark SQL示例”)
.config(“spark.some.config.option”,“some value”).config(“spark.sql.warehouse.dir”,warehouseLocation)
.enableHiveSupport().config(“set spark.sql.crossJoin.enabled”、“true”)
.getOrCreate();
SQLContext SQLContext=新的SQLContext(spark);
数据集df=(新的XmlReader()).withRowTag(booksFileTag).xmlFile(sqlContext,localxml);
df.show();
}
}
您需要在POM.xml中添加此依赖项:

<dependency>
   <groupId>com.databricks</groupId>
   <artifactId>spark-xml_2.10</artifactId>
   <version>0.4.0</version>
</dependency>

com.databricks
spark-xml_2.10
0.4.0
并且您的输入文件格式不正确


谢谢。

对于简单的案例,有两个很好的选择:

  • wholeTextFiles
    。在XML解析器中使用map方法,可以是Scala XML pull解析器(编码更快)或SAX pull解析器(性能更好)
  • Hadoop streaming XMLInputFormat
必须定义开始和结束标记才能处理它,但是,它会为每个用户标记创建一个分区
  • sparkxml包
    也是一个不错的选择
  • 使用所有选项,您只能处理简单的XML,这些XML可以解释为具有行和列的数据集

    然而,如果我们把它弄得有点复杂,那么这些选项就没有用了

    例如,如果您还有一个实体:

    <root>
        <users>
        <user>...</users>
        <companies>
        <company>...</companies>
    </root>
    
    
    ...
    ...