2010-05-17 5 views
11

Je suis en train d'analyser un flux rss qui ressemble à ceci pour l'attribut "date":Scala: XML Attribute analyse syntaxique

<rss version="2.0"> 
<channel> 
    <item> 
     <y:c date="AA"></y:c> 
    </item> 
</channel> 
</rss> 

J'ai essayé plusieurs versions différentes de ce: (rssfeed contient les données RSS)

println(((rssFeed \\ "channel" \\ "item" \ "y:c" \"date").toString)) 

Mais rien ne semble fonctionner. Qu'est-ce que je rate?

Toute aide serait vraiment appréciée!

+1

'rssFeed'? Ne devrait-il pas être 'rss'? – VonC

+1

rssFeed est une variable contenant les données RSS – Chris

Répondre

18

Le "y" dans <y:c est un préfixe d'espace de noms. Ça ne fait pas partie du nom. De plus, les attributs sont référencés avec un '@'. Essayez ceci:

println(((rssFeed \\ "channel" \\ "item" \ "c" \ "@date").toString)) 
14

Les attributs sont récupérés en utilisant le sélecteur "@attrName". Ainsi, votre sélecteur doit effectivement être quelque chose comme ce qui suit:

println((rssFeed \\ "channel" \\ "item" \ "c" \ "@date").text) 
+1

Notez le .text pour obtenir la date comme une chaîne plutôt que comme un noeud – sblundy

+1

En effet. La méthode 'text' est généralement préférable à' toString' car elle gère avec élégance le cas où votre sélecteur a saisi un morceau de XML plutôt qu'un noeud 'Text'. –

3

Aussi, pensez à la différence entre \ et \\. \\ cherche une descendant, pas seulement un enfant, comme celui-ci (note qu'il saute de canal à c, sans objet):

scala> (rssFeed \\ "channel" \\ "c" \ "@date").text 
res20: String = AA 

Ou ce genre de chose si vous voulez juste tous les < c > éléments, et ne se soucient pas de leurs parents:

scala> (rssFeed \\ "c" \ "@date").text    
res24: String = AA 

et ce paramètre définit un chemin exact:

scala> (rssFeed \ "channel" \ "item" \ "c" \ "@date").text 
res25: String = AA 
3

Pensez à utiliser compréhensions de séquence, aussi. Ils sont utiles pour traiter XML, en particulier si vous avez besoin de conditions compliquées.

Pour le cas simple:

for { 
    c <- rssFeed \\ "@date" 
} yield c 

vous donne l'attribut de la date de tout rssfeed.

Mais si vous voulez quelque chose de plus complexe:

val rssFeed = <rss version="2.0"> 
       <channel> 
        <item> 
        <y:c date="AA"></y:c> 
        <y:c date="AB"></y:c> 
        <y:c date="AC"></y:c> 
        </item> 
       </channel> 
       </rss> 

val sep = "\n----\n" 

for { 
    channel <- rssFeed \ "channel" 
    item <- channel \ "item" 
    y <- item \ "c" 
    date <- y \ "@date" if (date text).equals("AA") 
} yield { 
    val s = List(channel, item, y, date).mkString(sep) 
    println(s) 
} 

Vous donne:

<channel> 
         <item> 
          <y:c date="AA"></y:c> 
          <y:c date="AB"></y:c> 
          <y:c date="AC"></y:c> 
         </item> 
         </channel> 
    ---- 
    <item> 
          <y:c date="AA"></y:c> 
          <y:c date="AB"></y:c> 
          <y:c date="AC"></y:c> 
         </item> 
    ---- 
    <y:c date="AA"></y:c> 
    ---- 
    AA