{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TupleSections #-} module Data.XRD.XML ( toDocument ) where import Data.Maybe (catMaybes) import Data.Text (Text, pack) import Data.Time (defaultTimeLocale, formatTime, iso8601DateFormat) import Data.Foldable (for_) import Text.XML (Document(..), Prologue(..), Element(..), Name(..), def) import Text.XML.Writer (XML) import qualified Data.Map as Map import qualified Text.XML.Writer as XML import Data.XRD.Types ( XRD(..) , Subject(..) , Property(..) , Link(..), LinkType(..), Title(..) , uriText, linkRelText ) toDocument :: XRD -> Document toDocument XRD{..} = document xrdID $ do for_ xrdExpires $ \expires -> XML.element (xrdName "Expires") . pack $ formatTime defaultTimeLocale xmlTime expires for_ xrdSubject $ \(Subject subjectURI) -> XML.element (xrdName "Subject") $ uriText subjectURI for_ xrdAliases $ \(Subject subjectURI) -> XML.element (xrdName "Alias") $ uriText subjectURI for_ xrdProperties renderProperty for_ xrdLinks $ \Link{..} -> do let attrs = catMaybes [ fmap (("rel",) . linkRelText) linkRel , fmap (\(LinkType lt) -> ("type", lt)) linkType , fmap (\href -> ("href", uriText href)) linkHref , fmap (\template -> ("template", template)) linkTemplate ] XML.elementA (xrdName "Link") attrs $ do for_ linkTitles $ \(Title lang text) -> case lang of Nothing -> XML.element (xrdName "Title") text Just value -> XML.elementA (xrdName "Title") [("xml:lang", value)] text for_ linkProperties renderProperty document :: Maybe Text -> XML -> Document document xrdID xml = Document { documentPrologue = Prologue def def def , documentRoot = Element { elementName = xrdName "XRD" , elementAttributes = case xrdID of Nothing -> mempty Just id' -> Map.singleton "id" id' , elementNodes = XML.render xml } , documentEpilogue = mempty } renderProperty :: Property -> XML renderProperty (Property propertyURI body) = XML.elementA (xrdName "Property") attrs content where (attrs, content) = case body of Just text -> ( [("type", uriText propertyURI)] , XML.content text ) Nothing -> ( [ ("type", uriText propertyURI) , ("{http://www.w3.org/2001/XMLSchema-instance}nil", "True") ] , XML.empty ) xrdName :: Text -> Name xrdName name = Name { nameLocalName = name , nameNamespace = Just "http://docs.oasis-open.org/ns/xri/xrd-1.0" , namePrefix = Nothing } xmlTime :: String xmlTime = iso8601DateFormat $ Just "%H:%M:%SZ"