4

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

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-conduit 解析响应正文时,我遇到了问题:

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

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

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

尼尔

4

1 回答 1

6

您可以使用httpLbs而不是http,因此它返回一个惰性ByteString而不是一个Source-parseLBS函数的命名是因为它需要:a L azy B yte S字符串。但是,正如您所提到的,最好使用两者直接基于的管道接口。为此,您应该runResourceT从 中删除该行doPost,并使用以下内容获取 XML 文档:

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

这使用了 xml-conduit 的sinkDoc功能,将Sourcefrom http-conduit 连接到Sinkfrom xml-conduit。

连接后,必须使用 运行完整的管道runResourceT,以确保及时释放所有分配的资源。您的原始代码的问题在于它ResourceT从内部运行得太早doPost;您通常应该runResourceT在想要得到实际结果的时候使用 right,因为管道必须完全在单个ResourceT.

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

于 2012-02-12T00:35:29.173 回答