2015-09-15 58 views
1

我想写一个xpickle,它将某些类型的值构造函数序列化为特定属性的XML属性值,并将XML属性值反序列化为值类型的构造函数。HXT xpickle(de)在属性值和值构造函数之间的序列化

我有如下数据:

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"并且使用xpTextAttr函数构造这些值。这里的问题是,xpTextAttrString -> PU String,我正尝试在需要PU Property的地方使用它。但是我无法找到一种产生PU Property值的替代方法,该值取决于值为Property的值构造函数。

回答

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 
+0

看起来'PU'没有'Functor'实例。当你编译这个时,你会得到:'没有使用'<$''产生的(Functor PU)实例。我不知道'PU'的'fmap'实现会做什么。 – ironchicken

+0

啊,是的,因为它构造了一个可逆的解析器,从“PU字符串”到“PU属性”需要两个函数,每个函数都有一个函数。试试'xpWrap(const A)(const“a”)$ xpTextAttr a' – drquicksilver

+0

仍然没有破解这个:将'xpAlt'的列表参数设为'[xpWrap(const A,const“a”)$ xpTextAttr“一个“,...]'导致串行化到''和一个'xpCheckEmptyAttributes:未处理的XML属性(s)检测到反序列化错误。”#: – ironchicken

相关问题