packages feed

libxml-sax 0.2 → 0.3

raw patch · 3 files changed

+167/−21 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.XML.LibXML.SAX: attributeName :: Attribute -> QName
+ Text.XML.LibXML.SAX: attributeValue :: Attribute -> String
+ Text.XML.LibXML.SAX: qnameLocalName :: QName -> String
+ Text.XML.LibXML.SAX: qnameNamespace :: QName -> String
+ Text.XML.LibXML.SAX: qnamePrefix :: QName -> String

Files

+ Tests.hs view
@@ -0,0 +1,124 @@+{- Copyright (C) 2009 John Millikin <jmillikin@gmail.com>+   +   This program is free software: you can redistribute it and/or modify+   it under the terms of the GNU General Public License as published by+   the Free Software Foundation, either version 3 of the License, or+   any later version.+   +   This program is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+   GNU General Public License for more details.+   +   You should have received a copy of the GNU General Public License+   along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}++module Main () where++import Test.HUnit+import Text.XML.LibXML.SAX++allTests = "allTests" ~: TestList [beginTests, endTests, textTests, otherTests, incrementalTests]+beginTests = "beginTests" ~: TestList [testBegin, testBeginNS, testBeginPrefix]+endTests = "endTests" ~: TestList [testEnd, testEndNS, testEndPrefix]+textTests = "textTests" ~: TestList [testText, testPredefinedEntity, testNumericEntity]+otherTests = "otherTests" ~: TestList [testProcessingInstruction, testComment, testCDATA, testError]+incrementalTests = "incrementalTests" ~: TestList [incrBegin, incrEnd, incrText]++testBegin = TestCase $ do+	parser <- mkParser+	[event] <- parse parser "<test>" False+	BeginElement (QName "" "" "test") [] @=? event++testBeginNS = TestCase $ do+	parser <- mkParser+	[event] <- parse parser "<test xmlns='urn:test'>" False+	BeginElement (QName "urn:test" "" "test") [] @=? event++testBeginPrefix = TestCase $ do+	parser <- mkParser+	[event] <- parse parser "<t:test xmlns:t='urn:test'>" False+	BeginElement (QName "urn:test" "t" "test") [] @=? event++testEnd = TestCase $ do+	parser <- mkParser+	[_, event] <- parse parser "<test/>" True+	EndElement (QName "" "" "test") @=? event++testEndNS = TestCase $ do+	parser <- mkParser+	[_, event] <- parse parser "<test xmlns='urn:test'/>" True+	EndElement (QName "urn:test" "" "test") @=? event++testEndPrefix = TestCase $ do+	parser <- mkParser+	[_, event] <- parse parser "<t:test xmlns:t='urn:test'/>" True+	EndElement (QName "urn:test" "t" "test") @=? event++testText = TestCase $ do+	parser <- mkParser+	[_, event, _] <- parse parser "<test>text here</test>" True+	Characters "text here" @=? event++testPredefinedEntity = TestCase $ do+	parser <- mkParser+	events <- parse parser "<test>text &amp; here</test>" True+	let events' = init . tail $ events+	[Characters "text ", Characters "&", Characters " here"] @=? events'++testNumericEntity = TestCase $ do+	parser <- mkParser+	events <- parse parser "<test>text &#x003C; here</test>" True+	let events' = init . tail $ events+	[Characters "text ", Characters "<", Characters " here"] @=? events'++testProcessingInstruction = TestCase $ do+	parser <- mkParser+	events <- parse parser "<?instr version='1.0'?><test/>" True+	ProcessingInstruction "instr" "version='1.0'" @=? head events++testComment = TestCase $ do+	parser <- mkParser+	events <- parse parser "<!-- comment here --><test/>" True+	Comment " comment here " @=? head events++testCDATA = TestCase $ do+	parser <- mkParser+	events <- parse parser "<test><![CDATA[<test2/>]]></test>" True+	let events' = init . tail $ events+	[Characters "<test2/>"] @=? events'++testError = TestCase $ do+	parser <- mkParser+	events <- parse parser "</a>" True+	[ParseError "StartTag: invalid element name\n"] @=? events++incrBegin = TestCase $ do+	parser <- mkParser+	let parse' = parse parser+	+	[] <- parse' "<test" False+	[event] <- parse' ">" False+	BeginElement (QName "" "" "test") [] @=? event++incrEnd = TestCase $ do+	parser <- mkParser+	let parse' = parse parser+	+	[_] <- parse' "<test></test" False+	[event] <- parse' ">" True+	EndElement (QName "" "" "test") @=? event++incrText = TestCase $ do+	parser <- mkParser+	let parse' = parse parser+	+	[_] <- parse' "<test>text" False+	[] <- parse' " more text" False+	[event, _] <- parse' "</test>" True+	Characters "text more text" @=? event++main = do+	runTestTT allTests+
Text/XML/LibXML/SAX.chs view
@@ -18,13 +18,13 @@  #include <libxml/parser.h> -module Text.XML.LibXML.SAX (-	 Parser-	,Event(..)-	,Attribute(..)-	,QName(..)-	,mkParser-	,parse+module Text.XML.LibXML.SAX+	( Parser+	, Event(..)+	, Attribute(..)+	, QName(..)+	, mkParser+	, parse 	) where  import Data.IORef (newIORef, readIORef, writeIORef, IORef)@@ -37,18 +37,26 @@ 	| EndElement QName 	| Characters String 	| Comment String-	| ProcessingInstruction String String -- Target, Data+	| ProcessingInstruction String String -- ^ Target, Data 	| ParseError String 	deriving (Show, Eq) -data Attribute = Attribute QName String+data Attribute = Attribute+	{ attributeName  :: QName+	, attributeValue :: String+	} 	deriving (Show, Eq) --- Namespace, prefix, local name-data QName = QName String String String+data QName = QName+	{ qnameNamespace :: String+	, qnamePrefix    :: String+	, qnameLocalName :: String+	} 	deriving (Show, Eq) -data Parser = Parser (ForeignPtr Context)+-- | An opaque reference to a libXML SAX parser.+-- +newtype Parser = Parser (ForeignPtr Context)  data Context = Context data SAXHandler = SAXHandler@@ -63,6 +71,8 @@ {#pointer *xmlSAXHandler as SAXHandlerPtr -> SAXHandler #} {#pointer *_xmlSAXHandler as SAXHandlerPtr nocode #} +-- | Construct a new, empty parser.+--  mkParser :: IO Parser mkParser = let n = nullPtr in do 	context <- {#call xmlCreatePushParserCtxt #} n n n 0 n@@ -72,6 +82,13 @@ foreign import ccall "libxml/parser.h &xmlFreeParserCtxt" 	xmlFreeParserCtxt :: FunPtr (Ptr Context -> IO ()) +-- | Feed some text into the parser. This may be performed multiple times+-- per 'Parser' value, in which case the internal parser state is retained+-- between computations.+-- +-- If the third parameter is 'True', the parser assumes that this is the+-- last input and checks that the document was closed correctly.+--  parse :: Parser -> String -> Bool -> IO [Event] parse (Parser fptr) s final = do 	withCStringLen s $ \(cs, cs_len) -> do@@ -83,7 +100,7 @@ 	rc <- {#call xmlParseChunk #} ctxt cs (fromIntegral cs_len) cFinal 	errors <- checkErrors rc ctxt 	events <- readIORef eventRef-	return $ events ++ errors+	return $ reverse events ++ errors 	 withHandlers :: Ptr Context -> (IORef [Event] -> IO a) -> IO a withHandlers ctxt block = do@@ -177,7 +194,7 @@ 	es <- readIORef eventref 	c_attrs <- splitCAttributes n_attrs (castPtr raw_attrs) 	attrs <- mapM convertCAttribute c_attrs-	writeIORef eventref (es ++ [BeginElement (QName ns pfx ln) attrs])+	writeIORef eventref ((BeginElement (QName ns pfx ln) attrs):es)  onEndElement :: IORef [Event] -> EndElementNsSAX2Func onEndElement eventref _ cln cpfx cns = do@@ -185,26 +202,26 @@ 	pfx <- peekNullable $ castPtr cpfx 	ln <- peekCString $ castPtr cln 	es <- readIORef eventref-	writeIORef eventref (es ++ [EndElement (QName ns pfx ln)])+	writeIORef eventref ((EndElement (QName ns pfx ln)):es)  onCharacters :: IORef [Event] -> CharactersSAXFunc onCharacters eventref _ ctext ctextlen = do 	text <- peekCStringLen (castPtr ctext, fromIntegral ctextlen) 	es <- readIORef eventref-	writeIORef eventref (es ++ [Characters text])+	writeIORef eventref ((Characters text):es)  onComment :: IORef [Event] -> CommentSAXFunc onComment eventRef _ ctext = do 	text <- peekCString (castPtr ctext) 	es <- readIORef eventRef-	writeIORef eventRef (es ++ [Comment text])+	writeIORef eventRef ((Comment text):es)  onProcessingInstruction :: IORef [Event] -> ProcessingInstructionSAXFunc onProcessingInstruction eventRef _ ctarget cdata = do 	target <- peekCString (castPtr ctarget) 	data' <- peekCString (castPtr cdata) 	es <- readIORef eventRef-	writeIORef eventRef (es ++ [ProcessingInstruction target data'])+	writeIORef eventRef ((ProcessingInstruction target data'):es)  foreign import ccall "wrapper" 	wrappedBegin :: StartElementNsSAX2Func -> IO (FunPtr StartElementNsSAX2Func)
libxml-sax.cabal view
@@ -1,15 +1,20 @@ Name: libxml-sax-Version: 0.2+Version: 0.3 Stability: Alpha Synopsis: Bindings for the libXML2 SAX interface Description: Incrementally convert text to lists of XML events-License: GPL+License: GPL-3 License-file: License.txt Author: John Millikin maintainer: jmillikin@gmail.com+copyright: Copyright (c) John Millikin 2009-2010,+                     (c) Dmitry Astapov 2010 Build-Type: Simple-Cabal-Version: >=1.2+Cabal-Version: >=1.4 Category: XML+homepage: http://ianen.org/haskell/bindings/libxml-sax/+tested-with: GHC==6.10.4+extra-source-files: Tests.hs  Library   Build-Depends: base >=3 && < 5