在使用Spark时,有时候主函数入口参数过多的时候,会特别复杂,这个时候我们可以将相应的参数写在xml文件中,然后只要将xml文件的路径传进去即可,这里的xml路径可以是本地的,也可以是hdfs上的。

scala提供了类似于Xpath的语法来解析xml文件,其中很重要的两个操作符是”\”
和 “\\”

  • \ :根据搜索条件得到下一个节点
  • \\:根据条件获取所有的节点
1
2
3
4
5
6
7
8
9
10
<configure>
<input>
<name>app_feature_goods</name>
<hdfs>/user/path/to/goods</hdfs>
</input>
<input>
<name>app_feature_user</name>
<hdfs>/user/path/to/user</hdfs>
</input>
</configure>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
val input = args(0)
val xml = XML.load(input)


// 找到所有的一级节点 input
val input_list = xml\"input"
input_list.foreach(println)

// 遍历每个一级节点,得到具体的值
for(one <- input_list){
println(one\"name")
println((one\"name").text)
println(one\"hdfs")
println((one\"hdfs").text)
}

// 得到所有的name
val name_list = xml\\"name"
name_list.map(one => one.text).foreach(println)

// 获取所有hdfs
val hdfs_list = xml\\"hdfs"
hdfs_list.map(one => one.text).foreach(println)

// 获取具有class的值
println(xml\"input"\"name"\\"@class")

// 打印出具有class属性的name值和hdfs值
println((xml\\"name").filter(_.attribute("class").exists(_.text.equals("test"))).text)
println((xml\\"hdfs").filter(_.attribute("class").exists(_.text.equals("test"))).text)

打印出的信息为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<input>
<name>app_feature_goods</name>
<hdfs>/user/path/to/goods</hdfs>
</input>
<input>
<name>app_feature_user</name>
<hdfs>/user/path/to/user</hdfs>
</input>
<input>
<name class="test">app_feature_user_test</name>
<hdfs class="test">/user/path/to/user_test</hdfs>
</input>
-------------
<name>app_feature_goods</name>
app_feature_goods
<hdfs>/user/path/to/goods</hdfs>
/user/path/to/goods
<name>app_feature_user</name>
app_feature_user
<hdfs>/user/path/to/user</hdfs>
/user/path/to/user
<name class="test">app_feature_user_test</name>
app_feature_user_test
<hdfs class="test">/user/path/to/user_test</hdfs>
/user/path/to/user_test
-------------
app_feature_goods
app_feature_user
app_feature_user_test
-------------
/user/path/to/goods
/user/path/to/user
/user/path/to/user_test
-------------
test
-------------
app_feature_user_test
/user/path/to/user_test
-------------

Process finished with exit code 0

当然还存在一种情况就是XML文件存在于hdfs之上,这时候就不能直接load xml文件里,不过可以通过下面一种方法获得

1
2
var rdd = sc.textFile(xml_path)
val xml = XML.loadString(rdd.collect().mkString("\n"))

接下来便可以通过上边的方法进行解析了。


打开微信扫一扫,关注公众号【搜索与推荐Wiki】