libxml-enumerator (empty) → 0.1
raw patch · 4 files changed
+156/−0 lines, 4 filesdep +basedep +bytestringdep +enumeratorsetup-changed
Dependencies added: base, bytestring, enumerator, libxml-sax, text, transformers, xml-types
Files
- Setup.hs +2/−0
- Text/XML/LibXML/Enumerator.hs +103/−0
- libxml-enumerator.cabal +29/−0
- license.txt +22/−0
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Text/XML/LibXML/Enumerator.hs view
@@ -0,0 +1,103 @@+-----------------------------------------------------------------------------+-- |+-- Module: Text.XML.LibXML.Enumerator+-- Copyright: 2010 John Millikin+-- License: MIT+--+-- Maintainer: jmillikin@gmail.com+-- Portability: portable+--+-----------------------------------------------------------------------------+module Text.XML.LibXML.Enumerator+ ( Event (..)+ , parseBytes+ , parseText+ ) where+import qualified Data.ByteString as B+import qualified Data.Enumerator as E+import Data.Enumerator ((>>==))+import qualified Data.Text as T+import qualified Data.XML.Types as X+import qualified Text.XML.LibXML.SAX as SAX++import Control.Monad.Trans.Class (lift)+import Control.Monad.ST (ST, unsafeSTToIO)+import qualified Data.STRef as ST+import System.IO.Unsafe (unsafePerformIO)++data Event+ = EventBeginDocument+ | EventEndDocument+ | EventBeginElement X.Name [X.Attribute]+ | EventEndElement X.Name+ | EventCharacters T.Text+ | EventComment T.Text+ | EventInstruction X.Instruction+ deriving (Show, Eq)++newParser :: Maybe T.Text -> ST s (SAX.Parser (ST s), ST.STRef s [Event], ST.STRef s (Maybe T.Text))+newParser name = do+ errRef <- ST.newSTRef Nothing+ p <- SAX.newParserST (\msg -> ST.writeSTRef errRef (Just msg)) name+ eventRef <- ST.newSTRef []+ + let addEvent e = ST.modifySTRef eventRef (e:) >> return True+ let setCallback cb st = SAX.setCallback p cb st+ + setCallback SAX.parsedBeginDocument (addEvent EventBeginDocument)+ setCallback SAX.parsedEndDocument (addEvent EventEndDocument)+ setCallback SAX.parsedBeginElement ((addEvent .) . EventBeginElement)+ setCallback SAX.parsedEndElement (addEvent . EventEndElement)+ setCallback SAX.parsedCharacters (addEvent . EventCharacters)+ setCallback SAX.parsedComment (addEvent . EventComment)+ setCallback SAX.parsedInstruction (addEvent . EventInstruction)+ + return (p, eventRef, errRef)++unsafePerformST_M :: Monad m => ST s a -> m a+unsafePerformST_M st = unsafePerformIO (unsafeSTToIO (fmap return st))++parseBytes :: Monad m => Maybe T.Text -> E.Enumeratee T.Text B.ByteString Event m b+parseBytes = parseSomething SAX.parseBytes++parseText :: Monad m => Maybe T.Text -> E.Enumeratee T.Text T.Text Event m b+parseText = parseSomething SAX.parseText++parseSomething :: Monad m+ => (SAX.Parser (ST s) -> a -> ST s ())+ -> Maybe T.Text+ -> E.Enumeratee T.Text a Event m b+parseSomething something name s = E.Iteratee $ do+ (p, eventRef, errRef) <- unsafePerformST_M $ newParser name+ + let withEvents st = unsafePerformST_M $ do+ ST.writeSTRef eventRef []+ ST.writeSTRef errRef Nothing+ st+ events <- ST.readSTRef eventRef+ err <- ST.readSTRef errRef+ return (reverse events, err)+ + let parseChunk bytes = withEvents (something p bytes)+ let complete = withEvents (SAX.parseComplete p)+ E.runIteratee $ eneeParser parseChunk complete s++eneeParser :: Monad m+ => (a -> m ([Event], Maybe T.Text))+ -> m ([Event], Maybe T.Text)+ -> E.Enumeratee T.Text a Event m b+eneeParser parseChunk parseComplete = E.checkDone (E.continue . step) where+ step k E.EOF = checkEvents k parseComplete (\k' -> E.yield (E.Continue k') E.EOF)+ step k (E.Chunks xs) = parseLoop k xs+ + parseLoop k [] = E.continue (step k)+ parseLoop k (x:xs) = checkEvents k (parseChunk x) (\k' -> parseLoop k' xs)+ + checkEvents k getEvents next = do+ (events, maybeErr) <- lift getEvents+ let checkError k' = case maybeErr of+ Nothing -> next k'+ Just err -> E.throwError err+ if null events+ then checkError k+ else k (E.Chunks events) >>== E.checkDone checkError
+ libxml-enumerator.cabal view
@@ -0,0 +1,29 @@+name: libxml-enumerator+version: 0.1+synopsis: Enumerator-based API for libXML's SAX interface+license: MIT+license-file: license.txt+author: John Millikin <jmillikin@gmail.com>+maintainer: jmillikin@gmail.com+copyright: Copyright (c) John Millikin 2010+build-type: Simple+cabal-version: >=1.6+category: Enumerator, Text, XML, Parsing+stability: experimental+bug-reports: mailto:jmillikin@gmail.com+tested-with: GHC==6.12.1++library+ ghc-options: -Wall -fno-warn-unused-do-bind++ build-depends:+ base >= 4 && < 5+ , bytestring >= 0.9 && < 0.10+ , text >= 0.7 && < 0.8+ , enumerator >= 0.1 && < 0.4+ , transformers >= 0.2 && < 0.3+ , libxml-sax >= 0.6 && < 0.7+ , xml-types >= 0.1 && < 0.2++ exposed-modules:+ Text.XML.LibXML.Enumerator
+ license.txt view
@@ -0,0 +1,22 @@+Copyright (c) 2010 John Millikin++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.