xmlgen: создание узлов XML со смешанным содержимым (т.е. как с основным текстом, так и с вложенными элементами XML) в Haskell
Я пытаюсь сгенерировать 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 ответ
Проблема в выражении
(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")