我有以下xml:
<list>
<recipient>
<name></name>
<lastname></lastname>
<email></email>
<phone></phone>
<home></home>
</recipient>
<recipient>
</recipient>
</list>
以及以下数据类型:
data Recipient = Recipient { name :: String
, lastname :: String
, email :: String
, phone :: Maybe String
, home :: Maybe String }
我想要做的是阅读xml并获取收件人列表:[收件人]
为此,我写了以下内容:
import Text.XML.HXT.Core
readMyXml :: FilePath -> IO [Recipient]
readMyXml path = do
-- lets read the doc
fe <- readFile path
let
-- parse it
doc = readString [withValidate no] fe
-- get all recipient nodes
reps <- getAllRep
-- the part I don't have
-- the only thing wrong in the following is the map function
-- I need an equivalent that runs on hxt trees
return $ map frmRep2Dat reps
-- ^
-- |
-- here
-- end of part I don't have
where
getAllRep = runX $ doc
>>> deep (hasName "list")
>>> multi (hasName "recipient")
frmRep2Dat branch = do
let
-- gets the recipient of a recipient node child
getV name = runX $
branch
>>> deep (hasName name)
>>> removeAllWhiteSpace
>>> deep getText
-- normaly there is no need to check because not maybe fields are
-- mandatory and should not be empty
getVal name = do
val <- getV name
case val of
[] -> ""
[""] -> ""
_ -> head val
-- some maybe wrapping
getMayVal name = do
val <- getV name
case val of
[] -> Nothing
[""] -> Nothing
_ -> Just (head val)
name <- getVal "name"
lastname <- getVal "lastname"
email <- getVal "email"
phone <- getMayVal "phone"
home <- getMayVal "home"
return $ Recipient name lastname email phone home
关于如何映射树的任何线索?
答案 0 :(得分:1)
发现没有必要遍历树。 HXT已经做到了。 从xml构造数据的方法比我编写的天真的方法更简单 我用以下方法替换了整个readMyXml函数:
readMyXml path = do
fi <- readFile path
let
doc = readString [withValidate no] fi
return =<< runX $ getRecipients doc
wrapStr a = if null a
then Nothing
else Just a
getD a = deep (hasName a)
>>> removeAllWhiteSpace
>>> deep getText
getMD a = getD a
>>^ wrapStr
getRecipients doc = doc
>>> deep (hasName "list")
>>> multi (hasName "recipient")
>>> proc y -> do
nime <- getD "name" -< y
lstn <- getD "lastname" -< y
mail <- getD "email" -< y
phon <- getMD "phone" -< y
homi <- getMD "home" -< y
returnA -< Recipient nime lstn mail phon homi
现在,应用于问题中定义的文档的getRecipients的返回值是[收件人]
干杯