首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在XML中解析带有命名空间等的元素

在XML中解析带有命名空间等的元素
EN

Stack Overflow用户
提问于 2016-03-08 08:36:06
回答 1查看 161关注 0票数 1

这个问题是关于如何解析具有xmlns属性等的xml内容。如果能做得更好,我将不胜感激。

我有一个XML文件test.xml,如下所示:

代码语言:javascript
复制
<?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“内容的代码

代码语言:javascript
复制
{-# 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中的输出:正确解析:

代码语言:javascript
复制
*Main> main
["My ","Title"]

使用laxElement方法定位SomeResult内容是一种好方法吗?如果有更好的方法,我将非常感谢对此的指点。

此外,我还需要以相反的方向进行http编码(当为上面的响应构建一个请求时),其中内部主体被转义(就像在text.xml中的SomeResult下)。这是在使用Text.XML构建请求时默认处理的东西,还是必须使用html-entities之类的东西显式地将内部主体转换为转义的http?

EN

回答 1

Stack Overflow用户

发布于 2016-03-09 05:30:03

xml-conduit一起,我建议使用像xml-html-conduit-lensxml-lens这样的小“镜头”包(两者都很相似,但我在快速浏览了一下源代码后选择了第一个)。支持命名空间(参见this issue)

如果需要更具体的示例,可以查看one of my experimental project。在该项目中,以下是从VCloud应用编程接口获取特定机器信息的遍历:

代码语言:javascript
复制
fetchVM :: AsXmlDocument t => Text -> Traversal' t Element
fetchVM n = xml...ovfNode "VirtualSystem".attributed (ix (nsName ovfNS "id").only n)

然后,您可以组合遍历as such

代码语言:javascript
复制
vmId = raw ^. responseBody . fetchVM vmName . fetchVmId.text

看看ovhNodensName是如何定义的,看看我是如何处理名称空间的。

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

另一个技巧是坚持使用“xml-conduit”(至少现在是这样)。一些人建议将taggy作为替代,但不幸的是,它目前还没有处于活跃的开发周期中(参见https://github.com/alpmestan/taggy/issues/14)

我希望它能帮上忙。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35856841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档