【问题标题】:Parsing elements with namespace etc. in XML在 XML 中使用命名空间等解析元素
【发布时间】:2016-03-08 00:36:06
【问题描述】:

这个问题是关于如何使用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>
&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”内容的代码:

{-# 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 内容的好方法吗?如果有更好的方法,我将非常感谢这方面的指点。

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

【问题讨论】:

    标签: xml haskell xml-conduit


    【解决方案1】:

    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-conduit”(至少现在是这样)。一些人建议将taggy 作为替代品,但不幸的是,它目前不在活跃的开发周期中(请参阅https://github.com/alpmestan/taggy/issues/14

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      相关资源
      最近更新 更多