module AWS.Lib.Parser
where
import Data.XML.Types (Event(..), Name(..))
import Data.Text (Text)
import qualified Data.Text as T
import Data.Conduit
import qualified Data.Conduit.List as CL
import qualified Text.XML.Stream.Parse as XML
import Control.Applicative
text :: MonadThrow m => GLSink Event m Text
text = XML.content
itemConduit :: MonadThrow m
=> Text
-> GLSink Event m o
-> GLConduit Event m o
itemConduit tag inner =
maybe (()) id <$> elementM tag (listConduit "item" inner)
listConduit :: MonadThrow m
=> Text
-> GLSink Event m o
-> GLConduit Event m o
listConduit name p =
awaitWhile isTag >>= maybe (return ()) (\e -> do
leftover e
if isBeginTagName name e
then do
element name $ p >>= yield
listConduit name p
else return ()
)
listConsumer :: MonadThrow m
=> Text
-> GLSink Event m o
-> GLSink Event m [o]
listConsumer name p = listConduit name p >+> CL.consume
itemsSet :: MonadThrow m
=> Text
-> GLSink Event m o
-> GLSink Event m [o]
itemsSet tag inner = itemConduit tag inner >+> CL.consume
isTag :: Event -> Bool
isTag (EventBeginElement _ _) =True
isTag (EventEndElement _) =True
isTag _ = False
sinkDropWhile :: Monad m => (i -> Bool) -> GLSink i m ()
sinkDropWhile f = await >>= maybe (return ()) g
where
g i | f i = sinkDropWhile f
| otherwise = leftover i >> return ()
isBeginTagName :: Text -> Event -> Bool
isBeginTagName name (EventBeginElement n _)
| nameLocalName n == name = True
| otherwise = False
isBeginTagName _ _ = False
awaitWhile :: Monad m
=> (i -> Bool)
-> Pipe l i o u m (Maybe i)
awaitWhile f = await >>= g
where
g Nothing = return Nothing
g (Just a)
| f a = return $ Just a
| otherwise = awaitWhile f
getF :: MonadThrow m
=> Text
-> (Text -> b)
-> Pipe Event Event o u m b
getF name f = tagContent name >>= return . f
getT :: MonadThrow m
=> Text
-> Pipe Event Event o u m Text
getT name = getF name id
getM :: MonadThrow m
=> Text
-> (Maybe Text -> b)
-> Pipe Event Event o u m b
getM name f = tagContentM name >>= return . f
getMT :: MonadThrow m
=> Text
-> Pipe Event Event o u m (Maybe Text)
getMT name = getM name id
elementM :: MonadThrow m
=> Text
-> Pipe Event Event o u m a
-> Pipe Event Event o u m (Maybe a)
elementM name inner = do
sinkDropWhile $ not . isTag
XML.tagPredicate g (return ()) $ const inner
where
g n = (nameLocalName n == name)
element :: MonadThrow m
=> Text
-> Pipe Event Event o u m a
-> Pipe Event Event o u m a
element name inner = XML.force "parse error" $ elementM name inner
tagContentM :: MonadThrow m
=> Text
-> GLSink Event m (Maybe Text)
tagContentM name = elementM name text
tagContent :: MonadThrow m
=> Text
-> GLSink Event m Text
tagContent name =
XML.force ("parse error:" ++ T.unpack name) $ tagContentM name