xmlgen:在Haskell中生成混合内容XML节点(即同时包含正文和嵌套XML元素)



我正在尝试生成具有混合内容节点(具有正文和子节点)的XML,如下所示:

<person>
some text
<hugo age="24">thingy</hugo>
</person>

我正在使用 xmlgen 库。

以下是我走了多远:

import Text.XML.Generator
import qualified Data.ByteString as B
makeElt = xelem "person" $
            xelems $ (xtext "some text" : 
                      (xelem "hugo" (xattr "age" "24" <#> 
                                     xtext "thingy")))
main = do
  let elt = makeElt
  B.putStr . xrender $ doc defaultDocInfo elt

这无法编译,GHC 的错误消息对我来说是不可理解的(作为初学者):

$ runhaskell test.hs
test.hs:6:24:
    Couldn't match type `Elem' with `Xml Elem'
    The function `xelem' is applied to two arguments,
    but its type `[Char]
                  -> Text.XML.Generator.MkElemRes [Char] (Xml Attr, Xml Elem)'
    has only one
    In the second argument of `(:)', namely
      `(xelem "hugo" (xattr "age" "24" <#> xtext "thingy"))'
    In the second argument of `($)', namely
      `(xtext "some text"
        : (xelem "hugo" (xattr "age" "24" <#> xtext "thingy")))'
test.hs:6:24:
    Couldn't match type `Xml' with `[]'
    The function `xelem' is applied to two arguments,
    but its type `[Char]
                  -> Text.XML.Generator.MkElemRes [Char] (Xml Attr, Xml Elem)'
    has only one
    In the second argument of `(:)', namely
      `(xelem "hugo" (xattr "age" "24" <#> xtext "thingy"))'
    In the second argument of `($)', namely
      `(xtext "some text"
        : (xelem "hugo" (xattr "age" "24" <#> xtext "thingy")))'

是否非常接近我需要的结果,或者我应该以不同的方式编写?

我尝试寻找 xmlgen 库的示例用法,但没有找到我的用例。任何帮助将不胜感激。

问题出在表达式中

(xtext "some text" : 
 (xelem "hugo" (xattr "age" "24" <#> 
                xtext "thingy")))

:后面的部分(以 xelem "hugo" 开头)不是列表。调试此类问题的好方法是使用 ghci。这就是我最初所做的,ghci 很快将您引向正确的方向:

*Text.XML.Generator> :t xtext "some text" : xelem "hugo" (xattr "age" "24" <#> xtext "thingy")
<interactive>:1:21:
    Couldn't match expected type `[Xml Elem]'
                with actual type `Xml Elem'
    In the return type of a call of `xelem'
    In the second argument of `(:)', namely
      `xelem "hugo" (xattr "age" "24" <#> xtext "thingy")'
    In the expression:
      xtext "some text"
      : xelem "hugo" (xattr "age" "24" <#> xtext "thingy")

一个很好的问题是为什么GHC首先给出如此糟糕的错误消息。问题是xelem的结果类型是重载的,实际上xelem的类型是n -> MkElemRes n c。您尝试在示例中使用的MkElemRes n c的实例化确实是一种函数类型,因此示例的这一部分是正确的。但一般来说,MkElemRes n c不需要是函数类型,这就是为什么 GHC 抱怨两个只期望一个参数(即类型 MkElemRes n c 的一个)的原因。

以下是原始问题的一种解决方案:

xelem "person" $ 
   xelems [xtext "some text", xelem "hugo" (xattr "age" "24" <#> xtext "thingy")]

这是一个替代解决方案:

xelem "person" $ xtext "some text" <> xelem "hugo" (xattr "age" "24" <#> xtext "thingy")

最新更新