module Text.XML.HaXml.XmlContent
(
module Text.XML.HaXml.XmlContent.Parser
, module Text.XML.HaXml.TypeMapping
, toXml, fromXml
, readXml, showXml, fpsShowXml
, fReadXml, fWriteXml, fpsWriteXml
, hGetXml, hPutXml, fpsHPutXml
) where
import System.IO
import qualified Text.XML.HaXml.ByteStringPP as FPS (document)
import qualified Data.ByteString.Lazy.Char8 as FPS
import Text.PrettyPrint.HughesPJ (render)
import Text.XML.HaXml.Types
import Text.XML.HaXml.TypeMapping
import Text.XML.HaXml.Posn (Posn, posInNewCxt)
import Text.XML.HaXml.Pretty (document)
import Text.XML.HaXml.Parse (xmlParse)
import Text.XML.HaXml.XmlContent.Parser
fReadXml :: XmlContent a => FilePath -> IO a
fReadXml fp = do
f <- ( if fp=="-" then return stdin
else openFile fp ReadMode )
x <- hGetContents f
let (Document _ _ y _) = xmlParse fp x
y' = CElem y (posInNewCxt fp Nothing)
either fail return (fst (runParser parseContents [y']))
fWriteXml :: XmlContent a => FilePath -> a -> IO ()
fWriteXml fp x = do
f <- ( if fp=="-" then return stdout
else openFile fp WriteMode )
hPutXml f False x
hClose f
fpsWriteXml :: XmlContent a => FilePath -> a -> IO ()
fpsWriteXml fp x = do
f <- ( if fp=="-" then return stdout
else openFile fp WriteMode )
fpsHPutXml f False x
hClose f
readXml :: XmlContent a => String -> Either String a
readXml s =
let (Document _ _ y _) = xmlParse "string input" s in
fst (runParser parseContents
[CElem y (posInNewCxt "string input" Nothing)])
showXml :: XmlContent a => Bool -> a -> String
showXml dtd x =
case toContents x of
[CElem _ _] -> (render . document . toXml dtd) x
_ -> ""
fpsShowXml :: XmlContent a => Bool -> a -> FPS.ByteString
fpsShowXml dtd x =
case toContents x of
[CElem _ _] -> (FPS.document . toXml dtd) x
_ -> FPS.empty
toXml :: XmlContent a => Bool -> a -> Document ()
toXml dtd value =
let ht = toHType value in
Document (Prolog (Just (XMLDecl "1.0" Nothing Nothing))
[] (if dtd then Just (toDTD ht) else Nothing) [])
emptyST
( case toContents value of
[] -> Elem (N "empty") [] []
[CElem e ()] -> e
(CElem _ ():_) -> error "too many XML elements in document" )
[]
fromXml :: XmlContent a => Document Posn -> Either String a
fromXml (Document _ _ e@(Elem _ _ _) _) =
fst (runParser parseContents [CElem e (posInNewCxt "document" Nothing)])
hGetXml :: XmlContent a => Handle -> IO a
hGetXml h = do
x <- hGetContents h
let (Document _ _ y _) = xmlParse "file handle" x
either fail return
(fst (runParser parseContents
[CElem y (posInNewCxt "file handle" Nothing)]))
hPutXml :: XmlContent a => Handle -> Bool -> a -> IO ()
hPutXml h dtd x = do
(hPutStrLn h . render . document . toXml dtd) x
fpsHPutXml :: XmlContent a => Handle -> Bool -> a -> IO ()
fpsHPutXml h dtd x = do
(FPS.hPut h . FPS.document . toXml dtd) x
instance XmlContent Char where
toContents _ = error $ "Text.XML.HaXml.XmlContent.toContents "++
" used on a Haskell Char"
parseContents = fail $ "Text.XML.HaXml.XmlContent.parseContents "++
" used on a Haskell Char "
xToChar = id
xFromChar = id
instance XmlContent a => XmlContent [a] where
toContents xs = case toHType x of
(Prim "Char" _) ->
[CString True (map xToChar xs) ()]
_ -> concatMap toContents xs
where (x:_) = xs
parseContents = let result = runParser p []
p = case (toHType . head . (\ (Right x)->x) . fst)
result of
(Prim "Char" _) -> fmap (map xFromChar) $ text
_ -> many parseContents
in p
instance (XmlContent a) => XmlContent (Maybe a) where
toContents m = maybe [] toContents m
parseContents = optional parseContents