这个问题是关于如何用xmlns
属性等解析xml内容。我编写了解析它的代码。我将非常感谢能否做得更好。
我有一个XML文件test.xml
,如下所示:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>
<SomeResponse xmlns="https://testsomestuff.org/API/WS/">
<SomeResult>
<html>
<head>
<title>My <b>Title</b></title>
</head>
<body>
<p>Foo bar baz</p>
</body>
</html>
</SomeResult>
</SomeResponse>
</soap:Body></soap:Envelope>
我写了代码来解析&#34; SomeResult&#34;内容使用xml-conduit
:
{-# LANGUAGE OverloadedStrings #-}
import Prelude hiding (readFile)
import Text.XML
import Text.XML.Cursor
import qualified Data.Text as T
import Data.Text.Lazy.Builder (toLazyText)
import Data.Text.Lazy (fromStrict)
main :: IO ()
main = do
doc <- readFile def "test.xml"
let cursor = fromDocument doc
res = fromStrict $ T.concat $ child cursor >>= laxElement "Body" >>= child >>= laxElement "SomeResponse" >>= child >>= laxElement "SomeResult" >>= descendant >>= content
pres = parseText_ def res
cursor2 = fromDocument pres
res2 = child cursor2 >>= element "head" >>= child >>= element "title" >>= descendant >>= content
print $ res2
ghci
中的输出:正确解析:
*Main> main
["My ","Title"]
是laxElement
方法找到SomeResult
内容的好方法吗?如果有更好的方法,我将非常感谢指点。
此外,我需要反向进行http编码(在构建上述响应的请求时)内部主体被转义(例如SomeResult
中的text.xml
下)。这是在使用Text.XML
构建请求时默认处理的问题,还是我必须使用类似html-entities的内容将内部主体转换为转义的http?
答案 0 :(得分:1)
与xml-conduit
一起,我会建议使用一个微小的“镜头”包,例如xml-html-conduit-lens或xml-lens
(两者都非常相似,但我快速选择了第一个浏览源头)。支持命名空间(请参阅this issue)
如果您需要更具体的示例,可以查看one of my experimental project。从该项目开始,这里是一个从VCloud API获取特定机器信息的遍历:
fetchVM :: AsXmlDocument t => Text -> Traversal' t Element
fetchVM n = xml...ovfNode "VirtualSystem".attributed (ix (nsName ovfNS "id").only n)
然后,您可以组合遍历as such:
vmId = raw ^. responseBody . fetchVM vmName . fetchVmId.text
查看如何定义ovhNode
或nsName
以查看我如何处理命名空间。
这是另一篇关于这个主题的有趣文章: https://www.schoolofhaskell.com/user/chad/snippets/random-code-snippets/xml-conduit-lens
另一个提示是坚持使用'xml-conduit'(至少目前为止)。有些人建议将taggy
作为替代品,但遗憾的是,目前尚未处于活跃的开发周期(请参阅https://github.com/alpmestan/taggy/issues/14)
我希望它有所帮助。