I am trying to
- Load a CSV File
- Read IDs from the file
- Load an external xml file for each Id
- Read some names from XML
- Write out the ID and names into new CSV File
I am new to Haskell and really wanna learn it, I am still in the copy and paste phase of understanding. I have found tutorials for each part on its own, but I struggle with combining them.
The CSV is simple, like:
736572,"Mount Athos"
6697806,"North Aegean"
I use Cassava to read the CSV and HandsomeSoup for XML reading.
Here my attempt to read the id, load the xml and print the names from the xml at least.
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
import Text.XML.HXT.Core
import Text.HandsomeSoup
import Data.List
import Data.Char
getPlaceNames::String->String->String
getPlaceNames pid name = do
let doc = fromUrl ("http://api.geonames.org/get?geonameId="++pid++"&username=demo")
c<-runX $ doc >>> css "alternateNames" >>> deep getText
return (head c)
main :: IO ()
main = do
csvData <- BL.readFile "input.csv"
case decode NoHeader csvData of
Left err -> putStrLn err
Right v -> V.forM_ v $ \ ( pid, name ) ->
putStrLn $ getPlaceNames pid name
I think I am doing something wrong when I call getPlaceNames and return the names. I am not even sure if I should use the 'do' statement in getPlaceNames.
Error says
Couldn't match expected type ‘[[Char]]’
with actual type ‘IO [String]’
In a stmt of a 'do' block:
c <- runX $ doc >>> css "alternateNames" >>> deep getText
In the expression:
do { let doc
= fromUrl
("http://api.geonames.org/get?geonameId="
++ pid ++ "&username=demo");
c <- runX $ doc >>> css "alternateNames" >>> deep getText;
return (head c) }
In an equation for ‘getPlaceNames’:
getPlaceNames pid name
= do { let doc = ...;
c <- runX $ doc >>> css "alternateNames" >>> deep getText;
return (head c) }
But thats probably just one thing that I am doing wrong because of my lack of understanding of monads and bindings.
Any help appreciated, even if its just a pointer to the right docs.
Cheers
Bjorn
Thanks to chi I've figured out the whole procedure. I am posting my code for anyone else who needs to do something similar.
In the end I did not only take the names from the xml but multiple fields. So I changed
getPlaceNamestogtPlaceDetails.I show the full code, because it also shows how I read different fields from the XML and how I merge
alternateNameelements in the XML to one String.For example the input.csv line
736572,"Mount Athos"maps into out.csv this