Haskell读取CSV文件->;从url加载XML文件->;再次写出CSV文件

Haskell读取CSV文件->;从url加载XML文件->;再次写出CSV文件,xml,csv,haskell,hxt,Xml,Csv,Haskell,Hxt,我正在努力 加载CSV文件 从文件中读取ID 为每个Id加载一个外部xml文件 从XML中读取一些名称 将ID和名称写入新的CSV文件 我是Haskell的新手,非常想学习它,我仍然处于理解的复制和粘贴阶段。我已经找到了每个部分各自的教程,但我很难将它们结合起来 CSV很简单,如: 736572,"Mount Athos" 6697806,"North Aegean" 我用于读取CSV和XML 在这里,我尝试读取id,加载xml并至少从xml打印名称 {-# LANGUAGE ScopedTy

我正在努力

  • 加载CSV文件
  • 从文件中读取ID
  • 为每个Id加载一个外部xml文件
  • 从XML中读取一些名称
  • 将ID和名称写入新的CSV文件
  • 我是Haskell的新手,非常想学习它,我仍然处于理解的复制和粘贴阶段。我已经找到了每个部分各自的教程,但我很难将它们结合起来

    CSV很简单,如:

    736572,"Mount Athos"
    6697806,"North Aegean"
    
    我用于读取CSV和XML

    在这里,我尝试读取id,加载xml并至少从xml打印名称

    {-# 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
    
    {-#语言范围的TypeVariables}
    将限定数据.ByteString.Lazy导入为BL
    导入数据.Csv
    导入符合条件的数据。向量为V
    导入Text.XML.HXT.Core
    导入Text.HandsomeSoup
    导入数据。列表
    导入数据.Char
    getPlaceNames::String->String->String
    getPlaceNames pid name=do
    让doc=fromUrl(“http://api.geonames.org/get?geonameId=“++pid++”&username=demo”)
    c> >css“alternateNames”>>>deep getText
    报税表(总目c)
    main::IO()
    main=do
    csvData putStrLn错误
    右v->v.forM\uV$\(pid,名称)->
    putStrLn$getPlaceNames pid名称
    
    当我调用getPlaceNames并返回名称时,我认为我做错了什么。我甚至不确定是否应该在getPlaceNames中使用“do”语句

    错误说

     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) }
    
    无法匹配预期的类型“[[Char]]”
    实际类型为“IO[String]”
    在“do”块的stmt中:
    c>>css“alternateNames”>>>deep getText
    在表达式中:
    让医生来
    =fromUrl
    ("http://api.geonames.org/get?geonameId="
    ++pid++“&username=demo”);
    c>>css“alternateNames”>>>深度getText;
    返回(标题c)}
    在“getPlaceNames”的方程式中:
    getPlaceNames pid名称
    =do{let doc=。。。;
    c>>css“alternateNames”>>>深度getText;
    返回(标题c)}
    
    但这可能只是我做错的一件事,因为我对单子和绑定缺乏理解

    感谢您的帮助,即使这只是指向正确文档的指针

    干杯


    比约恩

    多亏了池,我把整个过程都弄明白了。我为其他需要做类似事情的人发布我的代码

    最后,我不仅从xml中提取了名称,还提取了多个字段。 因此,我将
    getPlaceNames
    更改为
    gtPlaceDetails

    我展示了完整的代码,因为它还展示了如何从XML中读取不同的字段,以及如何将XML中的
    alternateName
    元素合并到一个字符串中

    {-# LANGUAGE ScopedTypeVariables #-}
    
    
    import qualified Data.ByteString.Lazy.Char8 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
    
    
    uppercase :: String -> String
    uppercase = map toUpper
    
    
    toLanguageStr :: (String, String) -> String
    toLanguageStr (lan,name) = uppercase lan ++ ":" ++ name
    
    
    getPlaceDetails::String->String->IO (Int,String,Float,Float,Float,Float,Float,Float,String,String)
    getPlaceDetails pid name = do
        let doc = fromUrl ("http://api.geonames.org/get?geonameId="++pid++"&username=demo")
    
        id<-runX $ doc >>> css "geonameId" >>> deep getText
        name<-runX $ doc >>> css "name" >>> deep getText
        s<- runX $ doc >>> css "south" >>> deep getText
        w<- runX $ doc >>> css "west" >>> deep getText
        n<- runX $ doc >>> css "north" >>>  deep getText
        e<- runX $ doc >>> css "east" >>> deep getText
        lat<- runX $ doc >>> css "lat" >>> deep getText
        lng<- runX $ doc >>> css "lng" >>> deep getText
        translations<- runX $ doc >>> css "alternateName" >>> (getAttrValue "lang" &&& (deep getText))
        terms<- runX $ doc >>> css "alternateNames" >>> deep getText
        return ( read (head id),head name, read (head lat), read (head lng), read (head s), read (head w), read (head n), read (head e), intercalate "|" $ map toLanguageStr translations, head terms )
    
    
    
    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 )->do
                details <- getPlaceDetails pid name
                BL.appendFile "out.csv" $ encode [details]
                BL.putStrLn  (encode [details]) 
    

    也许你需要
    fromUrl(“http://api.geonames.org/get?geonameId=“++pid++”&username=demo“
    。另外,你应该在
    getPlaceNames
    中添加一个类型签名:我想一旦你声明了你需要的内容,就会出现更多的错误来帮助你修复代码。很好,我编辑了我的帖子,并添加了类型删除和括号。错误消息现在已更改。仍然不明白出了什么问题。好的,现在您需要在
    getPlaceNames
    中返回
    IO[String]
    ,因为您在那里运行的是副作用的东西。然后,在
    main
    中,你需要
    做得很棒,你还回答了我脑海中的另一个问题。几乎在那里,它删除了所有编译错误,但不在main中打印任何内容。我将IO[String]改为IO String,因为我只使用了'c'的第一个元素。如果我用getPlaceName打印它,我会得到正确的打印结果。但当我把它打印在主屏幕上时,我什么也得不到,甚至连一个错误都没有。我将main改为
    Right v->v.forM\uv$\(pid,name)->putStrLn(getPlaceNames pid name)
    do pns一起工作我不是HXT专家,但看起来好像每个
    runX$doc>>…
    都在查询web,这不是很有效。您可以使用例如
    (x,y,z)>>((css“x”>>>deep-getText)&&&&(css“y”>>deep-getText)&&&(css“z”>>deep-getText))
    ,只调用一次
    runX
    。再说一次,我曾经用过HXT,所以我不确定。也不确定,但我昨天感觉到它花了相当长的时间来获取一个条目的数据。这就解释了原因。我将试用你的版本,看看它是否有效。试过了,没有成功。如果我理解正确,您可以尝试合并箭头。然后编译器抱怨类型不匹配,因为表达式将返回元组中的元组。我想我得先知道箭头是怎么工作的<代码>无法将模式中的预期类型“[(字符串,(字符串,字符串))]”与实际类型“(t0,t1,t2)”匹配:(x,y,z)
    啊,我的
    (x,y,z)我看到它正在返回一个列表。。。也许你还需要
    (x,(y,z))
    
    736572,"Mount Athos",40.15798,24.33021,40.11294,23.99234,40.4563,24.40044,"KO:아토스 산|:Aftónomos Periochí Agíou Órous|:Ágion Óros|:Ágio Óros|:Athos|NO:Áthos|EN:Autonomous Monastic State of the Holy Mountain|:Avtonómos Periokhí Ayíou Órous|:Áyion Óros|:Dhioíkisis Ayíou Órous|:Hagion Oros|:Holy Athonite Republic|LINK:http://en.wikipedia.org/wiki/Mount_Athos|CA:Mont Athos|FR:Mont Athos|EN:Mount Athos|FR:République monastique du Mont Athos|EL:Αυτόνομη Μοναστική Πολιτεία Αγίου Όρους","Aftonomos Periochi Agiou Orous,Aftónomos Periochí Agíou Órous,Agio Oros,Agion Oros,Athos,Autonome Monastike Politeia Agiou Orous,Autonomous Monastic State of the Holy Mountain,Avtonomos Periokhi Ayiou Orous,Avtonómos Periokhí Ayíou Órous,Ayion Oros,Dhioikisis Ayiou Orous,Dhioíkisis Ayíou Órous,Hagion Oros,Holy Athonite Republic,Mont Athos,Mount Athos,Republique monastique du Mont Athos,République monastique du Mont Athos,atoseu san,Ágio Óros,Ágion Óros,Áthos,Áyion Óros,Αυτόνομη Μοναστική Πολιτεία Αγίου Όρους,아토스 산"