当你用Haskell(HaXml)进行SAX解析时,你如何保持“状态”?

时间:2011-11-15 22:41:34

标签: xml haskell sax haxml

我是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
    _ -> ""

1 个答案:

答案 0 :(得分:1)

这里的问题是map没有按照您的意愿携带状态。一种简单的方法是将您想要的内容写为递归函数,该函数通过递归调用传递状态。您将需要确定您在状态堆栈中保留的值的类型,但这只是一个问题......

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