1

次のような大きな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>
4

2 に答える 2

2

Scala XML (遅くなる可能性があり、メモリを大量に消費する可能性があります)

cmbaxter からの回答は技術的に正しいですが、「flatMap that shit」パターンで改善できます:-)

    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 のスケーリング (高速で必要なメモリが少ない)

しかし、これは最速の方法ではありません。ベンチマークが示すように、Scala 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

また、Anti XMLライブラリもあり、ベンチマークで非常によく見え、非常に優れた API を備えているようです。残念ながら、Scala 2.10 では実行できなかったため、実行例を提供できません。

結論

上記の例を使用すると、小さなテスト アプリケーションを作成できるはずです。これらを使用して、独自のベンチマークを実行できます。上記のベンチマークを見ると、Scales XML が問題を解決する可能性があると思います。しかし、実際の測定がなければ、これは単なる推測に過ぎません。

自分自身をベンチマークし、おそらく結果を投稿できます。

于 2013-08-13T10:45:09.177 に答える