2011-11-15 26 views
2

我是Haskell的总新手,和我的第一个真正的问题 与Haskell我想解析一个巨大的带有HaXml SAX解析的XML文件。当你用Haskell(HaXml)进行SAX解析时,你如何保持“状态”?

我遇到的最大问题是如何找出包含任何特定“charData”SaxElement的 元素标记。如果我正在使用命令式语言编写 ,那么我只需要一个有状态的Array 对象,该对象在SAX事件发生时维护元素标记堆栈。当遇到“SAX.SaxElementOpen”为 时,I 会将元素名称推送到堆栈,并在遇到“SAX.SaxElementClose”时弹出一个。 然后,如果我得到了一个“SAX.SaxCharData”事件/元素,我只是看 堆栈的顶部,看看有什么标签它被装入英寸

现在,我试图解决在Haskell这个问题,我不知道 如何解决缺乏全局有状态变量的问题。我只有一个 模糊的概念Monads做什么,所以如果他们是解决方案,我可以使用 一个或两个。

这里是希望足够的代码来说明如何到目前为止,我已经得到了:

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

尝试一个状态monad。你可以通过在列表中存储一个状态来定义你自己的'push'和'pop'操作。 – fuz

+0

我一直在看Monad国家,我不得不承认,在这一点上我感到非常困惑。 – dan

回答

1

这里的问题是,map如你所愿不携带状态。一个简单的方法是编写你想要的作为递归函数,通过递归调用传递状态。你需要决定你在状态堆栈上保留的是什么类型的值,但这只是一个问题...

go :: MyStack -> [SAX.SaxElement] -> [String] 
go _ [] = [] 
go s (e:es) = myProcessElem e : go s' es 
    where s' = pushPop s 
+0

谢谢。我认为国家Monad是de rigeuer,但这对我来说更直观。 – dan

相关问题