我正在试图从一个网页上获得数据,这个网页是以股票市场报价(
sample data)定期提供XML文件. XML的结构非常简单,就像这样:
<?xml version="1.0"?> <Contents> <StockQuote Symbol="PETR3" Date="21-12-2010" Time="13:20" Price="23.02" /> </Contents>
(这超过了这个,但这只是一个例子).
我想解析一下数据结构:
data Quote = Quote { symbol :: String,date :: Data.Time.Calendar.Day,time :: Data.Time.LocalTime.TimeOfDay,price :: Float}
我或多或少了解Parsec的作品(在“真实世界Haskell书”的层次上),而且我尝试了一些Text.XML库,但是我可以开发的是一个代码,但是对于这样一个简单的任务而言却是太大了,看起来像一个半烤的黑客,而不是最好的人可以做.
我不太了解解析器和XML(我基本上知道我在RWH书中看过的内容,以前从未使用过解析器)(我只是做统计和数值编程,我不是电脑科学家).有没有一个XML解析库,我只需要知道什么是模型并立即提取信息,而无需手工解析每个元素,而无需解析纯字符串?
我在想这样的事情:
myParser = do cont <- openXMLElem "Contents" quote <- openXMLElem "StockQuote" symb <- getXMLElemField "Symbol" date <- getXMLElemField "Date" (...) closequote <- closeXMLElem "StockQuote" closecont <- closeXMLElem "Contents" return (symb,date) results = parse myParser "" myXMLString
在那里我不必处理纯粹的字符串,并自己创建组合器(我吸吮它).
编辑:我可能需要阅读一些(完全正确的方法)解析器(不仅仅是Parsec)和关于XML的最低限度.你们推荐什么吗?
我必须解析的真正的字符串是:
stringTest = "<?xml version=\"1.0\"?>\r\n<ComportamentoPapeis><Papel Codigo=\"PETR3\" Nome=\"PETROBRAS ON\" Ibovespa=\"#\" Data=\"05/01/201100:00:00\" Abertura=\"29,80\" Minimo=\"30,31\" Maximo=\"30,67\" Medio=\"30,36\" Ultimo=\"30,45\" Oscilacao=\"1,89\" Minino=\"29,71\"/></ComportamentoPapeis>\r\n"
EDIT2:
我尝试了以下(readFloat,readQuoteTime等等只是从字符串中读取东西的功能).
bvspaParser :: (ArrowXml a) => a XmlTree Quote bvspaParser = hasName "ComportamentoPapeis" /> hasName "Papel" >>> proc x -> do (hour,date) <- readQuoteTime ^<< getAttrValue "Data" -< x quoteCode <- getAttrValue "Codigo" -< x openPrice <- readFloat ^<< getAttrValue "Abertura" -< x minim <- readFloat ^<< getAttrValue "Minimo" -< x maxim <- readFloat ^<< getAttrValue "Maximo" -< x ultimo <- readFloat ^<< getAttrValue "Ultimo" -< x returnA -< Quote quoteCode (LocalTime date hour) openPrice minim maxim ultimo docParser :: String -> IO [Quote] docParser str = runX $readString [] str >>> (parseXmlDocument False) >>> bvspaParser
当我把它称为ghci:
*Main> docParser stringTest >>= print []
有什么问题吗?
过去使用过
Haskell XML Toolbox.沿线的东西
{-# LANGUAGE Arrows #-} quoteParser :: (ArrowXml a) => a XmlTree Quote quoteParser = hasName "Contents" /> hasName "StockQuote" >>> proc x -> do symbol <- getAttrValue "Symbol" -< x date <- readTime defaultTimeLocale "%d-%m-%Y" ^<< getAttrValue "Date" -< x time <- readTime defaultTimeLocale "%H:%M" ^<< getAttrValue "Time" -< x price <- read ^<< getAttrValue "Price" -< x returnA -< Quote symbol date time price parseQuoteDocument :: String -> IO (Maybe Quote) parseQuoteDocument xml = liftM listToMaybe . runX . single $ readString [] xml >>> getChildren >>> quoteParser