packages feed

hexpat-iteratee 0.4 → 0.5

raw patch · 7 files changed

+108/−51 lines, 7 filesdep ~hexpatdep ~iterateePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hexpat, iteratee

API changes (from Hackage documentation)

- Text.XML.Expat.Chunked: ParserOptions :: Maybe Encoding -> Maybe (tag -> Maybe text) -> ParserOptions tag text
- Text.XML.Expat.Chunked: XMLT :: m (Result m a) -> XMLT m a
- Text.XML.Expat.Chunked: data ParserOptions tag text :: * -> * -> *
- Text.XML.Expat.Chunked: defaultParserOptions :: ParserOptions tag text
- Text.XML.Expat.Chunked: instance (Monad m) => Functor (XMLT m)
- Text.XML.Expat.Chunked: instance (Monad m) => Monad (XMLT m)
- Text.XML.Expat.Chunked: instance (MonadIO m) => MonadIO (XMLT m)
- Text.XML.Expat.Chunked: instance MonadTrans XMLT
- Text.XML.Expat.Chunked: parserEncoding :: ParserOptions tag text -> Maybe Encoding
- Text.XML.Expat.Chunked: runXMLT :: XMLT m a -> m (Result m a)
+ Text.XML.Expat.Chunked: ParseOptions :: Maybe Encoding -> Maybe (tag -> Maybe text) -> ParseOptions tag text
+ Text.XML.Expat.Chunked: data ParseOptions tag text :: * -> * -> *
+ Text.XML.Expat.Chunked: defaultEncoding :: ParseOptions tag text -> Maybe Encoding
+ Text.XML.Expat.Chunked: defaultParseOptions :: ParseOptions tag text
+ Text.XML.Expat.Chunked: instance (Monad m) => Functor (XMLT s m)
+ Text.XML.Expat.Chunked: instance (Monad m) => Monad (XMLT s m)
+ Text.XML.Expat.Chunked: instance (MonadIO m) => MonadIO (XMLT s m)
+ Text.XML.Expat.Chunked: instance MonadTrans (XMLT s)
- Text.XML.Expat.Chunked: data XMLT m a
+ Text.XML.Expat.Chunked: data XMLT s m a
- Text.XML.Expat.Chunked: entityDecoder :: ParserOptions tag text -> Maybe (tag -> Maybe text)
+ Text.XML.Expat.Chunked: entityDecoder :: ParseOptions tag text -> Maybe (tag -> Maybe text)
- Text.XML.Expat.Chunked: parse :: (MonadIO m, GenericXMLString tag, GenericXMLString text) => ParserOptions tag text -> (ListT (XMLT m) (Node m tag text) -> XMLT m a) -> m (IterateeG WrappedByteString Word8 m (Either ErrMsg a))
+ Text.XML.Expat.Chunked: parse :: (MonadIO m, GenericXMLString tag, GenericXMLString text) => ParseOptions tag text -> (forall s. ListT (XMLT s m) (Node s m tag text) -> XMLT s m a) -> m (IterateeG WrappedByteString Word8 m (Either ErrMsg a))
- Text.XML.Expat.Chunked: type NNode m text a = Node a (NName text) text
+ Text.XML.Expat.Chunked: type NNode s m text a = Node s a (NName text) text
- Text.XML.Expat.Chunked: type Node m tag text = NodeG (ListT (XMLT m)) tag text
+ Text.XML.Expat.Chunked: type Node s m tag text = NodeG (ListT (XMLT s m)) tag text
- Text.XML.Expat.Chunked: type QNode m a text = Node a (QName text) text
+ Text.XML.Expat.Chunked: type QNode s m a text = Node s a (QName text) text
- Text.XML.Expat.Chunked: type UNode m text = Node m text text
+ Text.XML.Expat.Chunked: type UNode s m text = Node s m text text

Files

Text/XML/Expat/Chunked.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, Rank2Types #-} module Text.XML.Expat.Chunked (   -- * Tree structure   Node,@@ -20,11 +20,11 @@   module Text.XML.Expat.Internal.Namespaced,    -- * Parse to tree-  ParserOptions(..),-  defaultParserOptions,+  ParseOptions(..),+  defaultParseOptions,   Encoding(..),   Text.XML.Expat.Chunked.parse,-  XMLT(..),+  XMLT,   XMLParseError(..),   XMLParseLocation(..)   ) where@@ -55,17 +55,29 @@ -- Note that you can use the type function 'ListOf' to give a list of -- any node type, using that node's associated list type, e.g. -- @ListOf (UNode Text)@-type Node m tag text = Tree.NodeG (ListT (XMLT m)) tag text+--+-- The /s/ parameter is a dummy type used to prevent nodes escaping from the+-- handler.  See 's' for more explanation.+type Node s m tag text = Tree.NodeG (ListT (XMLT s m)) tag text  -- | Type alias for a single node with unqualified tag names where tag and -- text are the same string type.-type UNode m text = Node m text text+--+-- The /s/ parameter is a dummy type used to prevent nodes escaping from the+-- handler.  See 's' for more explanation.+type UNode s m text = Node s m text text  -- | Type alias for a single annotated node where qualified names are used for tags-type QNode m a text = Node a (QName text) text+--+-- The /s/ parameter is a dummy type used to prevent nodes escaping from the+-- handler.  See 's' for more explanation.+type QNode s m a text = Node s a (QName text) text  -- | Type alias for a single annotated node where namespaced names are used for tags-type NNode m text a = Node a (NName text) text+--+-- The /s/ parameter is a dummy type used to prevent nodes escaping from the+-- handler.  See 's' for more explanation.+type NNode s m text a = Node s a (NName text) text  ------ Queue ------------------------------------------------------------------ @@ -102,18 +114,18 @@  ------ Handler ---------------------------------------------------------------- -data Result m a = Yield (XMLT m a) | Result a | HandlerErr String+data Result s m a = Yield (XMLT s m a) | Result a | HandlerErr String  -- | The monad transformer used for writing your handler for chunked XML trees, -- which executes as a co-routine.-data XMLT m a = XMLT {-        runXMLT :: m (Result m a)+data XMLT s m a = XMLT {+        runXMLT :: m (Result s m a)     } -instance Monad m => Functor (XMLT m) where+instance Monad m => Functor (XMLT s m) where     fmap = liftM -instance Monad m => Monad (XMLT m) where+instance Monad m => Monad (XMLT s m) where     return a = XMLT $ return $ Result a     f >>= g = XMLT $ do         res1 <- runXMLT f@@ -123,17 +135,17 @@             HandlerErr err -> return $ HandlerErr err      fail err = XMLT $ return $ HandlerErr err -instance MonadTrans XMLT where+instance MonadTrans (XMLT s) where     lift m = XMLT $ do         r <- m         return $ Result r -instance MonadIO m => MonadIO (XMLT m) where+instance MonadIO m => MonadIO (XMLT s m) where     liftIO m = XMLT $ do         r <- liftIO m         return $ Result r -yield :: Monad m => XMLT m ()+yield :: Monad m => XMLT s m () yield = XMLT $ return $ Yield (XMLT $ return $ Result ())  -------------------------------------------------------------------------------@@ -144,16 +156,23 @@ -- be suspended, and continued when it's available. -- -- This implementation does /not/ use Haskell's lazy I/O.+--+-- The /s/ type argument is a dummy type, which you should just leave polymorphic+-- by typing /s/ when using the type.  The \"forall s .\" in the type signature+-- prevents any parsed nodes escaping from the handler, because they may refer+-- to parts of the tree that haven't been parsed yet, and this parsing can't+-- take happen outside the handler.  If you need to extract nodes from your+-- handler, use a function like 'fromNodeContainer' to convert the container type. parse :: forall m a tag text . (              MonadIO m,              GenericXMLString tag,              GenericXMLString text          ) =>-         ParserOptions tag text-      -> (ListT (XMLT m) (Node m tag text) -> XMLT m a)+         ParseOptions tag text+      -> (forall s . ListT (XMLT s m) (Node s m tag text) -> XMLT s m a)   -- ^ Handler for parsed tree       -> m (IterateeG WrappedByteString Word8 m (Either ErrMsg a)) parse opts handler = do-    let enc = parserEncoding opts+    let enc = defaultEncoding opts      parser <- liftIO $ IO.newParser enc @@ -170,6 +189,11 @@         stack <- readIORef stackRef         (hd, tl) <- newQueue         push (head stack) $ Tree.Element name attrs (ListT $ iter hd)+        case stack of   -- If this is the first startElement of the document,+                        -- then end the root queue now.  XML documents only have+                        -- one root tag.+            [_] -> pushEnd rootTl+            _   -> return ()         writeIORef stackRef (tl:stack)         return True     liftIO $ IO.setEndElementHandler parser $ \_ _ -> do@@ -186,7 +210,7 @@         push (head stack) $ Tree.Text txt         return True -    let nextIter :: XMLT m a+    let nextIter :: XMLT s m a                  -> IterateeG WrappedByteString Word8 m (Either ErrMsg a)         nextIter handler = IterateeG $ \str -> do             case str of@@ -220,7 +244,7 @@         Result a       -> fail $ "handler returned before it demanded from the tree"         HandlerErr err -> fail $ "handler error before it demanded from the tree: "++err   where-    iter :: QueueHead (Node m tag text) -> XMLT m (ListItem (ListT (XMLT m)) (Node m tag text))+    iter :: QueueHead (Node s m tag text) -> XMLT s m (ListItem (ListT (XMLT s m)) (Node s m tag text))     iter hd = do         cell <- liftIO $ peek hd         case cell of
hexpat-iteratee.cabal view
@@ -1,6 +1,6 @@ Cabal-Version: >= 1.6 Name: hexpat-iteratee-Version: 0.4+Version: 0.5 Synopsis: Chunked XML parsing using iteratees Description:   This package provides chunked XML parsing using iteratees.  It is especially suited@@ -50,8 +50,8 @@     parallel,     containers,     extensible-exceptions >= 0.1 && < 0.2,-    iteratee >= 0.3,-    hexpat >= 0.16,+    iteratee == 0.3.*,+    hexpat >= 0.17,     List >= 0.4   Exposed-Modules:     Text.XML.Expat.Chunked
test/client-server/server.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}+import Control.Applicative import Control.Concurrent import Control.Exception import Control.Monad@@ -9,7 +10,8 @@ import Data.Iteratee import Data.Iteratee.IO.Fd import Data.Iteratee.WrappedByteString-import Data.List.Class+import Data.List.Class as List+import Data.Maybe import Data.Text (Text) import qualified Data.Text as T import Network@@ -17,6 +19,7 @@ import System.Posix.IO (handleToFd, fdWriteBuf, closeFd) import System.Posix.Types (Fd) import Text.XML.Expat.Chunked+import qualified Text.XML.Expat.Chunked as Tree import Text.XML.Expat.Format import Foreign.Ptr @@ -29,7 +32,7 @@     forever $ do         (h, _, _) <- accept ls         forkIO $ handleToFd h >>= \fd -> do-            iter <- parse defaultParserOptions (session fd)+            iter <- parse defaultParseOptions (session (fdPutStrBS fd))             result <- enumFd fd iter >>= run             print result           `finally`@@ -46,25 +49,45 @@             then fail "write failed"             else writeFully (buf `plusPtr` fromIntegral written) (len - written) -session :: Fd                      -- ^ Socket for writing output to-        -> ListOf (UNode IO Text)  -- ^ Input XML document-        -> XMLT IO ()-session fd inputXML = do+session :: (B.ByteString -> IO ())  -- ^ Write output data to socket+        -> ListOf (UNode s IO Text)   -- ^ Input XML document+        -> XMLT s IO ()+session writeOut inputXML = do     let outputXML = formatG $ indent 2 $ Element "server" [] (processRoot inputXML)-    execute $ liftIO . fdPutStrBS fd =<< outputXML+    execute $ liftIO . writeOut =<< outputXML     return () -processRoot :: ListOf (UNode IO Text) -> ListOf (UNode IO Text)+processRoot :: ListOf (UNode s IO Text) -> ListOf (UNode s IO Text) processRoot root = do     Element _ _ children <- root     child <- children     extractElements child   where-    extractElements :: UNode IO Text -> UNodes IO Text+    extractElements :: UNode s IO Text -> ListOf (UNode s IO Text)     extractElements elt | isElement elt = processCommand elt `cons` mzero     extractElements _                   = mzero -processCommand :: UNode IO Text -> UNode IO Text-processCommand (Element "hello" _ _) = Element "hello-back" [] mzero+processCommand :: UNode s IO Text -> UNode s IO Text+processCommand elt@(Element "title" _ _) = Element "title" [] $ joinL $ do+    txt <- textContentM elt+    return $ search txt processCommand (Element cmd _ _) = Element "unknown" [("command", cmd)] mzero++list2list :: (List l, List l') => l a -> ItemM l (l' a)+list2list l = fromList `liftM` toList l++search :: forall s . Text -> ListOf (UNode s IO Text)+search key = joinL $ do+    iter <- liftIO $ parse defaultParseOptions $ \root -> do+        let l = do+                elt@(Element _ _ children) <- root+                movie <- List.filter isElement children+                return movie+        fromNodeListContainer l+    eMovies <- liftIO $ fileDriver iter "movies.xml"+    case eMovies of+        Left err -> fail $ "failed to read 'movies.xml': "++show err+        Right movies -> return $ List.filter matches movies+  where+    matches elt = key `T.isInfixOf` fromMaybe "" (getAttribute elt "title") 
test/test1.hs view
@@ -1,3 +1,4 @@+-- Make sure monads-fd package is installed. import Text.XML.Expat.Chunked import Text.XML.Expat.Format @@ -13,19 +14,17 @@  main :: IO () main = do-    eErr <- fileDriver (parse defaultParserOptions dump) "sudoku.xml"+    iter <- parse defaultParseOptions dump+    eErr <- fileDriver iter "sudoku.xml"     case eErr of         Left err -> putStrLn $ "failed: "++show err         Right () -> putStrLn "" -dump :: UNode IO Text -> XMLT IO ()+dump :: ListOf (UNode s IO Text) -> XMLT s IO () dump doc = do-    let txt = formatG doc+    (elt:_) <- toList doc+    let txt = formatG elt     execute $ forL txt $ liftIO . B.hPutStr stdout   where-    mapL :: List c => (a -> ItemM c b) -> c a -> c b-    mapL f = joinM . liftM f-    joinM :: List c => c (ItemM c a) -> c a-    joinM = (>>= joinL . liftM return)     forL = flip mapL 
test/test2.hs view
@@ -1,3 +1,4 @@+-- Make sure monads-fd package is installed. import Text.XML.Expat.Chunked import Text.XML.Expat.Format @@ -13,12 +14,14 @@  main :: IO () main = do-    eErr <- fileDriver (parse defaultParserOptions dump) "sudoku.xml"+    putStrLn $ "test the handler failing"+    iter <- parse defaultParseOptions dump+    eErr <- fileDriver iter "sudoku.xml"     case eErr of         Left err -> putStrLn $ "failed: "++show err         Right () -> putStrLn "" -dump :: UNode IO Text -> XMLT IO ()+dump :: ListOf (UNode s IO Text) -> XMLT s IO () dump doc = do     fail "die!" 
test/test3.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-}+-- Make sure monads-fd package is installed. import Text.XML.Expat.Chunked import Text.XML.Expat.Format @@ -19,14 +20,17 @@  main :: IO () main = do-    eErr <- myFileDriver (parse defaultParserOptions dump) "sudoku.xml"+    putStrLn $ "Check for lazy behaviour by | indicating where blocks are passed to the parser"+    iter <- parse defaultParseOptions dump+    eErr <- myFileDriver iter "sudoku.xml"     case eErr of         Left err -> putStrLn $ "failed: "++show err         Right () -> putStrLn "" -dump :: UNode IO Text -> XMLT IO ()+dump :: ListOf (UNode s IO Text) -> XMLT s IO () dump doc = do-    let txt = formatG doc+    (elt:_) <- toList doc+    let txt = formatG elt     forIter txt $ liftIO . B.hPutStr stdout     return () 
test/test4.hs view
@@ -1,3 +1,4 @@+-- Make sure monads-fd package is installed. import Text.XML.Expat.Chunked import Text.XML.Expat.Format @@ -13,14 +14,17 @@  main :: IO () main = do-    eErr <- fileDriver (parse defaultParserOptions dump) "broken.xml"+    putStrLn $ "Test handling of parse error"+    iter <- parse defaultParseOptions dump+    eErr <- fileDriver iter "broken.xml"     case eErr of         Left err -> putStrLn $ "failed: "++show err         Right () -> putStrLn "" -dump :: UNode IO Text -> XMLT IO ()+dump :: ListOf (UNode s IO Text) -> XMLT s IO () dump doc = do-    let txt = formatG doc+    (elt:_) <- toList doc+    let txt = formatG elt     execute $ forL txt $ liftIO . B.hPutStr stdout   where     mapL :: List c => (a -> ItemM c b) -> c a -> c b