Я пытаюсь получить данные с веб-страницы, периодически использующей 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 (на уровне книги Real World 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
где мне не нужно было бы разбираться с чистой строкой и сами создавать комбинаторы (я сосать ее).
EDIT: Мне, вероятно, нужно немного почитать (достаточно, чтобы это сделать правильно) о парсерах вообще (не только 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
[]
Что-то не так?