xml-conduit 1.7.1.2 → 1.8.0
raw patch · 9 files changed
+297/−303 lines, 9 filesdep −blaze-builderdep ~bytestringdep ~conduitdep ~conduit-extraPVP ok
version bump matches the API change (PVP)
Dependencies removed: blaze-builder
Dependency ranges changed: bytestring, conduit, conduit-extra, resourcet
API changes (from Hackage documentation)
- Text.XML: fromEvents :: MonadThrow m => Consumer EventPos m Document
+ Text.XML: fromEvents :: MonadThrow m => ConduitT EventPos o m Document
- Text.XML: renderBytes :: (PrimMonad base, MonadBase base m) => RenderSettings -> Document -> ConduitM a ByteString m ()
+ Text.XML: renderBytes :: PrimMonad m => RenderSettings -> Document -> ConduitT i ByteString m ()
- Text.XML: sinkDoc :: MonadThrow m => ParseSettings -> Consumer ByteString m Document
+ Text.XML: sinkDoc :: MonadThrow m => ParseSettings -> ConduitT ByteString o m Document
- Text.XML: sinkTextDoc :: MonadThrow m => ParseSettings -> Consumer Text m Document
+ Text.XML: sinkTextDoc :: MonadThrow m => ParseSettings -> ConduitT Text o m Document
- Text.XML.Stream.Parse: choose :: Monad m => [ConduitM Event o m (Maybe a)] -> ConduitM Event o m (Maybe a)
+ Text.XML.Stream.Parse: choose :: Monad m => [ConduitT Event o m (Maybe a)] -> ConduitT Event o m (Maybe a)
- Text.XML.Stream.Parse: content :: MonadThrow m => Consumer Event m Text
+ Text.XML.Stream.Parse: content :: MonadThrow m => ConduitT Event o m Text
- Text.XML.Stream.Parse: contentMaybe :: MonadThrow m => Consumer Event m (Maybe Text)
+ Text.XML.Stream.Parse: contentMaybe :: MonadThrow m => ConduitT Event o m (Maybe Text)
- Text.XML.Stream.Parse: detectUtf :: MonadThrow m => Conduit ByteString m Text
+ Text.XML.Stream.Parse: detectUtf :: MonadThrow m => ConduitT ByteString Text m ()
- Text.XML.Stream.Parse: ignoreAllTreesContent :: MonadThrow m => ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreAllTreesContent :: MonadThrow m => ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: ignoreAnyTreeContent :: MonadThrow m => ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreAnyTreeContent :: MonadThrow m => ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: ignoreEmptyTag :: MonadThrow m => NameMatcher a -> ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreEmptyTag :: MonadThrow m => NameMatcher a -> ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: ignoreTag :: MonadThrow m => NameMatcher a -> ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreTag :: MonadThrow m => NameMatcher a -> ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: ignoreTree :: MonadThrow m => NameMatcher a -> ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreTree :: MonadThrow m => NameMatcher a -> ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: ignoreTreeContent :: MonadThrow m => NameMatcher a -> ConduitM Event o m (Maybe ())
+ Text.XML.Stream.Parse: ignoreTreeContent :: MonadThrow m => NameMatcher a -> ConduitT Event o m (Maybe ())
- Text.XML.Stream.Parse: many :: Monad m => ConduitM Event o m (Maybe a) -> ConduitM Event o m [a]
+ Text.XML.Stream.Parse: many :: Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a]
- Text.XML.Stream.Parse: many' :: MonadThrow m => ConduitM Event o m (Maybe a) -> ConduitM Event o m [a]
+ Text.XML.Stream.Parse: many' :: MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m [a]
- Text.XML.Stream.Parse: manyIgnore :: Monad m => ConduitM Event o m (Maybe a) -> ConduitM Event o m (Maybe b) -> ConduitM Event o m [a]
+ Text.XML.Stream.Parse: manyIgnore :: Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe b) -> ConduitT Event o m [a]
- Text.XML.Stream.Parse: manyIgnoreYield :: MonadThrow m => ConduitM Event b m (Maybe b) -> ConduitM Event b m (Maybe ()) -> Conduit Event m b
+ Text.XML.Stream.Parse: manyIgnoreYield :: MonadThrow m => ConduitT Event b m (Maybe b) -> ConduitT Event b m (Maybe ()) -> ConduitT Event b m ()
- Text.XML.Stream.Parse: manyYield :: Monad m => ConduitM a b m (Maybe b) -> Conduit a m b
+ Text.XML.Stream.Parse: manyYield :: Monad m => ConduitT a b m (Maybe b) -> ConduitT a b m ()
- Text.XML.Stream.Parse: manyYield' :: MonadThrow m => ConduitM Event b m (Maybe b) -> Conduit Event m b
+ Text.XML.Stream.Parse: manyYield' :: MonadThrow m => ConduitT Event b m (Maybe b) -> ConduitT Event b m ()
- Text.XML.Stream.Parse: many_ :: MonadThrow m => ConduitM Event o m (Maybe a) -> ConduitM Event o m ()
+ Text.XML.Stream.Parse: many_ :: MonadThrow m => ConduitT Event o m (Maybe a) -> ConduitT Event o m ()
- Text.XML.Stream.Parse: orE :: Monad m => Consumer Event m (Maybe a) -> Consumer Event m (Maybe a) -> Consumer Event m (Maybe a)
+ Text.XML.Stream.Parse: orE :: Monad m => ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe a) -> ConduitT Event o m (Maybe a)
- Text.XML.Stream.Parse: parseBytes :: MonadThrow m => ParseSettings -> Conduit ByteString m Event
+ Text.XML.Stream.Parse: parseBytes :: MonadThrow m => ParseSettings -> ConduitT ByteString Event m ()
- Text.XML.Stream.Parse: parseBytesPos :: MonadThrow m => ParseSettings -> Conduit ByteString m EventPos
+ Text.XML.Stream.Parse: parseBytesPos :: MonadThrow m => ParseSettings -> ConduitT ByteString EventPos m ()
- Text.XML.Stream.Parse: parseFile :: MonadResource m => ParseSettings -> FilePath -> Producer m Event
+ Text.XML.Stream.Parse: parseFile :: MonadResource m => ParseSettings -> FilePath -> ConduitT i Event m ()
- Text.XML.Stream.Parse: parseLBS :: MonadThrow m => ParseSettings -> ByteString -> Producer m Event
+ Text.XML.Stream.Parse: parseLBS :: MonadThrow m => ParseSettings -> ByteString -> ConduitT i Event m ()
- Text.XML.Stream.Parse: parseText :: MonadThrow m => ParseSettings -> Conduit Text m EventPos
+ Text.XML.Stream.Parse: parseText :: MonadThrow m => ParseSettings -> ConduitT Text EventPos m ()
- Text.XML.Stream.Parse: parseText' :: MonadThrow m => ParseSettings -> Conduit Text m Event
+ Text.XML.Stream.Parse: parseText' :: MonadThrow m => ParseSettings -> ConduitT Text Event m ()
- Text.XML.Stream.Parse: parseTextPos :: MonadThrow m => ParseSettings -> Conduit Text m EventPos
+ Text.XML.Stream.Parse: parseTextPos :: MonadThrow m => ParseSettings -> ConduitT Text EventPos m ()
- Text.XML.Stream.Parse: tag :: MonadThrow m => NameMatcher a -> (a -> AttrParser b) -> (b -> ConduitM Event o m c) -> ConduitM Event o m (Maybe c)
+ Text.XML.Stream.Parse: tag :: MonadThrow m => NameMatcher a -> (a -> AttrParser b) -> (b -> ConduitT Event o m c) -> ConduitT Event o m (Maybe c)
- Text.XML.Stream.Parse: tag' :: MonadThrow m => NameMatcher a -> AttrParser b -> (b -> ConduitM Event o m c) -> ConduitM Event o m (Maybe c)
+ Text.XML.Stream.Parse: tag' :: MonadThrow m => NameMatcher a -> AttrParser b -> (b -> ConduitT Event o m c) -> ConduitT Event o m (Maybe c)
- Text.XML.Stream.Parse: tagIgnoreAttrs :: MonadThrow m => NameMatcher a -> ConduitM Event o m b -> ConduitM Event o m (Maybe b)
+ Text.XML.Stream.Parse: tagIgnoreAttrs :: MonadThrow m => NameMatcher a -> ConduitT Event o m b -> ConduitT Event o m (Maybe b)
- Text.XML.Stream.Parse: tagNoAttr :: MonadThrow m => NameMatcher a -> ConduitM Event o m b -> ConduitM Event o m (Maybe b)
+ Text.XML.Stream.Parse: tagNoAttr :: MonadThrow m => NameMatcher a -> ConduitT Event o m b -> ConduitT Event o m (Maybe b)
- Text.XML.Stream.Parse: takeAllTreesContent :: MonadThrow m => ConduitM Event Event m (Maybe ())
+ Text.XML.Stream.Parse: takeAllTreesContent :: MonadThrow m => ConduitT Event Event m (Maybe ())
- Text.XML.Stream.Parse: takeAnyTreeContent :: MonadThrow m => ConduitM Event Event m (Maybe ())
+ Text.XML.Stream.Parse: takeAnyTreeContent :: MonadThrow m => ConduitT Event Event m (Maybe ())
- Text.XML.Stream.Parse: takeContent :: MonadThrow m => ConduitM Event Event m (Maybe ())
+ Text.XML.Stream.Parse: takeContent :: MonadThrow m => ConduitT Event Event m (Maybe ())
- Text.XML.Stream.Parse: takeTree :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitM Event Event m (Maybe ())
+ Text.XML.Stream.Parse: takeTree :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ())
- Text.XML.Stream.Parse: takeTreeContent :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitM Event Event m (Maybe ())
+ Text.XML.Stream.Parse: takeTreeContent :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ())
- Text.XML.Stream.Render: content :: (Monad m) => Text -> Source m Event
+ Text.XML.Stream.Render: content :: (Monad m) => Text -> ConduitT i Event m ()
- Text.XML.Stream.Render: prettify :: Monad m => Conduit (Flush Event) m (Flush Event)
+ Text.XML.Stream.Render: prettify :: Monad m => ConduitT (Flush Event) (Flush Event) m ()
- Text.XML.Stream.Render: renderBuilder :: Monad m => RenderSettings -> Conduit Event m Builder
+ Text.XML.Stream.Render: renderBuilder :: Monad m => RenderSettings -> ConduitT Event Builder m ()
- Text.XML.Stream.Render: renderBuilderFlush :: Monad m => RenderSettings -> Conduit (Flush Event) m (Flush Builder)
+ Text.XML.Stream.Render: renderBuilderFlush :: Monad m => RenderSettings -> ConduitT (Flush Event) (Flush Builder) m ()
- Text.XML.Stream.Render: renderBytes :: (PrimMonad base, MonadBase base m) => RenderSettings -> ConduitM Event ByteString m ()
+ Text.XML.Stream.Render: renderBytes :: PrimMonad m => RenderSettings -> ConduitT Event ByteString m ()
- Text.XML.Stream.Render: renderText :: (MonadThrow m, MonadBase base m, PrimMonad base) => RenderSettings -> ConduitM Event Text m ()
+ Text.XML.Stream.Render: renderText :: (PrimMonad m, MonadThrow m) => RenderSettings -> ConduitT Event Text m ()
- Text.XML.Stream.Render: tag :: (Monad m) => Name -> Attributes -> Source m Event -> Source m Event
+ Text.XML.Stream.Render: tag :: (Monad m) => Name -> Attributes -> ConduitT i Event m () -> ConduitT i Event m ()
- Text.XML.Unresolved: elementFromEvents :: MonadThrow m => Consumer EventPos m (Maybe Element)
+ Text.XML.Unresolved: elementFromEvents :: MonadThrow m => ConduitT EventPos o m (Maybe Element)
- Text.XML.Unresolved: fromEvents :: MonadThrow m => Consumer EventPos m Document
+ Text.XML.Unresolved: fromEvents :: MonadThrow m => ConduitT EventPos o m Document
- Text.XML.Unresolved: renderBuilder :: Monad m => RenderSettings -> Document -> Producer m Builder
+ Text.XML.Unresolved: renderBuilder :: Monad m => RenderSettings -> Document -> ConduitT i Builder m ()
- Text.XML.Unresolved: renderBytes :: (MonadBase base m, PrimMonad base) => RenderSettings -> Document -> ConduitM a ByteString m ()
+ Text.XML.Unresolved: renderBytes :: PrimMonad m => RenderSettings -> Document -> ConduitT i ByteString m ()
- Text.XML.Unresolved: renderText :: (PrimMonad base, MonadBase base m, MonadThrow m) => RenderSettings -> Document -> ConduitM a Text m ()
+ Text.XML.Unresolved: renderText :: (MonadThrow m, PrimMonad m) => RenderSettings -> Document -> ConduitT i Text m ()
- Text.XML.Unresolved: sinkDoc :: MonadThrow m => ParseSettings -> Consumer ByteString m Document
+ Text.XML.Unresolved: sinkDoc :: MonadThrow m => ParseSettings -> ConduitT ByteString o m Document
- Text.XML.Unresolved: sinkTextDoc :: MonadThrow m => ParseSettings -> Consumer Text m Document
+ Text.XML.Unresolved: sinkTextDoc :: MonadThrow m => ParseSettings -> ConduitT Text o m Document
Files
- ChangeLog.md +4/−0
- Text/XML.hs +19/−21
- Text/XML/Cursor.hs +3/−3
- Text/XML/Stream/Parse.hs +81/−82
- Text/XML/Stream/Render.hs +35/−33
- Text/XML/Stream/Token.hs +89/−90
- Text/XML/Unresolved.hs +28/−33
- test/main.hs +33/−35
- xml-conduit.cabal +5/−6
ChangeLog.md view
@@ -1,3 +1,7 @@+## 1.8.0++* Upgrade to conduit 1.3.0+ ## 1.7.1 * Add `psDecodeIllegalCharacters` field in `ParseSettings` to specify how illegal characters references should be decoded
Text/XML.hs view
@@ -74,13 +74,12 @@ , fromXMLElement ) where +import Conduit import Control.Applicative ((<$>)) import Control.DeepSeq (NFData (rnf)) import Control.Exception (Exception, SomeException, handle, throw, throwIO)-import Control.Monad.ST (runST)-import Control.Monad.Trans.Resource (MonadThrow, monadThrow,- runExceptionT, runResourceT)+import Control.Monad.Trans.Resource (MonadThrow, throwM) import Data.ByteString (ByteString) import qualified Data.ByteString.Lazy as L import Data.Data (Data)@@ -104,7 +103,6 @@ import qualified Text.XML.Unresolved as D import Control.Monad.Trans.Class (lift)-import Data.Conduit import qualified Data.Conduit.Binary as CB import Data.Conduit.Lazy (lazyConsume) import qualified Data.Conduit.List as CL@@ -228,7 +226,7 @@ readFile :: ParseSettings -> FilePath -> IO Document readFile ps fp = handle (throwIO . InvalidXMLFile fp)- (runResourceT $ CB.sourceFile fp $$ sinkDoc ps)+ (runConduitRes $ CB.sourceFile fp .| sinkDoc ps) data XMLException = InvalidXMLFile FilePath SomeException deriving Typeable@@ -243,48 +241,48 @@ instance Exception XMLException parseLBS :: ParseSettings -> L.ByteString -> Either SomeException Document-parseLBS ps lbs = runST- $ runExceptionT- $ CL.sourceList (L.toChunks lbs)- $$ sinkDoc ps+parseLBS ps lbs+ = runConduit+ $ CL.sourceList (L.toChunks lbs)+ .| sinkDoc ps parseLBS_ :: ParseSettings -> L.ByteString -> Document parseLBS_ ps = either throw id . parseLBS ps sinkDoc :: MonadThrow m => ParseSettings- -> Consumer ByteString m Document-sinkDoc ps = P.parseBytesPos ps =$= fromEvents+ -> ConduitT ByteString o m Document+sinkDoc ps = P.parseBytesPos ps .| fromEvents parseText :: ParseSettings -> TL.Text -> Either SomeException Document-parseText ps tl = runST- $ runExceptionT- $ CL.sourceList (TL.toChunks tl)- $$ sinkTextDoc ps+parseText ps tl+ = runConduit+ $ CL.sourceList (TL.toChunks tl)+ .| sinkTextDoc ps parseText_ :: ParseSettings -> TL.Text -> Document parseText_ ps = either throw id . parseText ps sinkTextDoc :: MonadThrow m => ParseSettings- -> Consumer Text m Document-sinkTextDoc ps = P.parseTextPos ps =$= fromEvents+ -> ConduitT Text o m Document+sinkTextDoc ps = P.parseTextPos ps .| fromEvents -fromEvents :: MonadThrow m => Consumer P.EventPos m Document+fromEvents :: MonadThrow m => ConduitT P.EventPos o m Document fromEvents = do d <- D.fromEvents- either (lift . monadThrow . UnresolvedEntityException) return $ fromXMLDocument d+ either (lift . throwM . UnresolvedEntityException) return $ fromXMLDocument d data UnresolvedEntityException = UnresolvedEntityException (Set Text) deriving (Show, Typeable) instance Exception UnresolvedEntityException ---renderBytes :: MonadUnsafeIO m => R.RenderSettings -> Document -> Producer m ByteString+renderBytes :: PrimMonad m => D.RenderSettings -> Document -> ConduitT i ByteString m () renderBytes rs doc = D.renderBytes rs $ toXMLDocument' rs doc writeFile :: R.RenderSettings -> FilePath -> Document -> IO () writeFile rs fp doc =- runResourceT $ renderBytes rs doc $$ CB.sinkFile fp+ runConduitRes $ renderBytes rs doc .| CB.sinkFile fp renderLBS :: R.RenderSettings -> Document -> L.ByteString renderLBS rs doc =
Text/XML/Cursor.hs view
@@ -60,7 +60,7 @@ import Control.Exception (Exception) import Control.Monad-import Control.Monad.Trans.Resource (MonadThrow, monadThrow)+import Control.Monad.Trans.Resource (MonadThrow, throwM) import Data.Function (on) import qualified Data.Map as Map import Data.Maybe (maybeToList)@@ -214,9 +214,9 @@ _ -> [] force :: (Exception e, MonadThrow f) => e -> [a] -> f a-force e [] = monadThrow e+force e [] = throwM e force _ (x:_) = return x forceM :: (Exception e, MonadThrow f) => e -> [f a] -> f a-forceM e [] = monadThrow e+forceM e [] = throwM e forceM _ (x:_) = x
Text/XML/Stream/Parse.hs view
@@ -35,7 +35,7 @@ -- > data Person = Person Int Text -- > deriving Show -- >--- > parsePerson :: MonadThrow m => Consumer Event m (Maybe Person)+-- > parsePerson :: MonadThrow m => ConduitT Event o m (Maybe Person) -- > parsePerson = tag' "person" (requireAttr "age") $ \age -> do -- > name <- content -- > return $ Person (read $ unpack age) name@@ -72,7 +72,7 @@ -- > -- > data Person = Person Int Text deriving Show -- >--- > parsePerson :: MonadThrow m => Consumer Event m (Maybe Person)+-- > parsePerson :: MonadThrow m => ConduitT Event o m (Maybe Person) -- > parsePerson = tag' "person" (requireAttr "age") $ \age -> do -- > name <- content -- > return $ Person (read $ unpack age) name@@ -81,7 +81,7 @@ -- > parsePeople = void $ tagNoAttr "people" $ manyYield parsePerson -- > -- > main = runResourceT $--- > parseFile def "people.xml" $$ parsePeople =$ CL.mapM_ (lift . print)+-- > parseFile def "people.xml" $$ parsePeople .| CL.mapM_ (lift . print) -- -- Previous versions of this module contained a number of more sophisticated -- functions written by Aristid Breitkreuz and Dmitry Olshansky. To keep this@@ -166,10 +166,11 @@ import Control.Exception (Exception (..), SomeException) import Control.Monad (ap, liftM, void) import Control.Monad.Fix (fix)+import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Maybe (MaybeT (..)) import Control.Monad.Trans.Resource (MonadResource, MonadThrow (..),- monadThrow)+ throwM) import Data.Attoparsec.Text (Parser, anyChar, char, manyTill, skipWhile, string, takeWhile, takeWhile1, try)@@ -177,11 +178,9 @@ import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import Data.Char (isSpace)-import Data.Conduit-import Data.Conduit.Attoparsec (PositionRange, conduitParser)-import Data.Conduit.Binary (sourceFile)-import qualified Data.Conduit.List as CL+import Conduit import qualified Data.Conduit.Text as CT+import Data.Conduit.Attoparsec (PositionRange, conduitParser) import Data.Default.Class (Default (..)) import Data.List (intercalate) import Data.List (foldl')@@ -271,7 +270,7 @@ -- first checks for BOMs, removing them as necessary, and then check for the -- equivalent of <?xml for each of UTF-8, UTF-16LE/BE, and UTF-32LE/BE. It -- defaults to assuming UTF-8.-detectUtf :: MonadThrow m => Conduit S.ByteString m T.Text+detectUtf :: MonadThrow m => ConduitT S.ByteString T.Text m () detectUtf = conduit id where@@ -307,7 +306,7 @@ checkXMLDecl :: MonadThrow m => S.ByteString -> Maybe CT.Codec- -> Conduit S.ByteString m T.Text+ -> ConduitT S.ByteString T.Text m () checkXMLDecl bs (Just codec) = leftover bs >> CT.decode codec checkXMLDecl bs0 Nothing = loop [] (AT.parse (parseToken def)) bs0@@ -343,15 +342,15 @@ -- to do the actual parsing. parseBytes :: MonadThrow m => ParseSettings- -> Conduit S.ByteString m Event+ -> ConduitT S.ByteString Event m () parseBytes = mapOutput snd . parseBytesPos parseBytesPos :: MonadThrow m => ParseSettings- -> Conduit S.ByteString m EventPos-parseBytesPos ps = detectUtf =$= parseTextPos ps+ -> ConduitT S.ByteString EventPos m ()+parseBytesPos ps = detectUtf .| parseTextPos ps -dropBOM :: Monad m => Conduit T.Text m T.Text+dropBOM :: Monad m => ConduitT T.Text T.Text m () dropBOM = await >>= maybe (return ()) push where@@ -374,13 +373,13 @@ -- Since 1.2.4 parseText' :: MonadThrow m => ParseSettings- -> Conduit T.Text m Event+ -> ConduitT T.Text Event m () parseText' = mapOutput snd . parseTextPos {-# DEPRECATED parseText "Please use 'parseText'' or 'parseTextPos'." #-} parseText :: MonadThrow m => ParseSettings- -> Conduit T.Text m EventPos+ -> ConduitT T.Text EventPos m () parseText = parseTextPos -- | Same as 'parseText'', but includes the position of each event.@@ -388,12 +387,12 @@ -- Since 1.2.4 parseTextPos :: MonadThrow m => ParseSettings- -> Conduit T.Text m EventPos+ -> ConduitT T.Text EventPos m () parseTextPos de = dropBOM- =$= tokenize- =$= toEventC de- =$= addBeginEnd+ .| tokenize+ .| toEventC de+ .| addBeginEnd where tokenize = conduitToken de addBeginEnd = yield (Nothing, EventBeginDocument) >> addEnd@@ -401,7 +400,7 @@ (yield (Nothing, EventEndDocument)) (\e -> yield e >> addEnd) -toEventC :: Monad m => ParseSettings -> Conduit (PositionRange, Token) m EventPos+toEventC :: Monad m => ParseSettings -> ConduitT (PositionRange, Token) EventPos m () toEventC ps = go [] [] where@@ -446,7 +445,7 @@ , psDecodeIllegalCharacters = const Nothing } -conduitToken :: MonadThrow m => ParseSettings -> Conduit T.Text m (PositionRange, Token)+conduitToken :: MonadThrow m => ParseSettings -> ConduitT T.Text (PositionRange, Token) m () conduitToken = conduitParser . parseToken parseToken :: ParseSettings -> Parser Token@@ -667,13 +666,13 @@ -- | Grabs the next piece of content if available. This function skips over any -- comments and instructions and concatenates all content until the next start -- or end tag.-contentMaybe :: MonadThrow m => Consumer Event m (Maybe Text)+contentMaybe :: MonadThrow m => ConduitT Event o m (Maybe Text) contentMaybe = do- x <- CL.peek+ x <- peekC case pc' x of- Ignore -> CL.drop 1 >> contentMaybe- IsContent t -> CL.drop 1 >> fmap Just (takeContents (t:))- IsError e -> lift $ monadThrow $ InvalidEntity e x+ Ignore -> dropC 1 >> contentMaybe+ IsContent t -> dropC 1 >> fmap Just (takeContents (t:))+ IsError e -> lift $ throwM $ InvalidEntity e x NotContent -> return Nothing where pc' Nothing = NotContent@@ -690,16 +689,16 @@ pc EventInstruction{} = Ignore pc EventComment{} = Ignore takeContents front = do- x <- CL.peek+ x <- peekC case pc' x of- Ignore -> CL.drop 1 >> takeContents front- IsContent t -> CL.drop 1 >> takeContents (front . (:) t)- IsError e -> lift $ monadThrow $ InvalidEntity e x+ Ignore -> dropC 1 >> takeContents front+ IsContent t -> dropC 1 >> takeContents (front . (:) t)+ IsError e -> lift $ throwM $ InvalidEntity e x NotContent -> return $ T.concat $ front [] -- | Grabs the next piece of content. If none if available, returns 'T.empty'. -- This is simply a wrapper around 'contentMaybe'.-content :: MonadThrow m => Consumer Event m Text+content :: MonadThrow m => ConduitT Event o m Text content = fromMaybe T.empty <$> contentMaybe @@ -733,9 +732,9 @@ -> (a -> AttrParser b) -- ^ Given the value returned by the name checker, this function will -- be used to get an @AttrParser@ appropriate for the specific tag. -- If the @AttrParser@ fails, the function will also return @Nothing@- -> (b -> ConduitM Event o m c) -- ^ Handler function to handle the attributes and children+ -> (b -> ConduitT Event o m c) -- ^ Handler function to handle the attributes and children -- of a tag, given the value return from the @AttrParser@- -> ConduitM Event o m (Maybe c)+ -> ConduitT Event o m (Maybe c) tag nameMatcher attrParser f = do (x, leftovers) <- dropWS [] res <- case x of@@ -748,7 +747,7 @@ case a of Just (EventEndElement name') | name == name' -> return (Just z')- _ -> lift $ monadThrow $ InvalidEndElement name a+ _ -> lift $ throwM $ InvalidEndElement name a Nothing -> return Nothing _ -> return Nothing @@ -776,29 +775,29 @@ case runAttrParser p as of Left e -> Left e Right ([], x) -> Right x- Right (attr, _) -> Left $ toException $ UnparsedAttributes attr+ Right (attr', _) -> Left $ toException $ UnparsedAttributes attr' -- | A simplified version of 'tag' where the 'NameMatcher' result isn't forwarded to the attributes parser. -- -- Since 1.5.0 tag' :: MonadThrow m- => NameMatcher a -> AttrParser b -> (b -> ConduitM Event o m c)- -> ConduitM Event o m (Maybe c)+ => NameMatcher a -> AttrParser b -> (b -> ConduitT Event o m c)+ -> ConduitT Event o m (Maybe c) tag' a b = tag a (const b) -- | A further simplified tag parser, which requires that no attributes exist. tagNoAttr :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m b -- ^ Handler function to handle the children of the matched tag- -> ConduitM Event o m (Maybe b)+ -> ConduitT Event o m b -- ^ Handler function to handle the children of the matched tag+ -> ConduitT Event o m (Maybe b) tagNoAttr name f = tag' name (return ()) $ const f -- | A further simplified tag parser, which ignores all attributes, if any exist tagIgnoreAttrs :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m b -- ^ Handler function to handle the children of the matched tag- -> ConduitM Event o m (Maybe b)+ -> ConduitT Event o m b -- ^ Handler function to handle the children of the matched tag+ -> ConduitT Event o m (Maybe b) tagIgnoreAttrs name f = tag' name ignoreAttrs $ const f @@ -810,14 +809,14 @@ -- Since 1.5.0 ignoreEmptyTag :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m (Maybe ())+ -> ConduitT Event o m (Maybe ()) ignoreEmptyTag nameMatcher = tagIgnoreAttrs nameMatcher (return ()) {-# DEPRECATED ignoreTag "Please use 'ignoreEmptyTag'." #-} ignoreTag :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m (Maybe ())+ -> ConduitT Event o m (Maybe ()) ignoreTag = ignoreEmptyTag @@ -828,21 +827,21 @@ -- Since 1.5.0 ignoreTreeContent :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m (Maybe ())+ -> ConduitT Event o m (Maybe ()) ignoreTreeContent namePred = tagIgnoreAttrs namePred (void $ many ignoreAnyTreeContent) {-# DEPRECATED ignoreTree "Please use 'ignoreTreeContent'." #-} ignoreTree :: MonadThrow m => NameMatcher a -- ^ Check if this is a correct tag name- -> ConduitM Event o m (Maybe ())+ -> ConduitT Event o m (Maybe ()) ignoreTree = ignoreTreeContent -- | Like 'ignoreTreeContent', but matches any name and also ignores content events.-ignoreAnyTreeContent :: MonadThrow m => ConduitM Event o m (Maybe ())+ignoreAnyTreeContent :: MonadThrow m => ConduitT Event o m (Maybe ()) ignoreAnyTreeContent = (void <$> contentMaybe) `orE` ignoreTreeContent anyName {-# DEPRECATED ignoreAllTreesContent "Please use 'ignoreAnyTreeContent'." #-}-ignoreAllTreesContent :: MonadThrow m => ConduitM Event o m (Maybe ())+ignoreAllTreesContent :: MonadThrow m => ConduitT Event o m (Maybe ()) ignoreAllTreesContent = ignoreAnyTreeContent -- | Get the value of the first parser which returns 'Just'. If no parsers@@ -850,16 +849,16 @@ -- -- > orE a b = choose [a, b] orE :: Monad m- => Consumer Event m (Maybe a) -- ^ The first (preferred) parser- -> Consumer Event m (Maybe a) -- ^ The second parser, only executed if the first parser fails- -> Consumer Event m (Maybe a)+ => ConduitT Event o m (Maybe a) -- ^ The first (preferred) parser+ -> ConduitT Event o m (Maybe a) -- ^ The second parser, only executed if the first parser fails+ -> ConduitT Event o m (Maybe a) orE a b = a >>= \x -> maybe b (const $ return x) x -- | Get the value of the first parser which returns 'Just'. If no parsers -- succeed (i.e., return 'Just'), this function returns 'Nothing'. choose :: Monad m- => [ConduitM Event o m (Maybe a)] -- ^ List of parsers that will be tried in order.- -> ConduitM Event o m (Maybe a) -- ^ Result of the first parser to succeed, or @Nothing@+ => [ConduitT Event o m (Maybe a)] -- ^ List of parsers that will be tried in order.+ -> ConduitT Event o m (Maybe a) -- ^ Result of the first parser to succeed, or @Nothing@ -- if no parser succeeded choose [] = return Nothing choose (i:is) = i >>= maybe (choose is) (return . Just)@@ -879,15 +878,15 @@ parseFile :: MonadResource m => ParseSettings -> FilePath- -> Producer m Event-parseFile ps fp = sourceFile fp =$= parseBytes ps+ -> ConduitT i Event m ()+parseFile ps fp = sourceFile fp .| transPipe liftIO (parseBytes ps) -- | Parse an event stream from a lazy 'L.ByteString'. parseLBS :: MonadThrow m => ParseSettings -> L.ByteString- -> Producer m Event-parseLBS ps lbs = CL.sourceList (L.toChunks lbs) =$= parseBytes ps+ -> ConduitT i Event m ()+parseLBS ps lbs = sourceLazy lbs .| parseBytes ps data XmlException = XmlException { xmlErrorMessage :: String@@ -1021,24 +1020,24 @@ -- | Keep parsing elements as long as the parser returns 'Just'. many :: Monad m- => ConduitM Event o m (Maybe a)- -> ConduitM Event o m [a]+ => ConduitT Event o m (Maybe a)+ -> ConduitT Event o m [a] many i = manyIgnore i $ return Nothing -- | Like 'many' but discards the results without building an intermediate list. -- -- Since 1.5.0 many_ :: MonadThrow m- => ConduitM Event o m (Maybe a)- -> ConduitM Event o m ()+ => ConduitT Event o m (Maybe a)+ -> ConduitT Event o m () many_ consumer = manyIgnoreYield (return Nothing) (void <$> consumer) -- | Keep parsing elements as long as the parser returns 'Just' -- or the ignore parser returns 'Just'. manyIgnore :: Monad m- => ConduitM Event o m (Maybe a)- -> ConduitM Event o m (Maybe b)- -> ConduitM Event o m [a]+ => ConduitT Event o m (Maybe a)+ -> ConduitT Event o m (Maybe b)+ -> ConduitT Event o m [a] manyIgnore i ignored = go id where go front = i >>= maybe (onFail front) (\y -> go $ front . (:) y) -- onFail is called if the main parser fails@@ -1047,25 +1046,25 @@ -- | Like @many@, but any tags and content the consumer doesn't match on -- are silently ignored. many' :: MonadThrow m- => ConduitM Event o m (Maybe a)- -> ConduitM Event o m [a]+ => ConduitT Event o m (Maybe a)+ -> ConduitT Event o m [a] many' consumer = manyIgnore consumer ignoreAllTreesContent -- | Like 'many', but uses 'yield' so the result list can be streamed -- to downstream conduits without waiting for 'manyYield' to finish manyYield :: Monad m- => ConduitM a b m (Maybe b)- -> Conduit a m b+ => ConduitT a b m (Maybe b)+ -> ConduitT a b m () manyYield consumer = fix $ \loop -> consumer >>= maybe (return ()) (\x -> yield x >> loop) -- | Like 'manyIgnore', but uses 'yield' so the result list can be streamed -- to downstream conduits without waiting for 'manyIgnoreYield' to finish manyIgnoreYield :: MonadThrow m- => ConduitM Event b m (Maybe b) -- ^ Consuming parser that generates the result stream- -> ConduitM Event b m (Maybe ()) -- ^ Ignore parser that consumes elements to be ignored- -> Conduit Event m b+ => ConduitT Event b m (Maybe b) -- ^ Consuming parser that generates the result stream+ -> ConduitT Event b m (Maybe ()) -- ^ Ignore parser that consumes elements to be ignored+ -> ConduitT Event b m () manyIgnoreYield consumer ignoreParser = fix $ \loop -> consumer >>= maybe (onFail loop) (\x -> yield x >> loop) where onFail loop = ignoreParser >>= maybe (return ()) (const loop)@@ -1073,8 +1072,8 @@ -- | Like 'many'', but uses 'yield' so the result list can be streamed -- to downstream conduits without waiting for 'manyYield'' to finish manyYield' :: MonadThrow m- => ConduitM Event b m (Maybe b)- -> Conduit Event m b+ => ConduitT Event b m (Maybe b)+ -> ConduitT Event b m () manyYield' consumer = manyIgnoreYield consumer ignoreAllTreesContent @@ -1083,7 +1082,7 @@ -- Returns @Just ()@ if a content 'Event' was consumed, @Nothing@ otherwise. -- -- Since 1.5.0-takeContent :: MonadThrow m => ConduitM Event Event m (Maybe ())+takeContent :: MonadThrow m => ConduitT Event Event m (Maybe ()) takeContent = do event <- await case event of@@ -1103,7 +1102,7 @@ -- Returns @Just ()@ if an element was consumed, 'Nothing' otherwise. -- -- Since 1.5.0-takeTree :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitM Event Event m (Maybe ())+takeTree :: MonadThrow m => NameMatcher a -> AttrParser b -> ConduitT Event Event m (Maybe ()) takeTree nameMatcher attrParser = do event <- await case event of@@ -1115,7 +1114,7 @@ endEvent <- await case endEvent of Just e'@(EventEndElement name') | name == name' -> yield e' >> return (Just ())- _ -> lift $ monadThrow $ InvalidEndElement name endEvent+ _ -> lift $ throwM $ InvalidEndElement name endEvent _ -> leftover e >> return Nothing _ -> leftover e >> return Nothing @@ -1130,27 +1129,27 @@ takeTreeContent :: MonadThrow m => NameMatcher a -> AttrParser b- -> ConduitM Event Event m (Maybe ())+ -> ConduitT Event Event m (Maybe ()) takeTreeContent nameMatcher attrParser = runMaybeT $ MaybeT (takeTree nameMatcher attrParser) <|> MaybeT takeContent -- | Like 'takeTreeContent', without checking for tag name or attributes. ----- >>> runResourceT $ parseLBS def "text<a></a>" $$ takeAnyTreeContent =$= consume+-- >>> runResourceT $ parseLBS def "text<a></a>" $$ takeAnyTreeContent .| consume -- Just [ EventContent (ContentText "text") ] ----- >>> runResourceT $ parseLBS def "</a><b></b>" $$ takeAnyTreeContent =$= consume+-- >>> runResourceT $ parseLBS def "</a><b></b>" $$ takeAnyTreeContent .| consume -- Just [ ] ----- >>> runResourceT $ parseLBS def "<b><c></c></b></a>text" $$ takeAnyTreeContent =$= consume+-- >>> runResourceT $ parseLBS def "<b><c></c></b></a>text" $$ takeAnyTreeContent .| consume -- Just [ EventBeginElement "b" [], EventBeginElement "c" [], EventEndElement "c", EventEndElement "b" ] -- -- Since 1.5.0 takeAnyTreeContent :: MonadThrow m- => ConduitM Event Event m (Maybe ())+ => ConduitT Event Event m (Maybe ()) takeAnyTreeContent = takeTreeContent anyName ignoreAttrs {-# DEPRECATED takeAllTreesContent "Please use 'takeAnyTreeContent'." #-}-takeAllTreesContent :: MonadThrow m => ConduitM Event Event m (Maybe ())+takeAllTreesContent :: MonadThrow m => ConduitT Event Event m (Maybe ()) takeAllTreesContent = takeAnyTreeContent
Text/XML/Stream/Render.hs view
@@ -30,14 +30,11 @@ , optionalAttr ) where -import Blaze.ByteString.Builder import Control.Applicative ((<$>)) import Control.Monad.Trans.Resource (MonadThrow) import Data.ByteString (ByteString)-import Data.Conduit-import Data.Conduit.Blaze (builderToByteString)-import qualified Data.Conduit.List as CL-import qualified Data.Conduit.Text as CT+import Data.ByteString.Builder (Builder)+import Conduit import Data.Default.Class (Default (def)) import Data.List (foldl') import Data.Map (Map)@@ -56,17 +53,14 @@ -- optimally sized 'ByteString's with minimal buffer copying. -- -- The output is UTF8 encoded.---renderBytes :: Monad m => RenderSettings -> Conduit Event m ByteString-renderBytes rs = renderBuilder rs =$= builderToByteString+renderBytes :: PrimMonad m => RenderSettings -> ConduitT Event ByteString m ()+renderBytes rs = renderBuilder rs .| builderToByteString -- | Render a stream of 'Event's into a stream of 'Text's. This function -- wraps around 'renderBuilder', 'builderToByteString' and 'renderBytes', so it -- produces optimally sized 'Text's with minimal buffer copying.-{--renderText :: (MonadThrow m)- => RenderSettings -> Conduit Event m Text--}-renderText rs = renderBytes rs =$= CT.decode CT.utf8+renderText :: (PrimMonad m, MonadThrow m) => RenderSettings -> ConduitT Event Text m ()+renderText rs = renderBytes rs .| decodeUtf8C data RenderSettings = RenderSettings { rsPretty :: Bool@@ -118,7 +112,7 @@ where order elt attrMap = let initialAttrs = fromMaybe [] $ lookup elt orderSpec- mkPair attr = (,) attr <$> Map.lookup attr attrMap+ mkPair attr' = (,) attr' <$> Map.lookup attr' attrMap otherAttrMap = Map.filterWithKey (const . not . (`elem` initialAttrs)) attrMap in mapMaybe mkPair initialAttrs ++ Map.toAscList otherAttrMap@@ -126,8 +120,8 @@ -- | Render a stream of 'Event's into a stream of 'Builder's. Builders are from -- the blaze-builder package, and allow the create of optimally sized -- 'ByteString's with minimal buffer copying.-renderBuilder :: Monad m => RenderSettings -> Conduit Event m Builder-renderBuilder settings = CL.map Chunk =$= renderBuilder' yield' settings+renderBuilder :: Monad m => RenderSettings -> ConduitT Event Builder m ()+renderBuilder settings = mapC Chunk .| renderBuilder' yield' settings where yield' Flush = return () yield' (Chunk bs) = yield bs@@ -136,18 +130,26 @@ -- events at needed point are rendered. -- -- @since 1.3.5-renderBuilderFlush :: Monad m => RenderSettings -> Conduit (Flush Event) m (Flush Builder)+renderBuilderFlush :: Monad m => RenderSettings -> ConduitT (Flush Event) (Flush Builder) m () renderBuilderFlush = renderBuilder' yield -renderBuilder' :: Monad m => (Flush Builder -> Producer m o) -> RenderSettings -> Conduit (Flush Event) m o+renderBuilder'+ :: Monad m+ => (Flush Builder -> ConduitT (Flush Event) o m ())+ -> RenderSettings+ -> ConduitT (Flush Event) o m () renderBuilder' yield' settings = if rsPretty settings- then prettify =$= renderEvent'+ then prettify .| renderEvent' else renderEvent' where renderEvent' = renderEvent yield' settings -renderEvent :: Monad m => (Flush Builder -> Producer m o) -> RenderSettings -> Conduit (Flush Event) m o+renderEvent+ :: Monad m+ => (Flush Builder -> ConduitT (Flush Event) o m ())+ -> RenderSettings+ -> ConduitT (Flush Event) o m () renderEvent yield' RenderSettings { rsPretty = isPretty, rsNamespaces = namespaces0, rsUseCDATA = useCDATA, rsXMLDeclaration = useXMLDecl } = loop [] where@@ -157,11 +159,11 @@ go nslevels (Chunk e) = case e of EventBeginElement n1 as -> do- mnext <- CL.peek+ mnext <- peekC isClosed <- case mnext of Just (Chunk (EventEndElement n2)) | n1 == n2 -> do- CL.drop 1+ dropC 1 return True _ -> return False let (token, nslevels') = mkBeginToken isPretty isClosed namespaces0 nslevels n1 as@@ -291,10 +293,10 @@ -- | Convert a stream of 'Event's into a prettified one, adding extra -- whitespace. Note that this can change the meaning of your XML.-prettify :: Monad m => Conduit (Flush Event) m (Flush Event)+prettify :: Monad m => ConduitT (Flush Event) (Flush Event) m () prettify = prettify' 0 -prettify' :: Monad m => Int -> Conduit (Flush Event) m (Flush Event)+prettify' :: Monad m => Int -> ConduitT (Flush Event) (Flush Event) m () prettify' level = await >>= maybe (return ()) goC where@@ -310,10 +312,10 @@ go e@EventBeginElement{} = do yield' before yield' e- mnext <- CL.peek+ mnext <- peekC case mnext of Just (Chunk next@EventEndElement{}) -> do- CL.drop 1+ dropC 1 yield' next yield' after prettify' level@@ -357,13 +359,13 @@ go e@EventEndDoctype{} = yield' e >> yield' after >> prettify' level takeContents front = do- me <- CL.peek+ me <- peekC case me of Just (Chunk (EventContent c)) -> do- CL.drop 1+ dropC 1 takeContents $ front . (c:) Just (Chunk (EventCDATA t)) -> do- CL.drop 1+ dropC 1 takeContents $ front . (ContentText t:) _ -> return $ front [] @@ -389,15 +391,15 @@ -- | Generate a complete XML 'Element'.-tag :: (Monad m) => Name -> Attributes -> Source m Event -- ^ 'Element''s subnodes.- -> Source m Event-tag name (Attributes a) content = do+tag :: (Monad m) => Name -> Attributes -> ConduitT i Event m () -- ^ 'Element''s subnodes.+ -> ConduitT i Event m ()+tag name (Attributes a) content' = do yield $ EventBeginElement name a- content+ content' yield $ EventEndElement name -- | Generate a textual 'EventContent'.-content :: (Monad m) => Text -> Source m Event+content :: (Monad m) => Text -> ConduitT i Event m () content = yield . EventContent . ContentText -- | A list of attributes.
Text/XML/Stream/Token.hs view
@@ -11,21 +11,20 @@ import Data.XML.Types (Instruction (..), Content (..), ExternalID (..)) import qualified Data.Text as T import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8Builder, encodeUtf8BuilderEscaped) import Data.String (IsString (fromString))-import Blaze.ByteString.Builder- (Builder, fromByteString, writeByteString, copyByteString)-import Blaze.ByteString.Builder.Internal.Write (fromWriteList)-import Blaze.ByteString.Builder.Char.Utf8 (writeChar, fromText)-import Data.Monoid (mconcat, mempty, mappend)-import Data.ByteString.Char8 ()+import Data.ByteString.Builder (Builder)+import qualified Data.ByteString.Builder.Prim as E+import Data.ByteString.Builder.Prim ((>*<), (>$<), condB)+import Data.Monoid (mconcat, mempty, (<>)) import Data.Map (Map)-import qualified Blaze.ByteString.Builder.Char8 as BC8 import qualified Data.Set as Set import Data.List (foldl') import Control.Arrow (first)+import Data.Word (Word8) oneSpace :: Builder-oneSpace = copyByteString " "+oneSpace = " " data Token = TokenXMLDeclaration [TAttribute] | TokenInstruction Instruction@@ -38,113 +37,113 @@ deriving Show tokenToBuilder :: Token -> Builder tokenToBuilder (TokenXMLDeclaration attrs) =- fromByteString "<?xml"- `mappend` foldAttrs oneSpace attrs (fromByteString "?>")-tokenToBuilder (TokenInstruction (Instruction target data_)) = mconcat- [ fromByteString "<?"- , fromText target- , fromByteString " "- , fromText data_- , fromByteString "?>"- ]+ "<?xml" <>+ foldAttrs oneSpace attrs <>+ "?>"+tokenToBuilder (TokenInstruction (Instruction target data_)) =+ "<?" <>+ encodeUtf8Builder target <>+ " " <>+ encodeUtf8Builder data_ <>+ "?>" tokenToBuilder (TokenBeginElement name attrs' isEmpty indent) =- copyByteString "<"- `mappend` tnameToText name- `mappend` foldAttrs+ "<" <>+ tnameToText name <>+ foldAttrs (if indent == 0 || lessThan3 attrs then oneSpace- else BC8.fromString ('\n' : replicate indent ' '))- attrs- (if isEmpty then fromByteString "/>" else fromByteString ">")+ else mconcat $ ("\n" : replicate indent " "))+ attrs <>+ (if isEmpty then "/>" else ">") where attrs = nubAttrs $ map (first splitTName) attrs' lessThan3 [] = True lessThan3 [_] = True lessThan3 [_, _] = True lessThan3 _ = False-tokenToBuilder (TokenEndElement name) = mconcat- [ fromByteString "</"- , tnameToText name- , fromByteString ">"- ]+tokenToBuilder (TokenEndElement name) = "</" <> tnameToText name <> ">" tokenToBuilder (TokenContent c) = contentToText c-tokenToBuilder (TokenCDATA t) = - copyByteString "<![CDATA["- `mappend` escCDATA t- `mappend` copyByteString "]]>"-tokenToBuilder (TokenComment t) = mconcat [fromByteString "<!--", fromText t, fromByteString "-->"]-tokenToBuilder (TokenDoctype name eid _) = mconcat- [ fromByteString "<!DOCTYPE "- , fromText name- , go eid- , fromByteString ">"- ]+tokenToBuilder (TokenCDATA t) = "<![CDATA[" <> escCDATA t <> "]]>"+tokenToBuilder (TokenComment t) = "<!--" <> encodeUtf8Builder t <> "-->"+tokenToBuilder (TokenDoctype name eid _) =+ "<!DOCTYPE " <>+ encodeUtf8Builder name <>+ go eid <>+ ">" where go Nothing = mempty- go (Just (SystemID uri)) = mconcat- [ fromByteString " SYSTEM \""- , fromText uri- , fromByteString "\""- ]- go (Just (PublicID pid uri)) = mconcat- [ fromByteString " PUBLIC \""- , fromText pid- , fromByteString "\" \""- , fromText uri- , fromByteString "\""- ]+ go (Just (SystemID uri)) = " SYSTEM \"" <> encodeUtf8Builder uri <> "\""+ go (Just (PublicID pid uri)) =+ " PUBLIC \"" <>+ encodeUtf8Builder pid <>+ "\" \"" <>+ encodeUtf8Builder uri <>+ "\"" data TName = TName (Maybe Text) Text deriving (Show, Eq, Ord) tnameToText :: TName -> Builder-tnameToText (TName Nothing name) = fromText name-tnameToText (TName (Just prefix) name) = mconcat [fromText prefix, fromByteString ":", fromText name]+tnameToText (TName Nothing name) = encodeUtf8Builder name+tnameToText (TName (Just prefix) name) =+ encodeUtf8Builder prefix <> ":" <> encodeUtf8Builder name contentToText :: Content -> Builder-contentToText (ContentText t) =- fromWriteList go $ T.unpack t+contentToText (ContentText t) = encodeUtf8BuilderEscaped charUtf8XmlEscaped t+contentToText (ContentEntity e) = "&" <> encodeUtf8Builder e <> ";"++{-# INLINE charUtf8XmlEscaped #-}+charUtf8XmlEscaped :: E.BoundedPrim Word8+charUtf8XmlEscaped =+ condB (> _gt) (E.liftFixedToBounded E.word8) $+ condB (== _lt) (fixed4 (_am,(_l,(_t,_sc)))) $ -- <+ condB (== _gt) (fixed4 (_am,(_g,(_t,_sc)))) $ -- >+ condB (== _am) (fixed5 (_am,(_a,(_m,(_p,_sc))))) $ -- &+ condB (== _dq) (fixed5 (_am,(_ha,(_3,(_4,_sc))))) $ -- "+ condB (== _sq) (fixed5 (_am,(_ha,(_3,(_9,_sc))))) $ -- '+ (E.liftFixedToBounded E.word8) -- fallback for Chars smaller than '>' where- go '<' = writeByteString "<"- go '>' = writeByteString ">"- go '&' = writeByteString "&"- -- Not escaping quotes, since this is only called outside of attributes- go c = writeChar c-contentToText (ContentEntity e) = mconcat- [ fromByteString "&"- , fromText e- , fromByteString ";"- ]+ _gt = 62 -- >+ _lt = 60 -- <+ _am = 38 -- &+ _dq = 34 -- "+ _sq = 39 -- '+ _l = 108 -- l+ _t = 116 -- t+ _g = 103 -- g+ _a = 97 -- a+ _m = 109 -- m+ _p = 112 -- p+ _3 = 51 -- 3+ _4 = 52 -- 4+ _ha = 35 -- #, hash+ _9 = 57 -- 9+ _sc = 59 -- ;+ {-# INLINE fixed4 #-}+ fixed4 x = E.liftFixedToBounded $ const x >$<+ E.word8 >*< E.word8 >*< E.word8 >*< E.word8 + {-# INLINE fixed5 #-}+ fixed5 x = E.liftFixedToBounded $ const x >$<+ E.word8 >*< E.word8 >*< E.word8 >*< E.word8 >*< E.word8+ type TAttribute = (TName, [Content]) foldAttrs :: Builder -- ^ before -> [TAttribute] -> Builder- -> Builder-foldAttrs before attrs rest' =- foldr go rest' attrs+foldAttrs before =+ foldMap go where- go (key, val) rest =- before- `mappend` tnameToText key- `mappend` copyByteString "=\""- `mappend` foldr go' (fromByteString "\"" `mappend` rest) val- go' (ContentText t) rest =- fromWriteList h (T.unpack t) `mappend` rest- where- h '<' = writeByteString "<"- h '>' = writeByteString ">"- h '&' = writeByteString "&"- h '"' = writeByteString """- -- Not escaping single quotes, since our attributes are always double- -- quoted- h c = writeChar c- go' (ContentEntity t) rest =- fromByteString "&"- `mappend` fromText t- `mappend` fromByteString ";"- `mappend` rest+ go (key, val) =+ before <>+ tnameToText key <>+ "=\"" <>+ foldMap go' val <>+ "\""+ go' (ContentText t) =+ encodeUtf8BuilderEscaped charUtf8XmlEscaped t+ go' (ContentEntity t) = "&" <> encodeUtf8Builder t <> ";" instance IsString TName where fromString = TName Nothing . T.pack@@ -171,6 +170,6 @@ | otherwise = TName (Just a) $ T.drop 1 b where (a, b) = T.break (== ':') t- + escCDATA :: Text -> Builder-escCDATA s = fromText (T.replace "]]>" "]]]]><![CDATA[>" s)+escCDATA s = encodeUtf8Builder (T.replace "]]>" "]]]]><![CDATA[>" s)
Text/XML/Unresolved.hs view
@@ -43,18 +43,15 @@ , R.rsNamespaces ) where -import Blaze.ByteString.Builder (Builder)+import Conduit import Control.Applicative ((<$>), (<*>)) import Control.Exception (Exception, SomeException, throw) import Control.Monad (when)-import Control.Monad.ST (runST) import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Resource (MonadThrow, monadThrow,- runExceptionT, runResourceT) import Data.ByteString (ByteString)+import Data.ByteString.Builder (Builder) import qualified Data.ByteString.Lazy as L import Data.Char (isSpace)-import Data.Conduit import qualified Data.Conduit.Binary as CB import Data.Conduit.Lazy (lazyConsume) import qualified Data.Conduit.List as CL@@ -72,16 +69,16 @@ import qualified Text.XML.Stream.Render as R readFile :: P.ParseSettings -> FilePath -> IO Document-readFile ps fp = runResourceT $ CB.sourceFile fp $$ sinkDoc ps+readFile ps fp = runConduitRes $ CB.sourceFile fp .| sinkDoc ps sinkDoc :: MonadThrow m => P.ParseSettings- -> Consumer ByteString m Document-sinkDoc ps = P.parseBytesPos ps =$= fromEvents+ -> ConduitT ByteString o m Document+sinkDoc ps = P.parseBytesPos ps .| fromEvents writeFile :: R.RenderSettings -> FilePath -> Document -> IO () writeFile rs fp doc =- runResourceT $ renderBytes rs doc $$ CB.sinkFile fp+ runConduitRes $ renderBytes rs doc .| CB.sinkFile fp renderLBS :: R.RenderSettings -> Document -> L.ByteString renderLBS rs doc =@@ -93,9 +90,7 @@ $ renderBytes rs doc parseLBS :: P.ParseSettings -> L.ByteString -> Either SomeException Document-parseLBS ps lbs =- runST $ runExceptionT- $ CL.sourceList (L.toChunks lbs) $$ sinkDoc ps+parseLBS ps lbs = runConduit $ CL.sourceList (L.toChunks lbs) .| sinkDoc ps parseLBS_ :: P.ParseSettings -> L.ByteString -> Document parseLBS_ ps lbs = either throw id $ parseLBS ps lbs@@ -125,14 +120,14 @@ prettyShowName :: Name -> String prettyShowName = show -- FIXME -renderBuilder :: Monad m => R.RenderSettings -> Document -> Producer m Builder-renderBuilder rs doc = CL.sourceList (toEvents doc) =$= R.renderBuilder rs+renderBuilder :: Monad m => R.RenderSettings -> Document -> ConduitT i Builder m ()+renderBuilder rs doc = CL.sourceList (toEvents doc) .| R.renderBuilder rs ---renderBytes :: MonadUnsafeIO m => R.RenderSettings -> Document -> Producer m ByteString-renderBytes rs doc = CL.sourceList (toEvents doc) =$= R.renderBytes rs+renderBytes :: PrimMonad m => R.RenderSettings -> Document -> ConduitT i ByteString m ()+renderBytes rs doc = CL.sourceList (toEvents doc) .| R.renderBytes rs ---renderText :: (MonadThrow m, MonadUnsafeIO m) => R.RenderSettings -> Document -> Producer m Text-renderText rs doc = CL.sourceList (toEvents doc) =$= R.renderText rs+renderText :: (MonadThrow m, PrimMonad m) => R.RenderSettings -> Document -> ConduitT i Text m ()+renderText rs doc = CL.sourceList (toEvents doc) .| R.renderText rs manyTries :: Monad m => m (Maybe a) -> m [a] manyTries f =@@ -148,7 +143,7 @@ dropReturn x = CL.drop 1 >> return x -- | Parse a document from a stream of events.-fromEvents :: MonadThrow m => Consumer P.EventPos m Document+fromEvents :: MonadThrow m => ConduitT P.EventPos o m Document fromEvents = do skip EventBeginDocument d <- Document <$> goP <*> require elementFromEvents <*> goM@@ -156,9 +151,9 @@ y <- CL.head case y of Nothing -> return d- Just (_, EventEndDocument) -> lift $ monadThrow MissingRootElement+ Just (_, EventEndDocument) -> lift $ throwM MissingRootElement Just z ->- lift $ monadThrow $ ContentAfterRoot z+ lift $ throwM $ ContentAfterRoot z where skip e = do x <- CL.peek@@ -171,8 +166,8 @@ my <- CL.head case my of Nothing -> error "Text.XML.Unresolved:impossible"- Just (_, EventEndDocument) -> lift $ monadThrow MissingRootElement- Just y -> lift $ monadThrow $ ContentAfterRoot y+ Just (_, EventEndDocument) -> lift $ throwM MissingRootElement+ Just y -> lift $ throwM $ ContentAfterRoot y goP = Prologue <$> goM <*> goD <*> goM goM = manyTries goM' goM' = do@@ -200,13 +195,13 @@ -- -- Just (EventDeclaration _) -> dropTillDoctype Just (_, EventEndDoctype) -> return ()- Just epos -> lift $ monadThrow $ InvalidInlineDoctype epos- Nothing -> lift $ monadThrow UnterminatedInlineDoctype+ Just epos -> lift $ throwM $ InvalidInlineDoctype epos+ Nothing -> lift $ throwM UnterminatedInlineDoctype -- | Try to parse a document element (as defined in XML) from a stream of events. -- -- @since 1.3.5-elementFromEvents :: MonadThrow m => Consumer P.EventPos m (Maybe Element)+elementFromEvents :: MonadThrow m => ConduitT P.EventPos o m (Maybe Element) elementFromEvents = goE where goE = do@@ -220,7 +215,7 @@ y <- CL.head if fmap snd y == Just (EventEndElement n) then return $ Element n as $ compressNodes ns- else lift $ monadThrow $ MissingEndElement n y+ else lift $ throwM $ MissingEndElement n y goN = do x <- CL.peek case x of@@ -283,15 +278,15 @@ compressNodes (x:xs) = x : compressNodes xs parseText :: ParseSettings -> TL.Text -> Either SomeException Document-parseText ps tl = runST- $ runExceptionT- $ CL.sourceList (TL.toChunks tl)- $$ sinkTextDoc ps+parseText ps tl =+ runConduit+ $ CL.sourceList (TL.toChunks tl)+ .| sinkTextDoc ps parseText_ :: ParseSettings -> TL.Text -> Document parseText_ ps = either throw id . parseText ps sinkTextDoc :: MonadThrow m => ParseSettings- -> Consumer Text m Document-sinkTextDoc ps = P.parseTextPos ps =$= fromEvents+ -> ConduitT Text o m Document+sinkTextDoc ps = P.parseTextPos ps .| fromEvents
test/main.hs view
@@ -15,18 +15,15 @@ import qualified Text.XML.Stream.Parse as P import qualified Text.XML.Unresolved as D -import Control.Applicative ((<$>)) import Control.Monad-import Control.Monad.Trans.Class (lift) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T import Text.XML.Cursor (($.//), ($/), ($//), ($|), (&.//), (&/), (&//)) -import Control.Monad.Trans.Resource (runResourceT) import qualified Control.Monad.Trans.Resource as C-import Data.Conduit ((=$=))+import Data.Conduit ((.|), runConduit, runConduitRes, ConduitT) import qualified Data.Conduit as C import qualified Data.Conduit.List as CL import qualified Data.Map as Map@@ -139,7 +136,7 @@ ] combinators :: Assertion-combinators = runResourceT $ P.parseLBS def input C.$$ do+combinators = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tag' "hello" (P.requireAttr "world") $ \world -> do liftIO $ world @?= "true" P.force "need child1" $ P.tagNoAttr "{mynamespace}child1" $ return ()@@ -186,7 +183,7 @@ testChooseElemOrTextIsChunkedText2 testChooseElemOrTextIsText :: Assertion-testChooseElemOrTextIsText = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsText = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -203,7 +200,7 @@ ] testChooseElemOrTextIsEncoded :: Assertion-testChooseElemOrTextIsEncoded = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsEncoded = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -220,7 +217,7 @@ ] testChooseElemOrTextIsEncodedNBSP :: Assertion-testChooseElemOrTextIsEncodedNBSP = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsEncodedNBSP = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -238,7 +235,7 @@ testChooseElemOrTextIsWhiteSpace :: Assertion-testChooseElemOrTextIsWhiteSpace = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsWhiteSpace = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -253,7 +250,7 @@ ] testChooseTextOrElemIsWhiteSpace :: Assertion-testChooseTextOrElemIsWhiteSpace = runResourceT $ P.parseLBS def input C.$$ do+testChooseTextOrElemIsWhiteSpace = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.contentMaybe@@ -268,7 +265,7 @@ ] testChooseElemOrTextIsChunkedText :: Assertion-testChooseElemOrTextIsChunkedText = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsChunkedText = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -283,7 +280,7 @@ ] testChooseElemOrTextIsChunkedText2 :: Assertion-testChooseElemOrTextIsChunkedText2 = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsChunkedText2 = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return "boom"@@ -298,7 +295,7 @@ ] testChooseElemOrTextIsElem :: Assertion-testChooseElemOrTextIsElem = runResourceT $ P.parseLBS def input C.$$ do+testChooseElemOrTextIsElem = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "success" $ return "success"@@ -315,7 +312,7 @@ ] testChooseTextOrElemIsText :: Assertion-testChooseTextOrElemIsText = runResourceT $ P.parseLBS def input C.$$ do+testChooseTextOrElemIsText = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.contentMaybe@@ -332,7 +329,7 @@ ] testChooseTextOrElemIsElem :: Assertion-testChooseTextOrElemIsElem = runResourceT $ P.parseLBS def input C.$$ do+testChooseTextOrElemIsElem = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.contentMaybe@@ -349,7 +346,7 @@ ] testChooseEitherElem :: Assertion-testChooseEitherElem = runResourceT $ P.parseLBS def input C.$$ do+testChooseEitherElem = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.choose [ P.tagNoAttr "failure" $ return 1@@ -368,9 +365,9 @@ testManyYield :: Assertion testManyYield = do -- Basically the same as testMany, but consume the streamed result- result <- runResourceT $- P.parseLBS def input C.$$ helloParser- =$= CL.consume+ result <- runConduitRes $+ P.parseLBS def input .| helloParser+ .| CL.consume length result @?= 5 where helloParser = void $ P.tagNoAttr "hello" $ P.manyYield successParser@@ -389,12 +386,12 @@ testTakeContent :: Assertion testTakeContent = do- result <- runResourceT $ P.parseLBS def input C.$$ rootParser+ result <- runConduitRes $ P.parseLBS def input .| rootParser result @?= Just [ EventContent (ContentText "Hello world !") ] where- rootParser = P.tagNoAttr "root" $ void (P.takeContent >> P.takeContent) =$= CL.consume+ rootParser = P.tagNoAttr "root" $ void (P.takeContent >> P.takeContent) .| CL.consume input = L.concat [ "<?xml version='1.0'?>" , "<!DOCTYPE foo []>\n"@@ -405,7 +402,7 @@ testTakeTree :: Assertion testTakeTree = do- result <- runResourceT $ P.parseLBS def input C.$$ rootParser+ result <- runConduitRes $ P.parseLBS def input .| rootParser result @?= [ EventBeginDocument , EventBeginDoctype "foo" Nothing@@ -417,7 +414,7 @@ , EventEndElement "a" ] where- rootParser = void (P.takeTree "a" P.ignoreAttrs) =$= CL.consume+ rootParser = void (P.takeTree "a" P.ignoreAttrs) .| CL.consume input = L.concat [ "<?xml version='1.0'?>" , "<!DOCTYPE foo []>\n"@@ -430,7 +427,7 @@ testTakeAnyTreeContent :: Assertion testTakeAnyTreeContent = do- result <- runResourceT $ P.parseLBS def input C.$$ rootParser+ result <- runConduitRes $ P.parseLBS def input .| rootParser result @?= Just [ EventBeginElement "b" [] , EventContent (ContentText "Hello ")@@ -441,7 +438,7 @@ , EventEndElement "b" ] where- rootParser = P.tagNoAttr "root" $ (P.takeAnyTreeContent >> void P.ignoreAnyTreeContent) =$= CL.consume+ rootParser = P.tagNoAttr "root" $ (P.takeAnyTreeContent >> void P.ignoreAnyTreeContent) .| CL.consume input = L.concat [ "<?xml version='1.0'?>" , "<!DOCTYPE foo []>\n"@@ -452,7 +449,7 @@ testMany :: Assertion-testMany = runResourceT $ P.parseLBS def input C.$$ do+testMany = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.many $ P.tagNoAttr "success" $ return () liftIO $ length x @?= 5@@ -470,7 +467,7 @@ ] testMany' :: Assertion-testMany' = runResourceT $ P.parseLBS def input C.$$ do+testMany' = runConduitRes $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.many' $ P.tagNoAttr "success" $ return () liftIO $ length x @?= 5@@ -490,7 +487,7 @@ ] testOrE :: IO ()-testOrE = runResourceT $ P.parseLBS def input C.$$ do+testOrE = runConduitRes $ runConduit $ P.parseLBS def input .| do P.force "need hello" $ P.tagNoAttr "hello" $ do x <- P.tagNoAttr "failure" (return 1) `P.orE` P.tagNoAttr "success" (return 2)@@ -509,10 +506,11 @@ ] testConduitParser :: Assertion-testConduitParser = runResourceT $ do- x <- P.parseLBS def input- C.$$ (P.force "need hello" $ P.tagNoAttr "hello" f)- =$= CL.consume+testConduitParser = do+ x <- runConduitRes+ $ P.parseLBS def input+ .| (P.force "need hello" $ P.tagNoAttr "hello" f)+ .| CL.consume liftIO $ x @?= [1, 1, 1] where input = L.concat@@ -524,7 +522,7 @@ , "<item/>" , "</hello>" ]- f :: C.MonadThrow m => C.Conduit Event m Int+ f :: C.MonadThrow m => ConduitT Event Int m () f = do ma <- P.tagNoAttr "item" (return 1) maybe (return ()) (\a -> C.yield a >> f) ma@@ -858,8 +856,8 @@ , "<bar a=\"a\" b=\"b\" c=\"c\"/>" , "</foo>" ]- rs = def { Res.rsAttrOrder = \name m ->- case name of+ rs = def { Res.rsAttrOrder = \name' m ->+ case name' of "foo" -> reverse $ Map.toAscList m _ -> Map.toAscList m }
xml-conduit.cabal view
@@ -1,5 +1,5 @@ name: xml-conduit-version: 1.7.1.2+version: 1.8.0 license: MIT license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>, Aristid Breitkreuz <aristidb@googlemail.com>@@ -17,15 +17,14 @@ library build-depends: base >= 4 && < 5- , conduit >= 1.0 && < 1.3- , conduit-extra >= 1.1- , resourcet >= 0.3 && < 1.2- , bytestring >= 0.9+ , conduit >= 1.3 && < 1.4+ , conduit-extra >= 1.3 && < 1.4+ , resourcet >= 1.2 && < 1.3+ , bytestring >= 0.10.2 , text >= 0.7 , containers >= 0.2 , xml-types >= 0.3.4 && < 0.4 , attoparsec >= 0.10- , blaze-builder >= 0.2 && < 0.5 , transformers >= 0.2 && < 0.6 , data-default-class , monad-control >= 0.3 && < 1.1