2012-02-12 33 views
4

我正在努力通过xml-conduit将http-conduit的响应转换为XML文档。将http-conduit连接到xml-conduit

doPost函数获取XML文档并将其发布到服务器。服务器使用XML文档进行响应。

doPost queryDoc = do 
    runResourceT $ do 

     manager <- liftIO $ newManager def 
     req <- liftIO $ parseUrl hostname 

     let req2 = req 
       { method = H.methodPost 
       , requestHeaders = [(CI.mk $ fromString "Content-Type", fromString "text/xml" :: Ascii) :: Header] 
       , redirectCount = 0 
       , checkStatus = \_ _ -> Nothing 
       , requestBody = RequestBodyLBS $ (renderLBS def queryDoc) 
       } 

     res <- http req2 manager 
     return $ res 

以下工作并返回 '200':

let pingdoc = Document (Prologue [] Nothing []) (Element "SYSTEM" [] []) [] 
Response status headers body <- doPost pingdoc 
return (H.statusCode status) 

然而,当我尝试使用XML-管道解析响应主体,我碰到的问题:

Response status headers body <- doPost xmldoc 
let xmlRes' = parseLBS def body 

由此产生的汇编错误是:

Couldn't match expected type `L.ByteString' 
      with actual type `Source m0 ByteString' 
In the second argument of `parseLBS', namely `body' 
In the expression: parseLBS def body 
In an equation for `xmlRes'': xmlRes' = parseLBS def body 

我试过使用$ =和$$连接Source从http-conduit到xml-conduit,但我没有任何成功。

有没有人有任何提示指向我在正确的方向?提前致谢。

尼尔

回答

6

你可以使用httpLbs,而不是http,所以它返回一个懒惰ByteString而非Source - 的parseLBS功能被命名,因为这是它需要:一个大号 AZY YTE T tring。但是,正如你所提到的那样,最好使用两者直接基于的导管接口。要做到这一点,你应该从doPost删除runResourceT线,并使用以下方法来获取XML文档:

xmlRes' <- runResourceT $ do 
    Response status headers body <- doPost xmldoc 
    body $$ sinkDoc def 

它使用XML-管道的sinkDoc功能,从http-管道连接SourceSink从XML -导管。

连接完成后,必须使用runResourceT运行完整管道,以确保及时释放所有分配的资源。您的原始代码的问题是它从doPost内部过早地运行ResourceT;您应该通常在需要实际结果的地方使用runResourceT,因为管道必须完全在单个ResourceT的范围内运行。

顺便说一句,res <- http req2 manager; return $ res可以简化为http req2 manager

+0

这工作,稍作调整。我不得不在sinkDoc:'body $$ sinkDoc def'之后添加默认分析设置非常感谢! – Neil 2012-02-12 02:57:13