module Text.RSS1.Import
( elementToFeed
) where
import Prelude.Compat
import Data.XML.Compat
import Data.XML.Types as XML
import Text.DublinCore.Types
import Text.RSS1.Syntax
import Text.RSS1.Utils
import Control.Monad.Compat (guard, mplus)
import Data.Maybe (mapMaybe)
import Data.Text.Util
elementToFeed :: XML.Element -> Maybe Feed
elementToFeed e = do
guard (elementName e == rdfName "RDF")
ver <- pAttr (Nothing, Nothing) "xmlns" e `mplus` Just rss10NS
ch <- pNode "channel" e >>= elementToChannel
let mbImg = pNode "image" e >>= elementToImage
let is = maybe [] elementToItems $ pNode "items" e
let mbTI = pNode "textinput" e >>= elementToTextInput
let ch1 = ch {channelItemURIs = is}
let its = pMany (Just rss10NS, Nothing) "item" elementToItem e
let es_rest = removeKnownElts e
let as_rest = removeKnownAttrs e
return
Feed
{ feedVersion = ver
, feedChannel = ch1
, feedImage = mbImg
, feedItems = its
, feedTextInput = mbTI
, feedTopics =
mapMaybe elementToTaxonomyTopic $ pQNodes (qualName' (taxNS, taxPrefix) "topic") e
, feedOther = es_rest
, feedAttrs = as_rest
}
elementToItems :: XML.Element -> [URIString]
elementToItems = seqLeaves
elementToTextInput :: XML.Element -> Maybe TextInputInfo
elementToTextInput e = do
let es = children e
uri <- pAttr' (rdfNS, rdfPrefix) "about" e
ti <- pQLeaf (rss10NS, Nothing) "title" e
desc <- pQLeaf (rss10NS, Nothing) "description" e
na <- pQLeaf (rss10NS, Nothing) "name" e
li <- pQLeaf (rss10NS, Nothing) "link" e
let dcs = mapMaybe elementToDC es
return
TextInputInfo
{ textInputURI = uri
, textInputTitle = ti
, textInputDesc = desc
, textInputName = na
, textInputLink = li
, textInputDC = dcs
, textInputOther = es
, textInputAttrs = elementAttributes e
}
elementToItem :: XML.Element -> Maybe Item
elementToItem e = do
guard (elementName e == qualName (Just rss10NS, Nothing) "item")
let es = children e
uri <- pAttr' (rdfNS, rdfPrefix) "about" e
ti <- pQLeaf (rss10NS, Nothing) "title" e
li <- pQLeaf (rss10NS, Nothing) "link" e
let desc = pQLeaf (rss10NS, Nothing) "description" e
let dcs = mapMaybe elementToDC es
let tos = maybe [] bagLeaves $ pQNode (qualName' (taxNS, taxPrefix) "topics") e
let cs = mapMaybe elementToContent es
let es_other = removeKnownElts e
let as_other = removeKnownAttrs e
return
Item
{ itemURI = uri
, itemTitle = ti
, itemLink = li
, itemDesc = desc
, itemDC = dcs
, itemTopics = tos
, itemContent = cs
, itemOther = es_other
, itemAttrs = as_other
}
elementToImage :: XML.Element -> Maybe Image
elementToImage e = do
let es = children e
let as = elementAttributes e
uri <- pAttr' (rdfNS, rdfPrefix) "about" e
ti <- pLeaf "title" e
ur <- pLeaf "url" e
li <- pLeaf "link" e
let dcs = mapMaybe elementToDC es
return
Image
{ imageURI = uri
, imageTitle = ti
, imageURL = ur
, imageLink = li
, imageDC = dcs
, imageOther = es
, imageAttrs = as
}
elementToChannel :: XML.Element -> Maybe Channel
elementToChannel e = do
let es = children e
uri <- pAttr' (rdfNS, rdfPrefix) "about" e
ti <- pLeaf "title" e
li <- pLeaf "link" e
de <- pLeaf "description" e
let mbImg = pLeaf "image" e
let is = maybe [] seqLeaves $ pNode "items" e
let tinp = pLeaf "textinput" e
let dcs = mapMaybe elementToDC es
let tos = maybe [] bagLeaves $ pQNode (qualName' (taxNS, taxPrefix) "topics") e
let cs = mapMaybe elementToContent es
let es_other = removeKnownElts e
let as_other = removeKnownAttrs e
let def_chan =
Channel
{ channelURI = uri
, channelTitle = ti
, channelLink = li
, channelDesc = de
, channelImageURI = mbImg
, channelItemURIs = is
, channelTextInputURI = tinp
, channelDC = dcs
, channelUpdatePeriod = Nothing
, channelUpdateFreq = Nothing
, channelUpdateBase = Nothing
, channelContent = cs
, channelTopics = tos
, channelOther = es_other
, channelAttrs = as_other
}
return (addSyndication e def_chan)
addSyndication :: XML.Element -> Channel -> Channel
addSyndication e ch =
ch
{ channelUpdatePeriod = toUpdatePeriod <$> pQLeaf' (synNS, synPrefix) "updatePeriod" e
, channelUpdateFreq = readInt =<< pQLeaf' (synNS, synPrefix) "updateFrequency" e
, channelUpdateBase = pQLeaf' (synNS, synPrefix) "updateBase" e
}
where
toUpdatePeriod x =
case x of
"hourly" -> Update_Hourly
"daily" -> Update_Daily
"weekly" -> Update_Weekly
"monthly" -> Update_Monthly
"yearly" -> Update_Yearly
_ -> Update_Hourly
elementToDC :: XML.Element -> Maybe DCItem
elementToDC e = do
guard (nameNamespace (elementName e) == Just dcNS)
let dcItem x = DCItem {dcElt = x, dcText = strContent e}
return $
dcItem $
case nameLocalName $ elementName e of
"title" -> DC_Title
"creator" -> DC_Creator
"subject" -> DC_Subject
"description" -> DC_Description
"publisher" -> DC_Publisher
"contributor" -> DC_Contributor
"date" -> DC_Date
"type" -> DC_Type
"format" -> DC_Format
"identifier" -> DC_Identifier
"source" -> DC_Source
"language" -> DC_Language
"relation" -> DC_Relation
"coverage" -> DC_Coverage
"rights" -> DC_Rights
oth -> DC_Other oth
elementToTaxonomyTopic :: XML.Element -> Maybe TaxonomyTopic
elementToTaxonomyTopic e = do
guard (elementName e == qualName' (taxNS, taxPrefix) "topic")
let es = children e
uri <- pAttr' (rdfNS, rdfPrefix) "about" e
li <- pQLeaf' (taxNS, taxPrefix) "link" e
return
TaxonomyTopic
{ taxonomyURI = uri
, taxonomyLink = li
, taxonomyTitle = pLeaf "title" e
, taxonomyDesc = pLeaf "description" e
, taxonomyTopics = maybe [] bagLeaves $ pQNode (qualName' (taxNS, taxPrefix) "topics") e
, taxonomyDC = mapMaybe elementToDC es
, taxonomyOther = es
}
elementToContent :: XML.Element -> Maybe ContentInfo
elementToContent e = do
guard (elementName e == qualName' (conNS, conPrefix) "items")
return
ContentInfo
{ contentURI = pAttr' (rdfNS, rdfPrefix) "about" e
, contentFormat = pQLeaf' (conNS, conPrefix) "format" e
, contentEncoding = pQLeaf' (conNS, conPrefix) "encoding" e
, contentValue = pQLeaf' (rdfNS, rdfPrefix) "value" e
}
bagLeaves :: XML.Element -> [URIString]
bagLeaves be =
mapMaybe
(\e -> do
guard (elementName e == qualName' (rdfNS, rdfPrefix) "li")
pAttr' (rdfNS, rdfPrefix) "resource" e `mplus`
fmap strContent (pQNode (qualName' (rdfNS, rdfPrefix) "li") e))
(maybe [] children $ pQNode (qualName' (rdfNS, rdfPrefix) "Bag") be)
seqLeaves :: XML.Element -> [URIString]
seqLeaves se =
mapMaybe
(\e -> do
guard (elementName e == rdfName "li")
return (strContent e))
(maybe [] children $ pQNode (rdfName "Seq") se)