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

时间:2013-01-24 06:11:08

标签: haskell xml-generation

我正在尝试使用混合内容节点(包含正文和子节点)生成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库的示例用法,但没有找到我的用例。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

问题在于表达式

(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")