HXT xpickle(de)在属性值和值构造函数之间进行序列化

时间:2015-09-15 22:58:10

标签: xml haskell hxt

我试图编写一个xpickle,它将某种类型的值构造函数序列化为特定属性的XML属性值,并将XML属性值反序列化为该类型的值构造函数。

我有以下数据:

module Main where

import Text.XML.HXT.Core

newtype Things = Things [Thing]
data Thing = Thing (Maybe Property)
data Property = A | B

someThings :: Things
someThings = Things [ Thing (Just A)
                    , Thing Nothing
                    , Thing (Just B)
                    ]

我想将其序列化为:

<things>
  <thing property="a" />
  <thing />
  <thing property="b" />
</things>

以下是我采取的方法:

instance XmlPickler Things where
  xpickle = xpWrap ( \things -> Things things , \(Things things) -> things ) $
            xpElem "things" $
            xpThings

xpThings :: PU [Thing]
xpThings = xpList xpickle

instance XmlPickler Thing where
  xpickle = xpElem "thing" $
            xpWrap ( \p -> Thing p , \(Thing p) -> p ) $
            xpProperty

xpProperty :: PU (Maybe Property)
xpProperty = xpOption $ xpAttr "property" xpPropertyValue

xpPropertyValue :: PU Property
xpPropertyValue = xpAlt tag ps
  where
    tag A = 1
    tag B = 2
    ps = [ xpTextAttr "a"
         , xpTextAttr "b"
         ]

main :: IO ()
main = do
  putStrLn $ showPickled [ withIndent yes ] someThings
  return ()

此处,xpProperty创建或读取@property属性,然后使用xpPropertyValue计算出该值。 xpPropertyValue根据值的值构造函数确定值:A给出"a"B给出"b",并使用{{1}构造值功能。这里的问题是xpTextAttrxpTextAttr,我试图在需要String -> PU String的地方使用它。但我无法计算出另一种生成PU Property值的方法,该方法取决于PU Property值的值构造函数。

1 个答案:

答案 0 :(得分:0)

这未正确使用xpTextAttr。首先,它的第一个参数应该是属性名"property",其次,它返回它匹配的文本。

您想分别返回构造函数AB

您需要使用xpWrap来指定属性("a""b")的文本内容与这些构造函数之间的映射(双向)。我认为标签是0基础的,所以0和1。

where
  tag A = 0
  tag B = 1
  ps = [ xpWrap (const A,const "a") $ xpTextAttr "property"
       , xpWrap (const B,const "b") $ xpTextAttr "property"
       ]

然后调用xpAttr是错误的。老实说,我不确定xpAttr是什么,与资格名称有关。事实上,xpProperty的代码足够

xpProperty :: PU (Maybe Property)
xpProperty = xpOption $ xpPropertyValue