我是Haskell的新手,也是我第一个真正的问题 使用Haskell我试图用HaXml SAX解析来解析一个巨大的XML文件。
我遇到的一个大问题是如何弄清楚封闭的内容 任何特定“charData”SaxElement的元素标记是。如果我在做 这是一种命令式语言,我只有一个有状态的数组 在SAX事件发生时维护元素标记栈的对象。一世 当“SAX.SaxElementOpen”为时,会将元素名称推送到堆栈 遇到,并在遇到“SAX.SaxElementClose”时弹出一个。 然后,如果我有一个“SAX.SaxCharData”事件/元素,我可以看看 堆栈的顶部,以查看它所包含的标记。
现在我正试图在Haskell中解决这个问题,我不知道 如何解决缺乏全局有状态变量的问题。我只有一个 莫纳德所做的含糊不清的概念,所以如果他们是解决方案,我可以使用 一两个小费。
希望有足够的代码来展示我已经走了多远:
module Main where
import qualified Text.XML.HaXml.SAX as SAX
import Text.XML.HaXml
import Data.Maybe
import Text.XML.HaXml.Namespaces
main = let inputFilename = "/path/to/file.xml" in
do content <- readFile inputFilename
let (elements, error) = SAX.saxParse inputFilename content
mapM_ putStrLn (summarizeElements elements)
summarizeElements :: [SAX.SaxElement] -> [String]
summarizeElements elements = filter (\s -> length s > 0) $ map summarizeElement elements
summarizeElement :: SAX.SaxElement -> String
summarizeElement element = case element of
(SAX.SaxElementOpen name attrs) -> myProcessElem name attrs
(SAX.SaxCharData charData) -> myProcessCharData charData
(SAX.SaxElementTag name attrs) -> myProcessElem name attrs
_ -> ""
答案 0 :(得分:1)
这里的问题是map
没有按照您的意愿携带状态。一种简单的方法是将您想要的内容写为递归函数,该函数通过递归调用传递状态。您将需要确定您在状态堆栈中保留的值的类型,但这只是一个问题......
go :: MyStack -> [SAX.SaxElement] -> [String]
go _ [] = []
go s (e:es) = myProcessElem e : go s' es
where s' = pushPop s