2012-02-12 32 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