{-# LANGUAGE CPP #-} -------------------------------------------------------------------- -- | -- Module : Text.Feed.Import -- Copyright : (c) Galois, Inc. 2008, -- (c) Sigbjorn Finne 2009- -- License : BSD3 -- -- Maintainer: Sigbjorn Finne -- Stability : provisional -- -- Convert from XML to Feeds. -- -------------------------------------------------------------------- module Text.Feed.Import ( parseFeedFromFile -- :: FilePath -> IO Feed , parseFeedString -- :: String -> Maybe Feed , parseFeedSource -- :: XmlSource s => s -> Maybe Feed -- if you know your format, use these directly: , readRSS2 -- :: XML.Element -> Maybe Feed , readRSS1 -- :: XML.Element -> Maybe Feed , readAtom -- :: XML.Element -> Maybe Feed ) where import Text.Atom.Feed.Import as Atom import Text.RSS.Import as RSS import Text.RSS1.Import as RSS1 import Text.Feed.Types import Text.XML.Light as XML import Text.XML.Light.Lexer ( XmlSource ) import Control.Monad #if MIN_VERSION_utf8_string(1,0,0) import Codec.Binary.UTF8.String (decodeString) import System.IO (IOMode(..), hGetContents, openBinaryFile ) utf8readFile :: FilePath -> IO String utf8readFile fp = fmap decodeString (hGetContents =<< openBinaryFile fp ReadMode) #else import System.IO.UTF8 as UTF8 ( readFile ) utf8readFile :: FilePath -> IO String utf8readFile = UTF8.readFile #endif -- | 'parseFeedFromFile fp' reads in the contents of the file at @fp@; -- the assumed encoding is UTF-8. parseFeedFromFile :: FilePath -> IO Feed parseFeedFromFile fp = do ls <- utf8readFile fp case parseFeedString ls of Nothing -> fail ("parseFeedFromFile: not a well-formed XML content in: " ++ fp) Just f -> return f -- | 'parseFeedWithParser tries to parse the string @str@ -- as one of the feed formats. First as Atom, then RSS2 before -- giving RSS1 a try. @Nothing@ is, rather unhelpfully, returned -- as an indication of error. parseFeedWithParser :: XmlSource s => (s -> Maybe Element) -> s -> Maybe Feed parseFeedWithParser parser str = case parser str of Nothing -> Nothing Just e -> readAtom e `mplus` readRSS2 e `mplus` readRSS1 e `mplus` Just (XMLFeed e) parseFeedString :: String -> Maybe Feed parseFeedString = parseFeedSource -- | 'parseFeedSource s' tries to parse the source @s@ as -- one of the feed formats. First as Atom, then RSS2 before giving -- RSS1 a try. @Nothing@ is, rather unhelpfully, returned as an -- indication of error. parseFeedSource :: XmlSource s => s -> Maybe Feed parseFeedSource = parseFeedWithParser parseXMLDoc -- | 'readRSS2 elt' tries to derive an RSS2.x, RSS-0.9x feed document -- from the XML element @e@. readRSS2 :: XML.Element -> Maybe Feed readRSS2 e = fmap RSSFeed $ RSS.elementToRSS e -- | 'readRSS1 elt' tries to derive an RSS1.0 feed document -- from the XML element @e@. readRSS1 :: XML.Element -> Maybe Feed readRSS1 e = fmap RSS1Feed $ RSS1.elementToFeed e -- | 'readAtom elt' tries to derive an Atom feed document -- from the XML element @e@. readAtom :: XML.Element -> Maybe Feed readAtom e = fmap AtomFeed $ Atom.elementFeed e