如果字段缺失,则按顺序xml解析节点

时间:2015-08-14 02:19:49

标签: xml scala

在Scala中,我尝试为每封邮件返回appidplaytime_forever的值。我得到了值,但它们没有用冒号分隔

我的目标是返回类似240:7110:99103:104:NA以及NA:4:NA

的字符串
<response>
    <game_count>120</game_count>
    <games>
        <message>
            <appid>240</appid>
            <playtime_forever>103</playtime_forever>
        </message>
        <message>
            <appid>7110</appid>
            <playtime_forever>104</playtime_forever>
            <playtime_2weeks>4</playtime_2weeks>
        </message>
        <message>
            <appid>99</appid>
        </message>
        ....

我尝试这样做,但我的代码不会在值之间打印:

 import scala.xml._
 import collection.mutable.HashMap
 import java.nio.file.{Paths, Files}
 import java.io.IOException
import java.io.FileWriter

object HelloWorld {
    def main(args: Array[String]) {
    val noDupFile="nodup_steam_out.txt"
    val api="BLAH"
    val res:String="76561198036298569"
        try{
        var id=""
        var playtime_forever=""
        var url="http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key="+api+"&steamid="+res+"&format=xml"
            var str = scala.io.Source.fromURL(url.toString,"utf-8").mkString        
            var x=xml.XML.loadString(str)       
            var allNodes = x \\ "response" \\ "games"   
            println(allNodes)
            println("===")
            allNodes.foreach(n => {
                id+=((n\\ "message"\\ "appid").text.mkString+":")
                playtime_forever+=((n\\ "message"\\ "playtime_forever").text.mkString+":")
            })
            id=id.dropRight(1)
            playtime_forever=playtime_forever.dropRight(1)
            println(id)
            println("===")
            println(playtime_forever)
        }
        catch{
            case e:  IOException=> println("4.Bad page request (profile locked down)")
            println("NA")
        }
}}

我的输出:

===
2407110685068606900240024202430151201990022330223201739024720101306020603032380323903240041700451008190499004267022380709008980122101222047810387204778099810655604432032104020920917003953032703956098800109700200550981009820092800728505523015001510152
0153020129010545020434020676020488020912069802116002117401088002041006910692028050201280984001153202169102076507302085802126804952020071020510020579070100701107012076708870200510224300224920224940224540220440227860219740322330233250244770244850248390
23560020642024154024347026176026420026430026655026911025197029402020181031704030769027567026164032873037397034005034262034611023019065980:
1031047600150016310639462850435310320238051159473703808182726891233201693412054165342792324301751299015495132390460443873851954101720404392861016201162121001233019337963364406457370269616429320390000946410560047166321029080898705251113602444197828434
8011527577224275325600701902340:

===

1 个答案:

答案 0 :(得分:0)

我提取您的示例x​​ml代码并将其放在message.xml

  <response>
     <games>
      <message>
         <appid>240</appid>
         <playtime_forever>103</playtime_forever>
     </message>
     <message>
         <appid>7110</appid>
         <playtime_forever>104</playtime_forever>
         <playtime_2weeks>4</playtime_2weeks>
     </message>
     <message>
         <appid>99</appid>
     </message>
    </games>

然后按照以下代码解决问题。

 import scala.xml.{ NodeSeq, XML }
 object XmlPrint extends App {
    // change this line according to your situation
    val originalXML = XML.load(getClass.getClassLoader.getResourceAsStream("message.xml"))

    val messageNodes = originalXML \\ "games" \\ "message"
    val attrCollector = (List[String](), List[String](), List[String]())

    def getValueFromNode(node: NodeSeq, attrName: String) = {
        (node \ attrName).find(_.label == attrName).map(_.text).getOrElse("N/A")
    }

    //(List(240, 7110, 99),List(103, 104, N/A),List(N/A, 4, N/A))
    val (appIds, foreverTimes, twoWeeks) = messageNodes.map { messageNode =>
        (
            // here, assuming message node can  have at most three sub nodes
            // appid playtime_forever playtime_2weeks
            getValueFromNode(messageNode, "appid"),
            getValueFromNode(messageNode, "playtime_forever"),
            getValueFromNode(messageNode, "playtime_2weeks")
        )
    }.foldRight(attrCollector)({
        (elem, attrTuple) => {
            val (l1, l2, l3) = attrTuple
            (elem._1 :: l1, elem._2 :: l2, elem._3 :: l3)
        }
    })

    // 240:7110:99
    println(appIds.mkString(":"))
    // 103:104:N/A
    println(foreverTimes.mkString(":"))
    // N/A:4:N/A
    println(twoWeeks.mkString(":"))
}

无论如何,希望它是你想要的。