module Text.XML.HaXml.SAX
( SaxElement(..)
, saxParse
) where
import Text.XML.HaXml.Types
import Text.XML.HaXml.Parse
import Text.XML.HaXml.Lex
import Text.ParserCombinators.Poly.State
data SaxElement
= SaxDocTypeDecl DocTypeDecl
| SaxProcessingInstruction ProcessingInstruction
| SaxComment String
| SaxElementOpen Name [Attribute]
| SaxElementClose Name
| SaxElementTag Name [Attribute]
| SaxCharData CharData
| SaxReference Reference
saxParse :: String
-> String
-> ([SaxElement],Maybe String)
saxParse file cntnt = parseStream sax emptySTs
(xmlLex file cntnt)
parseStream :: Parser s t a -> s -> [t] -> ([a], Maybe String)
parseStream _ _ [] = ([],Nothing)
parseStream p state toks = case runParser p state toks of
(Left err, _, _) -> ([],Just err)
(Right res, nstate, rest) -> (res:moreres, err)
where (moreres,err) = parseStream p nstate rest
sax :: XParser SaxElement
sax = oneOf [ saxelementopen
, saxelementclose
, saxprocessinginstruction
, saxcomment
, saxdoctypedecl
, saxreference
, saxchardata
]
`adjustErr` (++("\nLooking for a SAX event:\n"
++" elem-open, elem-close, PI, comment, DTD, ref, or chardata"))
saxelementopen :: XParser SaxElement
saxelementopen = do
tok TokAnyOpen
(ElemTag (N n) as) <- elemtag
(( do tok TokEndClose
return (SaxElementTag n as)) `onFail`
( do tok TokAnyClose
return (SaxElementOpen n as))
`onFail` fail "missing > or /> in element tag")
saxelementclose :: XParser SaxElement
saxelementclose = do
tok TokEndOpen
n <- name
tok TokAnyClose
return (SaxElementClose n)
saxcomment :: XParser SaxElement
saxcomment = comment >>= return . SaxComment
saxchardata :: XParser SaxElement
saxchardata =
(cdsect >>= return . SaxCharData)
`onFail`
(chardata >>= return . SaxCharData)
saxreference :: XParser SaxElement
saxreference = reference >>= return . SaxReference
saxdoctypedecl :: XParser SaxElement
saxdoctypedecl = doctypedecl >>= return . SaxDocTypeDecl
saxprocessinginstruction :: XParser SaxElement
saxprocessinginstruction = fmap SaxProcessingInstruction processinginstruction