用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> 
&lt;html&gt; 
    &lt;head&gt; 
     &lt;title&gt;My &lt;b&gt;Title&lt;/b&gt;&lt;/title&gt; 
    &lt;/head&gt; 
    &lt;body&gt; 
     &lt;p&gt;Foo bar baz&lt;/p&gt; 
    &lt;/body&gt; 
&lt;/html&gt; 
</SomeResult> 
</SomeResponse> 
</soap:Body></soap:Envelope> 

我使用xml-conduit写的代码来解析 “SomeResult” 内容解析正确:

*Main> main 
["My ","Title"] 

laxElement应用程序蟑螂找到SomeResult内容的好方法吗?如果有更好的方法,我会非常感谢这方面的指针。

此外,我需要做相反方向的HTTP编码(当建立一个上面的响应请求时)内部身体被转义的地方(如SomeResulttext.xml)。当使用Text.XML构建请求时,默认情况下是否需要处理这些内容,或者是否必须通过使用类似html-entities的内容来明确地将内部体转换为转义http?加上xml-conduit

,我建议使用一个微小的“镜头”包,如xml-html-conduit-lensxml-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 

看看如何ovhNodensName定义看我如何处理命名空间。

这里是关于主题的另一个有趣的文章: https://www.schoolofhaskell.com/user/chad/snippets/random-code-snippets/xml-conduit-lens

另一个技巧是坚持“XML的导管”(至少现在)。有人建议taggy作为替代品,但不幸的是,它目前不在积极的开发周期(见https://github.com/alpmestan/taggy/issues/14

我希望它有帮助。