module Data.XML.Parser.Mid.Doctype
( ExternalID(..)
, externalID
, GeneralEntityDeclaration(..)
, generalEntityDeclaration
, Doctype(..)
, doctype
) where
import Control.Applicative
import Data.Maybe
import qualified Data.Text as Text
import Data.Text (Text)
import Data.XML.Parser.Low
import Text.Parser.Char
import Text.Parser.Combinators
data ExternalID = PublicID Text Text | SystemID Text
deriving (Eq, Ord, Read, Show)
data GeneralEntityDeclaration = GeneralEntityDeclaration Text [Content]
deriving (Eq, Ord, Read, Show)
data Doctype = Doctype Text (Maybe ExternalID) [GeneralEntityDeclaration]
deriving (Eq, Ord, Read, Show)
generalEntityDeclaration :: CharParsing m => Monad m => m GeneralEntityDeclaration
generalEntityDeclaration = do
tokenEntityDeclarationOpen
tokenWhitespace
name <- tokenName
tokenWhitespace
quote <- tokenQuote
definition <- many (tokenContent $ quote:"%")
char quote
optional tokenWhitespace
tokenElementClose
return $ GeneralEntityDeclaration name definition
externalID :: CharParsing m => Monad m => m ExternalID
externalID = publicID <|> systemID where
publicID = do
string "PUBLIC"
tokenWhitespace
a <- systemLiteral
tokenWhitespace
b <- systemLiteral
return $ PublicID a b
systemID = string "SYSTEM" *> tokenWhitespace *> (SystemID <$> systemLiteral)
systemLiteral = Text.pack <$> manyQuoted anyChar
doctype :: CharParsing m => Monad m => m Doctype
doctype = do
tokenDoctypeOpen
tokenWhitespace
name <- tokenName
externalID <- optional $ tokenWhitespace >> externalID
optional tokenWhitespace
entities <- fromMaybe mempty <$> optional
(between (char '[' >> optional tokenWhitespace) (optional tokenWhitespace >> char ']') $
many generalEntityDeclaration)
tokenElementClose
return $ Doctype name externalID entities
quoted :: CharParsing m => Monad m => m a -> m a
quoted x = x `surroundedBy` tokenSingleQuote <|> x `surroundedBy` tokenDoubleQuote
manyQuoted :: CharParsing m => Monad m => m a -> m [a]
manyQuoted x = manyQuotedBy tokenSingleQuote x <|> manyQuotedBy tokenDoubleQuote x where
manyQuotedBy quote x = do
quote
manyTill x (try quote)