module Database.HSparql.Connection ( EndPoint , BindingValue(..) , query ) where import Control.Monad import Data.Maybe import Network.HTTP import Text.XML.Light import Database.HSparql.QueryGenerator -- |URI of the SPARQL endpoint. type EndPoint = String -- |Local representations of incoming XML results. data BindingValue = URI String -- ^Absolute reference to remote resource. | Literal String -- ^Simple literal string. | TypedLiteral String String -- ^Literal element with type resource | LangLiteral String String -- ^Literal element with language resource | Unbound -- ^Unbound result value deriving (Show, Eq) -- |Base 'QName' for results with a SPARQL-result URI specified. sparqlResult :: String -> QName sparqlResult s = (unqual s) { qURI = Just "http://www.w3.org/2005/sparql-results#" } -- |Transform the 'String' result from the HTTP request into a two-dimensional -- table storing the bindings for each variable in each row. structureContent :: String -> Maybe [[BindingValue]] structureContent s = do e <- doc return $ map (projectResult $ vars e) $ findElements (sparqlResult "result") e where doc :: Maybe Element doc = parseXMLDoc s vars :: Element -> [String] vars = catMaybes . map (findAttr $ unqual "name") . findElements (sparqlResult "variable") projectResult :: [String] -> Element -> [BindingValue] projectResult vs e = map pVar vs where pVar v = maybe Unbound (value . head . elChildren) $ filterElement (pred v) e pred v e = isJust $ do a <- findAttr (unqual "name") e guard $ a == v value :: Element -> BindingValue value e = case qName (elName e) of "uri" -> URI (strContent e) "literal" -> case findAttr (unqual "datatype") e of Just dt -> TypedLiteral (strContent e) dt Nothing -> case findAttr langAttr e of Just lang -> LangLiteral (strContent e) lang Nothing -> Literal (strContent e) _ -> Unbound langAttr :: QName langAttr = blank_name { qName = "lang", qPrefix = Just "xml" } -- |Connect to remote 'EndPoint' and find all possible bindings for the -- 'Variable's in the 'Query' action. query :: EndPoint -> Query [Variable] -> IO (Maybe [[BindingValue]]) query ep q = do let uri = ep ++ "?" ++ urlEncodeVars [("query", createQuery q)] request = replaceHeader HdrUserAgent "hsparql-client" (getRequest uri) response <- simpleHTTP request >>= getResponseBody return $ structureContent response