这可能是一个很长的镜头,但认为它不会让人感到伤心。我试图在pyspark中使用Elsevier's open-sourced spark-xml-utils
package来使用XSLT转换一些XML记录。
我已经在一些探索性代码上取得了一些成功:
# open XSLT processor from spark's jvm context
with open('/tmp/foo.xsl', 'r') as f:
proc = sc._jvm.com.elsevier.spark_xml_utils.xslt.XSLTProcessor.getInstance(f.read())
# transform XML record with 'proc'
with open('/tmp/bar.xml','r') as f:
transformed = proc.transform(f.read())
但是,在更现实的情况下,我无法将proc.transform
放入lambda
地图功能,收到的错误类似于:
"调用o55时出错。 getstate 。跟踪: py4j.Py4JException:方法 getstate ([])不存在于 py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318) 在 py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326) 在py4j.Gateway.invoke(Gateway.java:272)at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) 在py4j.commands.CallCommand.execute(CallCommand.java:79)at py4j.GatewayConnection.run(GatewayConnection.java:214)at java.lang.Thread.run(Thread.java:748)"
当我得到一个小例子来处理单个记录时,那是在pyspark shell中运行的,我假设它正在使用火花驱动器。但是在上面提到的map函数中,这是通过Livy和YARN在Spark中引入的工作者。这个SO question/answer表明我可能无法在该上下文中使用jvm中的函数。
现在,spark-xml-utils
库在scala中提供了一些示例,正是我想做的事情:
import com.elsevier.spark_xml_utils.xslt.XSLTProcessor
val xmlKeyPair = sc.sequenceFile[String, String]("s3n://spark-xml-utils/xml/part*")
val stylesheet = sc.textFile("s3n://spark-xml-utils/stylesheets/srctitle.xsl").collect.head
val srctitles = xmlKeyPair.mapPartitions(recsIter => {
val proc = XSLTProcessor.getInstance(stylesheet)
recsIter.map(rec => proc.transform(rec._2))
})
我想知道,如何将其转换为pyspark代码,以便我可以在RDD上运行它?理想情况下,在具有以下输入和输出格式的RDD上:
id | document | other | columns
-----------------------------------------------------
sprog | <xml here...> | more | data
baz | <xml here...> | more | data
可能会成为
id | document | other | columns
-----------------------------------------------------
sprog | <*transformed* xml here...> | more | data
baz | <*transformed* xml here...> | more | data
非常感谢任何帮助或建议。
更新8/28/2018:还尝试了mapPartitions
,没有骰子。 __getstate__()