---------------------------------------------------------------------- -- | -- Module : XML -- -- Utilities for creating XML documents. ---------------------------------------------------------------------- module GF.Data.XML (XML(..), Attr, comments, showXMLDoc, showsXMLDoc, showsXML, bottomUpXML) where import GF.Data.Utilities data XML = Data String | CData String | Tag String [Attr] [XML] | ETag String [Attr] | Comment String | Empty deriving (Ord,Eq,Show) type Attr = (String,String) comments :: [String] -> [XML] comments = map Comment showXMLDoc :: XML -> String showXMLDoc xml = showsXMLDoc xml "" showsXMLDoc :: XML -> ShowS showsXMLDoc xml = showString header . showsXML xml where header = "" showsXML :: XML -> ShowS showsXML = showsX 0 where showsX i x = ind i . case x of (Data s) -> showString s (CData s) -> showString "" (ETag t as) -> showChar '<' . showString t . showsAttrs as . showString "/>" (Tag t as cs) -> showChar '<' . showString t . showsAttrs as . showChar '>' . concatS (map (showsX (i+1)) cs) . ind i . showString "' (Comment c) -> showString "" (Empty) -> id ind i = showString ("\n" ++ replicate (2*i) ' ') showsAttrs :: [Attr] -> ShowS showsAttrs = concatS . map (showChar ' ' .) . map showsAttr showsAttr :: Attr -> ShowS showsAttr (n,v) = showString n . showString "=\"" . showString (escape v) . showString "\"" escape :: String -> String escape = concatMap escChar where escChar '<' = "<" escChar '>' = ">" escChar '&' = "&" escChar '"' = """ escChar c = [c] bottomUpXML :: (XML -> XML) -> XML -> XML bottomUpXML f (Tag n attrs cs) = f (Tag n attrs (map (bottomUpXML f) cs)) bottomUpXML f x = f x