{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-} {- | Module : Text.XML.Decode Description : Provides a Cursor based XML decoder that gives nice error messages Copyright : (c) Ben Kolera License : MIT Maintainer : Ben Kolera Stability : experimental This library extends the functionality of 'Text.XML.Cursor' to allow you to accumulate history as you traverse the structure. This leads to greater context about why your decoder failed when it invariably does. Here is an example of a decoder: @ data BookCategory = Haskell | Scala | Programming | FunctionalProgramming deriving (Eq,Show) bookCategoryFromText :: Text -> Maybe BookCategory bookCategoryFromText "Haskell" = Just Haskell bookCategoryFromText "Scala" = Just Scala bookCategoryFromText "Programming" = Just Programming bookCategoryFromText "Functional Programming" = Just FunctionalProgramming bookCategoryFromText _ = Nothing data LibrarySection = Fiction Text -- Fiction by author first letter(s) | NonFiction Double -- Dewey decimal number deriving (Eq,Show) makePrisms ''LibrarySection data Book = Book { _bookId :: Integer , _bookName :: Text , _bookSection :: LibrarySection , _bookPublished :: Day , _bookLastBorrowed :: Maybe UTCTime , _bookCategories :: [BookCategory] } deriving (Eq,Show) makeLenses ''Book data Library = Library { _books :: [Book] } deriving (Eq,Show) makeLenses ''Library instance DecodeCursor BookCategory where decode = parseCursor (parseMaybe "BookCategory" bookCategoryFromText) instance DecodeCursor LibrarySection where decode = decodeChoice [ choice (laxElement "fiction") decodeFiction , choice (laxElement "non_fiction") decodeNonFiction ] where decodeFiction c = Fiction <$> parseCursor parseText c decodeNonFiction c = NonFiction <$> parseCursor parseDouble c instance DecodeCursor Book where decode c = Book <$> decodeAttr "id" parseInteger c <*> decodeSingle (c %/ laxElement "name") <*> decodeSingle (c %/ laxElement "section") <*> (decodeSingle (c %/ laxElement "published") <&> toDay) <*> (decodeMay (c %/ laxElement "lastBorrowed") <&> fmap toUtcT) <*> decodeMany (c %/ laxElement "category") instance DecodeCursor Library where decode c = Library <$> decodeMany ( c %/ laxElement "book" ) @ If you tried to decode the following XML with a bad value for the section: @ Learn you a haskell for great good!
5.1
2011-04-21 2015-01-05T16:30:00Z Programming Haskell Functional Programming
@ Then you'd get an error that looks like this: @ Left ( "Choices Exhausted" , [ MoveAxis Child , LaxElement "book" , MoveAxis Child , LaxElement "section" , Choice [ [ MoveAxis Child , LaxElement "fiction" ] , [ MoveAxis Child , LaxElement "non_fiction" ]] Nothing ]) @ Checkout the tests for more examples! -} module Text.XML.Decode ( module Text.XML.Decode.DecodeCursor , module Text.XML.Decode.HCursor , module Text.XML.Decode.Parsers , module Text.XML.Decode.Time ) where import Text.XML.Decode.DecodeCursor import Text.XML.Decode.HCursor import Text.XML.Decode.Parsers import Text.XML.Decode.Time