diff --git a/Text/XML/Expat/Annotated.hs b/Text/XML/Expat/Annotated.hs
--- a/Text/XML/Expat/Annotated.hs
+++ b/Text/XML/Expat/Annotated.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies,
-        FlexibleContexts #-}
+        FlexibleContexts, ScopedTypeVariables #-}
 -- | A variant of /Node/ in which Element nodes have an annotation of any type,
 -- and some concrete functions that annotate with the XML parse location.
 --
@@ -36,6 +36,7 @@
   Encoding(..),
   parse,
   parse',
+  parseG,
   XMLParseError(..),
   XMLParseLocation(..),
 
@@ -45,6 +46,7 @@
 
   -- * Convert from SAX
   saxToTree,
+  saxToTreeG,
 
   -- * Abstraction of string types
   GenericXMLString(..),
@@ -86,6 +88,7 @@
 
 import Control.Monad (mplus, mzero)
 import Control.DeepSeq
+import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as L
 import Data.List.Class
@@ -285,6 +288,39 @@
     ptl (_:rema) = ptl rema  -- extended node types not supported in this tree type
     ptl [] = ([], Nothing, [])
 
+-- | A lower level function that converts a generalized SAX stream into a tree structure.
+-- Ignores parse errors.
+saxToTreeG :: forall l a tag text . (GenericXMLString tag, List l, Monad (ItemM l)) =>
+              l (SAXEvent tag text, a)
+           -> ItemM l (NodeG a l tag text)
+saxToTreeG events = do
+    (elts, _) <- process events
+    findRoot elts
+  where
+    findRoot :: l (NodeG a l tag text) -> ItemM l (NodeG a l tag text)
+    findRoot elts = do
+        li <- runList elts
+        case li of
+            Cons elt@(Element _ _ _ _) _ -> return elt
+            Cons _ rema -> findRoot rema
+            Nil -> return $ Element (gxFromString "") mzero mzero (error "saxToTree null annotation")
+    process :: l (SAXEvent tag text, a)
+            -> ItemM l (l (NodeG a l tag text), l (SAXEvent tag text, a))
+    process events = do
+        li <- runList events
+        case li of
+            Nil -> return (mzero, mzero)
+            Cons (StartElement name attrs, ann) rema -> do
+                (children, rema') <- process rema
+                (out, rema'') <- process rema'
+                return (Element name attrs children ann `cons` out, rema'')
+            Cons (EndElement _, _) rema -> return (mzero, rema)
+            Cons (CharacterData txt, _) rema -> do
+                (out, rema') <- process rema
+                return (Text txt `cons` out, rema')
+            --Cons (FailDocument err) rema = (mzero, mzero)
+            Cons _ rema -> process rema
+
 -- | Lazily parse XML to tree. Note that forcing the XMLParseError return value
 -- will force the entire parse.  Therefore, to ensure lazy operation, don't
 -- check the error status until you have processed the tree.
@@ -293,6 +329,15 @@
       -> L.ByteString             -- ^ Input text (a lazy ByteString)
       -> (LNode tag text, Maybe XMLParseError)
 parse opts bs = saxToTree $ SAX.parseLocations opts bs
+
+-- | Parse a generalized list to a tree, ignoring parse errors.
+-- This function allows for a parse from an enumerator/iteratee to a "lazy"
+-- tree structure using the @List-enumerator@ package.
+parseG :: (GenericXMLString tag, GenericXMLString text, List l) =>
+          ParseOptions tag text  -- ^ Parse options
+       -> l ByteString           -- ^ Input text as a generalized list of blocks
+       -> ItemM l (NodeG XMLParseLocation l tag text)
+parseG opts = saxToTreeG . SAX.parseLocationsG opts
 
 -- | DEPRECATED: Use 'parse' instead.
 --
diff --git a/Text/XML/Expat/SAX.hs b/Text/XML/Expat/SAX.hs
--- a/Text/XML/Expat/SAX.hs
+++ b/Text/XML/Expat/SAX.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, CPP #-}
+{-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, CPP, ScopedTypeVariables, FlexibleInstances #-}
 
 -- hexpat, a Haskell wrapper for expat
 -- Copyright (C) 2008 Evan Martin <martine@danga.com>
@@ -18,7 +18,9 @@
 
   textFromCString,
   parse,
+  parseG,
   parseLocations,
+  parseLocationsG,
   parseLocationsThrowing,
   parseThrowing,
   defaultParseOptions,
@@ -42,6 +44,7 @@
   ) where
 
 import Text.XML.Expat.Internal.IO hiding (parse)
+import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as L
 import qualified Data.ByteString.Internal as I
@@ -52,6 +55,7 @@
 import qualified Data.Text.Encoding as TE
 import qualified Codec.Binary.UTF8.String as U8
 import Data.Typeable
+import Data.List.Class hiding (tail)
 import Control.Exception.Extensible as Exc
 import Control.Applicative
 import Control.DeepSeq
@@ -105,7 +109,7 @@
     gxHead = head
     gxTail = tail
     gxBreakOn c = break (==c)
-    gxFromCStringLen cstr = U8.decodeString <$> peekCStringLen cstr
+    gxFromCStringLen cstr = U8.decode . B.unpack <$> peekByteStringLen cstr
     gxToByteString = B.pack . map c2w . U8.encodeString
 
 instance GenericXMLString B.ByteString where
@@ -206,92 +210,115 @@
                parseExternalEntityReference pp ctx Nothing c
            else return False
 
--- | Lazily parse XML to SAX events. In the event of an error, FailDocument is
--- the last element of the output list.
-parse :: (GenericXMLString tag, GenericXMLString text) =>
-         ParseOptions tag text -- ^ Parse options
-      -> L.ByteString           -- ^ Input text (a lazy ByteString)
-      -> [SAXEvent tag text]
-parse opts input = unsafePerformIO $ do
-    let enc = overrideEncoding opts
-    let mEntityDecoder = entityDecoder opts
+-- | Parse a generalized list of ByteStrings containing XML to SAX events.
+-- In the event of an error, FailDocument is the last element of the output list.
+parseG :: forall tag text l . (GenericXMLString tag, GenericXMLString text, List l) =>
+          ParseOptions tag text -- ^ Parse options
+       -> l ByteString          -- ^ Input text (a lazy ByteString)
+       -> l (SAXEvent tag text)
+parseG opts inputBlocks = runParser inputBlocks cacheRef
+  where
+    (parser, queueRef, cacheRef) = unsafePerformIO $ do
+        let enc = overrideEncoding opts
+        let mEntityDecoder = entityDecoder opts
 
-    parser <- newParser enc
-    queueRef <- newIORef []
+        parser <- newParser enc
+        queueRef <- newIORef []
 
-    case mEntityDecoder of
-        Just deco -> setEntityDecoder parser deco $ \_ txt -> do
-            modifyIORef queueRef (CharacterData txt:)
-        Nothing -> return ()
+        case mEntityDecoder of
+            Just deco -> setEntityDecoder parser deco $ \_ txt -> do
+                modifyIORef queueRef (CharacterData txt:)
+            Nothing -> return ()
 
-    setXMLDeclarationHandler parser $ \_ cVer cEnc cSd -> do
-        ver <- textFromCString cVer
-        mEnc <- if cEnc == nullPtr
-            then return Nothing
-            else Just <$> textFromCString cEnc
-        let sd = if cSd < 0
-                then Nothing
-                else Just $ if cSd /= 0 then True else False
-        modifyIORef queueRef (XMLDeclaration ver mEnc sd:)
-        return True
+        setXMLDeclarationHandler parser $ \_ cVer cEnc cSd -> do
+            ver <- textFromCString cVer
+            mEnc <- if cEnc == nullPtr
+                then return Nothing
+                else Just <$> textFromCString cEnc
+            let sd = if cSd < 0
+                    then Nothing
+                    else Just $ if cSd /= 0 then True else False
+            modifyIORef queueRef (XMLDeclaration ver mEnc sd:)
+            return True
 
-    setStartElementHandler parser $ \_ cName cAttrs -> do
-        name <- textFromCString cName
-        attrs <- forM cAttrs $ \(cAttrName,cAttrValue) -> do
-            attrName <- textFromCString cAttrName
-            attrValue <- textFromCString cAttrValue
-            return (attrName, attrValue)
-        modifyIORef queueRef (StartElement name attrs:)
-        return True
+        setStartElementHandler parser $ \_ cName cAttrs -> do
+            name <- textFromCString cName
+            attrs <- forM cAttrs $ \(cAttrName,cAttrValue) -> do
+                attrName <- textFromCString cAttrName
+                attrValue <- textFromCString cAttrValue
+                return (attrName, attrValue)
+            modifyIORef queueRef (StartElement name attrs:)
+            return True
 
-    setEndElementHandler parser $ \_ cName -> do
-        name <- textFromCString cName
-        modifyIORef queueRef (EndElement name:)
-        return True
+        setEndElementHandler parser $ \_ cName -> do
+            name <- textFromCString cName
+            modifyIORef queueRef (EndElement name:)
+            return True
 
-    setCharacterDataHandler parser $ \_ cText -> do
-        txt <- gxFromCStringLen cText
-        modifyIORef queueRef (CharacterData txt:)
-        return True
-        
-    setStartCDataHandler parser $ \_  -> do
-        modifyIORef queueRef (StartCData :)
-        return True
-        
-    setEndCDataHandler parser $ \_  -> do
-        modifyIORef queueRef (EndCData :)
-        return True
-        
-    setProcessingInstructionHandler parser $ \_ cTarget cText -> do
-        target <- textFromCString cTarget
-        txt <- textFromCString cText
-        modifyIORef queueRef (ProcessingInstruction target txt :)
-        return True
-        
-    setCommentHandler parser $ \_ cText -> do
-        txt <- textFromCString cText
-        modifyIORef queueRef (Comment txt :)
-        return True
+        setCharacterDataHandler parser $ \_ cText -> do
+            txt <- gxFromCStringLen cText
+            modifyIORef queueRef (CharacterData txt:)
+            return True
+            
+        setStartCDataHandler parser $ \_  -> do
+            modifyIORef queueRef (StartCData :)
+            return True
+            
+        setEndCDataHandler parser $ \_  -> do
+            modifyIORef queueRef (EndCData :)
+            return True
+            
+        setProcessingInstructionHandler parser $ \_ cTarget cText -> do
+            target <- textFromCString cTarget
+            txt <- textFromCString cText
+            modifyIORef queueRef (ProcessingInstruction target txt :)
+            return True
+            
+        setCommentHandler parser $ \_ cText -> do
+            txt <- textFromCString cText
+            modifyIORef queueRef (Comment txt :)
+            return True
 
-    let runParser inp = unsafeInterleaveIO $ do
-            rema <- withParser parser $ \pp -> case inp of
-                (c:cs) -> do
-                    mError <- parseChunk pp c False
-                    case mError of
-                        Just err -> return [FailDocument err]
-                        Nothing -> runParser cs
-                [] -> do
-                    mError <- parseChunk pp B.empty True
-                    case mError of
-                        Just err -> return [FailDocument err]
-                        Nothing -> return []
-            queue <- readIORef queueRef
-            writeIORef queueRef []
-            return $ reverse queue ++ rema
+        cacheRef <- newIORef Nothing
 
-    runParser $ L.toChunks input
+        return (parser, queueRef, cacheRef)
 
+    runParser :: l ByteString
+              -> IORef (Maybe (l (SAXEvent tag text)))
+              -> l (SAXEvent tag text)
+    runParser iblks cacheRef = joinL $ do
+        li <- runList iblks 
+        return $ unsafePerformIO $ do
+            mCached <- readIORef cacheRef
+            case mCached of
+                Just l -> return l
+                Nothing -> do
+                    (mError, rema) <- case li of
+                            Nil         -> do
+                                mError <- withParser parser $ \pp -> parseChunk pp B.empty True
+                                return (mError, mzero)
+                            Cons blk t -> unsafeInterleaveIO $ do
+                                mError <- withParser parser $ \pp -> parseChunk pp blk False
+                                cacheRef' <- newIORef Nothing
+                                return (mError, runParser t cacheRef')
+                    let rema' = case mError of
+                            Just err -> FailDocument err `cons` mzero
+                            Nothing -> rema
+                    queue <- readIORef queueRef
+                    writeIORef queueRef []
+                    let l = fromList (reverse queue) `mplus` rema'
+                    writeIORef cacheRef (Just l)
+                    return l
 
+-- | Lazily parse XML to SAX events. In the event of an error, FailDocument is
+-- the last element of the output list.
+parse :: (GenericXMLString tag, GenericXMLString text) =>
+         ParseOptions tag text  -- ^ Parse options
+      -> L.ByteString           -- ^ Input text (a lazy ByteString)
+      -> [SAXEvent tag text]
+parse opts input = parseG opts (L.toChunks input)
+
+
 -- | DEPRECATED: Use 'parse' instead.
 --
 -- Lazily parse XML to SAX events. In the event of an error, FailDocument is
@@ -312,104 +339,123 @@
 instance Exception XMLParseException where
 
 
--- | A variant of parseSAX that gives a document location with each SAX event.
-parseLocations :: (GenericXMLString tag, GenericXMLString text) =>
-                  ParseOptions tag text  -- ^ Parse options
-               -> L.ByteString            -- ^ Input text (a lazy ByteString)
-               -> [(SAXEvent tag text, XMLParseLocation)]
-parseLocations opts input = unsafePerformIO $ do
-    let enc = overrideEncoding opts
-    let mEntityDecoder = entityDecoder opts
+-- | Parse a generalized list of ByteStrings containing XML to SAX events.
+-- In the event of an error, FailDocument is the last element of the output list.
+parseLocationsG :: forall tag text l . (GenericXMLString tag, GenericXMLString text, List l) =>
+                   ParseOptions tag text -- ^ Parse options
+                -> l ByteString          -- ^ Input text (a lazy ByteString)
+                -> l (SAXEvent tag text, XMLParseLocation)
+parseLocationsG opts inputBlocks = runParser inputBlocks cacheRef
+  where
+    (parser, queueRef, cacheRef) = unsafePerformIO $ do
+        let enc = overrideEncoding opts
+        let mEntityDecoder = entityDecoder opts
 
-    -- Done with cut & paste coding for maximum speed.
-    parser <- newParser enc
-    queueRef <- newIORef []
+        parser <- newParser enc
+        queueRef <- newIORef []
 
-    case mEntityDecoder of
-        Just deco -> setEntityDecoder parser deco $ \pp txt -> do
+        case mEntityDecoder of
+            Just deco -> setEntityDecoder parser deco $ \pp txt -> do
+                loc <- getParseLocation pp
+                modifyIORef queueRef ((CharacterData txt, loc):)
+            Nothing -> return ()
+
+        setXMLDeclarationHandler parser $ \pp cVer cEnc cSd -> do
+            ver <- textFromCString cVer
+            mEnc <- if cEnc == nullPtr
+                then return Nothing
+                else Just <$> textFromCString cEnc
+            let sd = if cSd < 0
+                    then Nothing
+                    else Just $ if cSd /= 0 then True else False
             loc <- getParseLocation pp
-            modifyIORef queueRef ((CharacterData txt, loc):)
-        Nothing -> return ()
+            modifyIORef queueRef ((XMLDeclaration ver mEnc sd, loc):)
+            return True
 
-    setXMLDeclarationHandler parser $ \pp cVer cEnc cSd -> do
-        ver <- textFromCString cVer
-        mEnc <- if cEnc == nullPtr
-            then return Nothing
-            else Just <$> textFromCString cEnc
-        let sd = if cSd < 0
-                then Nothing
-                else Just $ if cSd /= 0 then True else False
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((XMLDeclaration ver mEnc sd,loc):)
-        return True
+        setStartElementHandler parser $ \pp cName cAttrs -> do
+            name <- textFromCString cName
+            attrs <- forM cAttrs $ \(cAttrName,cAttrValue) -> do
+                attrName <- textFromCString cAttrName
+                attrValue <- textFromCString cAttrValue
+                return (attrName, attrValue)
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((StartElement name attrs,loc):)
+            return True
 
-    setStartElementHandler parser $ \pp cName cAttrs -> do
-        name <- textFromCString cName
-        attrs <- forM cAttrs $ \(cAttrName,cAttrValue) -> do
-            attrName <- textFromCString cAttrName
-            attrValue <- textFromCString cAttrValue
-            return (attrName, attrValue)
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((StartElement name attrs,loc):)
-        return True
+        setEndElementHandler parser $ \pp cName -> do
+            name <- textFromCString cName
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((EndElement name, loc):)
+            return True
 
-    setEndElementHandler parser $ \pp cName -> do
-        name <- textFromCString cName
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((EndElement name, loc):)
-        return True
+        setCharacterDataHandler parser $ \pp cText -> do
+            txt <- gxFromCStringLen cText
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((CharacterData txt, loc):)
+            return True
+            
+        setStartCDataHandler parser $ \pp -> do
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((StartCData, loc):)
+            return True
+            
+        setEndCDataHandler parser $ \pp -> do
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((EndCData,loc):)
+            return True
+            
+        setProcessingInstructionHandler parser $ \pp cTarget cText -> do
+            target <- textFromCString cTarget
+            txt <- textFromCString cText
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((ProcessingInstruction target txt, loc):)
+            return True
+            
+        setCommentHandler parser $ \pp cText -> do
+            txt <- textFromCString cText
+            loc <- getParseLocation pp
+            modifyIORef queueRef ((Comment txt, loc):)
+            return True
 
-    setCharacterDataHandler parser $ \pp cText -> do
-        txt <- gxFromCStringLen cText
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((CharacterData txt, loc):)
-        return True
-        
-    setStartCDataHandler parser $ \pp -> do
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((StartCData, loc):)
-        return True
-        
-    setEndCDataHandler parser $ \pp -> do
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((EndCData, loc):)
-        return True
-        
-    setProcessingInstructionHandler parser $ \pp cTarget cText -> do
-        target <- textFromCString cTarget
-        txt <- textFromCString cText
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((ProcessingInstruction target txt, loc) :)
-        return True
-        
-    setCommentHandler parser $ \pp cText -> do
-        txt <- textFromCString cText
-        loc <- getParseLocation pp
-        modifyIORef queueRef ((Comment txt, loc) :)
-        return True
+        cacheRef <- newIORef Nothing
 
-    let runParser inp = unsafeInterleaveIO $ do
-            rema <- withParser parser $ \pp -> case inp of
-                (c:cs) -> do
-                    mError <- parseChunk pp c False
-                    case mError of
-                        Just err -> do
-                            loc <- getParseLocation pp
-                            return [(FailDocument err, loc)]
-                        Nothing -> runParser cs
-                [] -> do
-                    mError <- parseChunk pp B.empty True
-                    case mError of
-                        Just err -> do
-                            loc <- getParseLocation pp
-                            return [(FailDocument err, loc)]
-                        Nothing -> return []
-            queue <- readIORef queueRef
-            writeIORef queueRef []
-            return $ reverse queue ++ rema
+        return (parser, queueRef, cacheRef)
 
-    runParser $ L.toChunks input
+    runParser :: l ByteString
+              -> IORef (Maybe (l (SAXEvent tag text, XMLParseLocation)))
+              -> l (SAXEvent tag text, XMLParseLocation)
+    runParser iblks cacheRef = joinL $ do
+        li <- runList iblks 
+        return $ unsafePerformIO $ do
+            mCached <- readIORef cacheRef
+            case mCached of
+                Just l -> return l
+                Nothing -> do
+                    (mError, rema) <- case li of
+                            Nil         -> do
+                                mError <- withParser parser $ \pp -> parseChunk pp B.empty True
+                                return (mError, mzero)
+                            Cons blk t -> unsafeInterleaveIO $ do
+                                mError <- withParser parser $ \pp -> parseChunk pp blk False
+                                cacheRef' <- newIORef Nothing
+                                return (mError, runParser t cacheRef')
+                    rema' <- case mError of
+                            Just err -> do
+                                loc <- withParser parser getParseLocation
+                                return $ (FailDocument err, loc) `cons` mzero
+                            Nothing -> return rema
+                    queue <- readIORef queueRef
+                    writeIORef queueRef []
+                    let l = fromList (reverse queue) `mplus` rema'
+                    writeIORef cacheRef (Just l)
+                    return l
 
+-- | A variant of parseSAX that gives a document location with each SAX event.
+parseLocations :: (GenericXMLString tag, GenericXMLString text) =>
+                  ParseOptions tag text  -- ^ Parse options
+               -> L.ByteString            -- ^ Input text (a lazy ByteString)
+               -> [(SAXEvent tag text, XMLParseLocation)]
+parseLocations opts input = parseLocationsG opts (L.toChunks input)
 
 -- | DEPRECATED: Use 'parseLocations' instead.
 --
diff --git a/Text/XML/Expat/Tree.hs b/Text/XML/Expat/Tree.hs
--- a/Text/XML/Expat/Tree.hs
+++ b/Text/XML/Expat/Tree.hs
@@ -115,6 +115,7 @@
   Encoding(..),
   parse,
   parse',
+  parseG,
   XMLParseError(..),
   XMLParseLocation(..),
 
@@ -124,6 +125,7 @@
 
   -- * Convert from SAX
   saxToTree,
+  saxToTreeG,
 
   -- * Abstraction of string types
   GenericXMLString(..),
@@ -394,7 +396,7 @@
     let (nodes, mError, _) = ptl events
     in  (findRoot nodes, mError)
   where
-    findRoot (elt@(Element _ _ _ ):_) = elt
+    findRoot (elt@(Element _ _ _):_) = elt
     findRoot (_:nodes) = findRoot nodes
     findRoot [] = Element (gxFromString "") [] []
     ptl (StartElement name attrs:rema) =
@@ -410,6 +412,35 @@
     ptl (_:rema) = ptl rema  -- extended node types not supported in this tree type
     ptl [] = ([], Nothing, [])
 
+-- | A lower level function that converts a generalized SAX stream into a tree structure.
+-- Ignores parse errors.
+saxToTreeG :: (GenericXMLString tag, List l) =>
+              l (SAXEvent tag text)
+           -> ItemM l (NodeG l tag text)
+saxToTreeG events = do
+    (elts, _) <- process events
+    findRoot elts
+  where
+    findRoot elts = do
+        li <- runList elts
+        case li of
+            Cons elt@(Element _ _ _ ) _ -> return elt
+            Cons _ rema -> findRoot rema
+            Nil -> return $ Element (gxFromString "") mzero mzero
+    process events = do
+        li <- runList events
+        case li of
+            Nil -> return (mzero, mzero)
+            Cons (StartElement name attrs) rema -> do
+                (children, rema') <- process rema
+                (out, rema'') <- process rema'
+                return (Element name attrs children `cons` out, rema'')
+            Cons (EndElement _) rema -> return (mzero, rema)
+            Cons (CharacterData txt) rema -> do
+                (out, rema') <- process rema
+                return (Text txt `cons` out, rema')
+            --Cons (FailDocument err) rema = (mzero, mzero)
+            Cons _ rema -> process rema
 
 -- | Lazily parse XML to tree. Note that forcing the XMLParseError return value
 -- will force the entire parse.  Therefore, to ensure lazy operation, don't
@@ -420,6 +451,14 @@
       -> (Node tag text, Maybe XMLParseError)
 parse opts bs = saxToTree $ SAX.parse opts bs
 
+-- | Parse a generalized list to a tree, ignoring parse errors.
+-- This function allows for a parse from an enumerator/iteratee to a "lazy"
+-- tree structure using the @List-enumerator@ package.
+parseG :: (GenericXMLString tag, GenericXMLString text, List l) =>
+          ParseOptions tag text  -- ^ Parse options
+       -> l ByteString           -- ^ Input text as a generalized list of blocks
+       -> ItemM l (NodeG l tag text)
+parseG opts = saxToTreeG . SAX.parseG opts
 
 -- | DEPREACTED: Use 'parse' instead.
 --
diff --git a/hexpat.cabal b/hexpat.cabal
--- a/hexpat.cabal
+++ b/hexpat.cabal
@@ -1,6 +1,6 @@
 Cabal-Version: >= 1.6
 Name: hexpat
-Version: 0.19.6
+Version: 0.19.7
 Synopsis: XML parser/formatter based on expat
 Description:
   This package provides a general purpose Haskell XML library using Expat to
@@ -24,7 +24,7 @@
   with one of the lazy I\/O functions such as hGetContents.  However, this can be
   problematic in some applications because it doesn't handle I\/O errors properly
   and can give no guarantee of timely resource cleanup.  In these cases, chunked
-  I\/O is a better approach: Take a look at the /hexpat-iteratee/ package.
+  I\/O is a better approach: Take a look at the /hexpat-enumerator/ package.
   .
   /IO/ is filed under /Internal/ because it's low-level and most users won't want
   it.  The other /Internal/ modules are re-exported by /Annotated/, /Tree/ and /Extended/,
@@ -50,7 +50,8 @@
     if unbound (see note above); 0.19.2 include expat source code so \'cabal install\' just works
     on Linux, Mac and Windows (thanks Jacob Stanley); 0.19.3 fix misconfiguration of expat
     which broke entity parsing; 0.19.4 bump version constraint for text; 0.19.5 bump text
-    to < 0.12 and fix text-0.10.0.1 breakage; 0.19.6 dependency breakage with List.
+    to < 0.12 and fix text-0.10.0.1 breakage; 0.19.6 dependency breakage with List;
+    0.19.7 ghc-7.2.1 compatibility
 Category: XML
 License: BSD3
 License-File: LICENSE
@@ -122,7 +123,7 @@
     deepseq == 1.1.*,
     containers,
     extensible-exceptions == 0.1.*,
-    List == 0.4.*
+    List >= 0.4.2 && < 0.5
   Exposed-Modules:
     Text.XML.Expat.Annotated,
     Text.XML.Expat.Cursor,
diff --git a/test/hexpat-tests.cabal b/test/hexpat-tests.cabal
--- a/test/hexpat-tests.cabal
+++ b/test/hexpat-tests.cabal
@@ -4,17 +4,15 @@
 Build-Type: Simple
 
 Executable testsuite
-  hs-source-dirs:  .. suite
+  hs-source-dirs:  suite
   main-is:         TestSuite.hs
 
   build-depends:
     HUnit < 1.3,
-    QuickCheck == 2.3.*,
+    QuickCheck == 2.4.*,
     base >= 3 && < 5,
     bytestring,
     containers,
-    extensible-exceptions >= 0.1 && < 0.2,
-    haskell98,
     transformers,
     deepseq >= 1.1.0.0,
     parallel == 3.1.*,
@@ -23,20 +21,9 @@
     test-framework-quickcheck2 == 0.2.*,
     text >= 0.5,
     utf8-string >= 0.3.3,
-    List >= 0.4,
-    monads-fd,
-    random
+    List >= 0.4.2,
+    mtl,
+    random,
+    hexpat
 
   ghc-options: -Wall -fhpc -threaded
-  if impl(ghc >= 6.8)
-    ghc-options: -fwarn-tabs
-
-  include-dirs: ../cbits
-  c-sources:
-    ../cbits/xmlparse.c,
-    ../cbits/xmlrole.c,
-    ../cbits/xmltok.c,
-    ../cbits/xmltok_impl.c,
-    ../cbits/xmltok_ns.c
-  cc-options: -DHAVE_MEMMOVE -DXML_NS -DXML_DTD
-
diff --git a/test/suite/Text/XML/Expat/Tests.hs b/test/suite/Text/XML/Expat/Tests.hs
--- a/test/suite/Text/XML/Expat/Tests.hs
+++ b/test/suite/Text/XML/Expat/Tests.hs
@@ -1,5 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE OverloadedStrings, FlexibleInstances, TypeSynonymInstances #-}
 
 module Text.XML.Expat.Tests
   ( TCursor
diff --git a/test/suite/Text/XML/Expat/UnitTests.hs b/test/suite/Text/XML/Expat/UnitTests.hs
--- a/test/suite/Text/XML/Expat/UnitTests.hs
+++ b/test/suite/Text/XML/Expat/UnitTests.hs
@@ -11,7 +11,8 @@
 import qualified Data.ByteString.Lazy.Char8 as LC
 import qualified Data.ByteString.Lazy as L
 import qualified Data.Text as T
-import CForeign
+import Foreign
+import Foreign.C
 import Data.ByteString.Internal (c2w, w2c)
 import Data.Char
 import Data.Maybe
