用XML解析名称空间的元素
这个问题是关于如何使用xmlns
属性等解析xml内容。我写了代码来解析它的工作原理。我会很感激能否做得更好的指针。用XML解析名称空间的元素
我有如下一个XML文件test.xml
:
{-# 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
:
<?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>
我使用xml-conduit
写的代码来解析 “SomeResult” 内容解析正确:
*Main> main
["My ","Title"]
是laxElement
应用程序蟑螂找到SomeResult
内容的好方法吗?如果有更好的方法,我会非常感谢这方面的指针。
此外,我需要做相反方向的HTTP编码(当建立一个上面的响应请求时)内部身体被转义的地方(如SomeResult
在text.xml
)。当使用Text.XML
构建请求时,默认情况下是否需要处理这些内容,或者是否必须通过使用类似html-entities的内容来明确地将内部体转换为转义http?加上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的导管”(至少现在)。有人建议taggy
作为替代品,但不幸的是,它目前不在积极的开发周期(见https://github.com/alpmestan/taggy/issues/14)
我希望它有帮助。