解析Java或斯卡拉平,属性重XML的最快方法(Fastest way to parse flat,

2019-10-18 11:54发布

如果我有类似下面的大XML文件。 什么是分析它在Java或Scala中的最快方式。 流单个元素是重要的,但不是绝对必要

所有我在从每个结果对象获取属性值有趣。

<Response>
    <Result att1="1", att2="2", att3="3", att4="4", att5="5"/>
    <Result att1="1", att2="2", att3="3", att4="4", att5="5"/>
    <Result att1="1", att2="2", att3="3", att4="4", att5="5"/>
    <Result att1="1", att2="2", att3="3", att4="4", att5="5"/>
</Response>

Answer 1:

Scala的XML(可能是缓慢和内存饥饿)

从cmbaxter答案是正确的技术,但它可以通过改善“flatMap狗屎”的格局 :-)

    import io.Source
    import xml.pull._

    // Make it "def", because the Source is stateful and may be exhausted after it is read
    def xmlsrc=Source.fromString("""<Response>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         | </Response>""")

    // Also as "def", because the result is an iterator that may be exhausted
    def xmlEr=new XMLEventReader(xmlsrc)

    // flatMap keeps the "outer shape" of the type it operates, so we are still dealing with an iterator

    def attrs = xmlEr.flatMap{
         |   case e : EvElemStart => e.attrs.map(a => (a.key, a.value))
         |   case _ => Iterable.empty
         | }

    // Now lets look what is inside:
    attrs.foreach(println _)

    // Or just let's collect all values from "att5"
    attrs.collect{ case (name, value) if name == "att5" =>value}.foreach(println _)

秤XML(更快和需要更少的内存)

但是,这不会是最快的方式。 斯卡拉API是相当缓慢和内存饿相比其他解决方案,如基准测试显示。 但幸运的是有一个更快,更少的内存饿的解决方案:

    import scales.utils._
    import ScalesUtils._
    import scales.xml._
    import ScalesXml._
    import java.io.StringReader

    def xmlsrc=new StringReader("""<Response>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         |     <Result att1="1" att2="2" att3="3" att4="4" att5="5"/>
         | </Response>""")
    def pull=pullXml(xmlsrc)
    def attributes = pull flatMap {
         |   case Left(elem : Elem) => elem.attributes
         |   case _ => Nil
         | } map (attr => (attr.name, attr.value))

    attributes.foreach(println _)

不要忘了关闭你的迭代器,你与他们做了。 这是没有必要的,因为我有工作StringReader

反XML

也有反XML库,它看起来相当不错的基准,而且似乎有一个非常漂亮的API。 不幸的是我不能让它使用Scala 2.10跑,所以我不能提供一个运行实例。

结论

通过上面的例子,你应该可以写一个小的测试应用程序。 有了这些,你可以运行自己的基准。 看上面引述的基准,我想这秤XML可以解决你的问题。 但是,如果没有真正的meassuring,这是真的只是一种猜测。

基准自己,也许你可以发布你的结果。



Answer 2:

如果你的文件很大,你不希望整个事情加载到内存(即DOM),那么你可以采取一个路径是拉解析路径。 如果你想要做拉解析Scala中,以检查属性寻找“开始元素”的事件,那么你可以做这样的事情:

import scala.io.Source
import java.io.File
import scala.xml.pull.XMLEventReader
import scala.xml.pull.EvElemStart

val src = Source.fromFile(new File(pathToXml))
val reader = new XMLEventReader(src)
reader foreach{ 
  case EvElemStart(_, _, attrs, _) =>
    //do something here

  case _ =>
}

按照这一办法应确保您的文件不会被读入内存,并应该是快速的。



文章来源: Fastest way to parse flat, attribute-heavy xml in Java or Scala