到目前为止,我使用Haskell XML工具包HXT看到的所有示例都runX用于执行解析器.runX在IO monad中运行.有没有办法在IO之外使用这个XML解析器?对我来说似乎是一个纯粹的操作,不明白为什么我被迫在IO里面.
Tra*_*own 28
您可以使用HXT的xread一起runLA解析外部XML字符串IO.
xread 有以下类型:
xread :: ArrowXml a => a String XmlTree
Run Code Online (Sandbox Code Playgroud)
这意味着你可以使用类型的任何箭头组成它(ArrowXml a) => a XmlTree Whatever得到的a String Whatever.
runLA就像runX,但对于类型的东西LA:
runLA :: LA a b -> a -> [b]
Run Code Online (Sandbox Code Playgroud)
LA是一个实例ArrowXml.
综上所述,我对前一个问题的回答的以下版本使用HXT来解析包含格式良好的XML的字符串,而不IO涉及任何问题:
{-# LANGUAGE Arrows #-}
module Main where
import qualified Data.Map as M
import Text.XML.HXT.Arrow
classes :: (ArrowXml a) => a XmlTree (M.Map String String)
classes = listA (divs >>> pairs) >>> arr M.fromList
where
divs = getChildren >>> hasName "div"
pairs = proc div -> do
cls <- getAttrValue "class" -< div
val <- deep getText -< div
returnA -< (cls, val)
getValues :: (ArrowXml a) => [String] -> a XmlTree (String, Maybe String)
getValues cs = classes >>> arr (zip cs . lookupValues cs) >>> unlistA
where lookupValues cs m = map (flip M.lookup m) cs
xml = "<div><div class='c1'>a</div><div class='c2'>b</div>\
\<div class='c3'>123</div><div class='c4'>234</div></div>"
values :: [(String, Maybe String)]
values = runLA (xread >>> getValues ["c1", "c2", "c3", "c4"]) xml
main = print values
Run Code Online (Sandbox Code Playgroud)
classes并且getValues与之前的版本类似,只需进行一些小的更改以适应预期的输入和输出.主要区别在于我们使用xread而runLA不是readString和runX.
能够以ByteString类似的方式读取类似懒惰的东西会很好,但据我所知,目前HXT不可能.
还有其他一些事情:你可以用这种方式解析字符串IO,但是最好随时使用runX它:它可以让你更好地控制解析器的配置,错误信息等.
另外:我试图使在该示例代码简单,易于扩展,但在组合程序Control.Arrow,并Control.Arrow.ArrowList使其能够与箭头简明得多,如果你喜欢的工作.以下是等效定义classes,例如:
classes = (getChildren >>> hasName "div" >>> pairs) >. M.fromList
where pairs = getAttrValue "class" &&& deep getText
Run Code Online (Sandbox Code Playgroud)