Borsa fiyat teklifleriyle (sample data) periyodik olarak bir XML dosyasına hizmet veren bir web sayfasından veri almaya çalışıyorum. XML yapısı çok basittir ve bunun gibi bir şeydir:Haskell'deki XML Ayrıştırma
<?xml version="1.0"?>
<Contents>
<StockQuote Symbol="PETR3" Date="21-12-2010" Time="13:20" Price="23.02" />
</Contents>
(bundan fazlası var ama bu bir örnek olarak yeterli).
Bir veri yapısı bunu ayrıştırmak istiyorum: Anlıyorum
data Quote = Quote { symbol :: String,
date :: Data.Time.Calendar.Day,
time :: Data.Time.LocalTime.TimeOfDay,
price :: Float}
fazla veya daha az ne kadar Parsec (Real World Haskell kitabın düzeyinde) çalışır ve biraz çalıştı Text.XML
kütüphane ama geliştirebildiğim bir kod çalıştı ama bu kadar basit bir görev için çok büyük ve en iyi olanın yapamayacağı bir yarım fırında kesilmiş hack gibi görünüyor.
Ben ayrıştırıcıları ve XML hakkında çok şey (Ben önce ayrıştırıcıları hiç kullanılmamış ne RWH kitapta okumak temelde biliyorum) bilmiyorum (Ben sadece bir bilgisayar bilimcisi değilim, istatistik ve sayısal programlama yapmak) . Her öğeyi elle ayrıştırmak zorunda kalmadan ve saf dizeyi ayrıştırmak zorunda kalmadan, yalnızca modelin ne olduğunu ve bilgiyi hemen ayıklayabildiğim bir XML ayrıştırma kütüphanesi var mı?
Ben böyle bir şey düşünüyorum: Ben saf dize ile anlaşma ve (Ben ona emmek) combinators kendim yaratmak zorunda olmazdı
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
.
DÜZENLEME: Herhalde genel (sadece Parsec) içinde ayrıştırıcıları hakkında (bu doğru yolu halletmek için yeterli) biraz ve XML hakkında asgari okumak gerekir. Bir şey tavsiye eder misiniz?
ben ayrıştırmak zorunda gerçek dize şudur:
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:
Aşağıdaki çalıştı (vb readFloat, readQuoteTime ... dizeleri şeyleri okumak için sadece fonksiyonlardır).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
ben GHCi içinde diyoruz:
*Main> docParser stringTest >>= print
[]
yanlış bir şey var mı?
çizgisinde şey S. Doaitse Swierstra en öğretici, http://www.cs.uu.nl/research/techreps/repo/CS-2008/2008- 044.pdf, oldukça iyi bir tanıtımdır. Uygulama stilini kullanır, ancak Uygulamanın (veya ayrıştırıcı teorisinin) bilgisini varsaymaz. Hackage (Polyparse, Attoparsec, UU-parsinglib) üzerindeki ayrıştırıcı kitaplık kütüphanelerinin çoğunun Parsec'ten daha iyi seçimler olduğunu düşünüyorum. –