rdf4h 1.2.0 → 1.2.1
raw patch · 12 files changed
+156/−121 lines, 12 files
Files
- examples/ParseURLs.hs +18/−0
- rdf4h.cabal +4/−4
- src/Data/RDF.hs +6/−1
- src/Data/RDF/Types.hs +2/−2
- src/Data/RDF/Utils.hs +0/−25
- src/Rdf4hParseMain.hs +5/−0
- src/Text/RDF/RDF4H/Interact.hs +0/−1
- src/Text/RDF/RDF4H/NTriplesSerializer.hs +1/−2
- src/Text/RDF/RDF4H/ParserUtils.hs +6/−4
- src/Text/RDF/RDF4H/TurtleParser.hs +21/−22
- src/Text/RDF/RDF4H/TurtleSerializer.hs +9/−21
- src/Text/RDF/RDF4H/XmlParser.hs +84/−39
+ examples/ParseURLs.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE ScopedTypeVariables,+ OverloadedStrings #-}++module Main where++import Data.RDF++-- | looks up Tim Berners Lee card.rdf file for talks he has given.+-- returns a single String element: [\"Designing the Web for an Open Society\"].+timBernersLee :: IO ()+timBernersLee = do+ Right (rdf::TriplesGraph) <- parseURL (XmlParser Nothing Nothing) "http://www.w3.org/People/Berners-Lee/card.rdf"+ let ts = query rdf (Just (UNode "http://www.w3.org/2011/Talks/0331-hyderabad-tbl/data#talk")) (Just (UNode "dct:title")) Nothing+ let talks = map (\(Triple _ _ (LNode (PlainL s))) -> s) ts+ print talks++main :: IO ()+main = timBernersLee
rdf4h.cabal view
@@ -1,5 +1,5 @@ name: rdf4h-version: 1.2.0+version: 1.2.1 synopsis: A library for RDF processing in Haskell description: 'RDF for Haskell' is a library for working with RDF in Haskell.@@ -21,6 +21,7 @@ stability: Experimental tested-with: GHC==7.6.3 extra-tmp-files: test+extra-source-files: examples/ParseURLs.hs flag small_base description: Choose the new smaller, split-up base package.@@ -55,8 +56,7 @@ , HTTP >= 4000.0.0 , hxt >= 9.0.0 , text- other-modules: Data.RDF.Utils- , Text.RDF.RDF4H.ParserUtils+ other-modules: Text.RDF.RDF4H.ParserUtils , Text.RDF.RDF4H.Interact hs-source-dirs: src extensions: BangPatterns RankNTypes MultiParamTypeClasses Arrows FlexibleContexts OverloadedStrings@@ -110,4 +110,4 @@ source-repository head type: git- location: git://github.com/robstewart57/rdf4h.git+ location: https://github.com/robstewart57/rdf4h.git
src/Data/RDF.hs view
@@ -3,6 +3,10 @@ module Data.RDF ( + RDF(..),+ RdfSerializer(..),+ RdfParser(..),+ -- * Export types and query functions module Data.RDF.Types, module Data.RDF.Query,@@ -16,7 +20,7 @@ module Text.RDF.RDF4H.NTriplesParser, module Text.RDF.RDF4H.TurtleSerializer, module Text.RDF.RDF4H.TurtleParser,-+ module Text.RDF.RDF4H.XmlParser, ) where @@ -27,5 +31,6 @@ import Text.RDF.RDF4H.TurtleSerializer import Text.RDF.RDF4H.NTriplesParser import Text.RDF.RDF4H.TurtleParser+import Text.RDF.RDF4H.XmlParser import Data.RDF.Types import Data.RDF.Query
src/Data/RDF/Types.hs view
@@ -484,8 +484,8 @@ Nothing -> litValue Just fn -> fn litValue --- A table of mappings from a 'T.Text' URI (reversed as--- they are) to a function that canonicalizes a T.Text+-- A table of mappings from a 'T.Text' URI+-- to a function that canonicalizes a T.Text -- assumed to be of that type. {-# NOINLINE canonicalizerTable #-} canonicalizerTable :: Map T.Text (T.Text -> T.Text)
− src/Data/RDF/Utils.hs
@@ -1,25 +0,0 @@--module Data.RDF.Utils (- t2s, s2t, hPutStrRev-) where--import qualified Data.Text as T-import Data.Text.Encoding (encodeUtf8)-import qualified Data.ByteString as B-import System.IO---- |A convenience function for converting from a bytestring to a string.-{-# INLINE t2s #-}-t2s :: T.Text -> String-t2s = T.unpack---- |A convenience function for converting from a string to a bytestring.-{-# INLINE s2t #-}-s2t :: String -> T.Text-s2t = T.pack---- |Write to the handle the reversed value of the bytestring, with no newline.-{-# INLINE hPutStrRev #-}-hPutStrRev :: Handle -> T.Text -> IO ()-hPutStrRev h bs = B.hPutStr h ((encodeUtf8 . T.reverse) bs)-
src/Rdf4hParseMain.hs view
@@ -1,3 +1,8 @@+{-# LANGUAGE OverloadedStrings,+ RankNTypes,+ ScopedTypeVariables,+ MultiParamTypeClasses #-}+ module Main where import Data.RDF.Types
src/Text/RDF/RDF4H/Interact.hs view
@@ -17,7 +17,6 @@ import qualified Data.Text as T import Data.RDF.Types hiding (baseUrl)-import Data.RDF.Utils() import Data.RDF.TriplesGraph() import Data.RDF.MGraph()
src/Text/RDF/RDF4H/NTriplesSerializer.hs view
@@ -7,7 +7,6 @@ import Control.Monad (void) import Data.RDF.Types-import Data.RDF.Utils import qualified Data.Text as T import qualified Data.Text.IO as T import System.IO@@ -44,7 +43,7 @@ (UNode bs) -> hPutChar h '<' >> T.hPutStr h bs >> hPutChar h '>'- (BNode gId) -> hPutStrRev h gId+ (BNode gId) -> T.hPutStr h gId (BNodeGen i)-> putStr "_:genid" >> hPutStr h (show i) (LNode n) -> _writeLValue h n
src/Text/RDF/RDF4H/ParserUtils.hs view
@@ -12,27 +12,28 @@ import qualified Data.Text as T import Data.Maybe (fromMaybe) --- A convenience function for terminating a parse with a parse failure, using+-- | A convenience function for terminating a parse with a parse failure, using -- the given error message as the message for the failure. errResult :: RDF rdf => String -> Either ParseFailure rdf errResult msg = Left (ParseFailure msg) --- Keep the (Just t) triples (eliminating the Nothing comments), and unbox the+-- | Keep the (Just t) triples (eliminating the Nothing comments), and unbox the -- triples, leaving a list of triples. justTriples :: [Maybe Triple] -> [Triple] justTriples = map (fromMaybe (error "ParserUtils.justTriples")) . filter (/= Nothing) +-- | pars contents at URL in to and 'RDF' _parseURL :: RDF rdf => (T.Text -> Either ParseFailure rdf) -> String -> IO (Either ParseFailure rdf) _parseURL parseFunc url = maybe (return (Left (ParseFailure $ "Unable to parse URL: " ++ url)))- p+ doParse (parseURI url) where showRspCode (a, b, c) = map intToDigit [a, b, c] httpError resp = showRspCode (rspCode resp) ++ " " ++ rspReason resp- p url' =+ doParse url' = simpleHTTP (request url') >>= \resp -> case resp of (Left e) -> return (errResult $ "couldn't retrieve from URL: " ++ show url' ++ " [" ++ show e ++ "]")@@ -40,6 +41,7 @@ (2, 0, 0) -> return $ parseFunc (decodeUtf8 (rspBody res)) _ -> return (errResult $ "couldn't retrieve from URL: " ++ httpError res) +-- | construct HTTP GET request. request :: URI -> HTTPRequest B.ByteString request uri = Request { rqURI = uri, rqMethod = GET,
src/Text/RDF/RDF4H/TurtleParser.hs view
@@ -8,7 +8,6 @@ where import Data.RDF.Types-import Data.RDF.Utils import Data.RDF.Namespace import Text.RDF.RDF4H.ParserUtils import Text.Parsec@@ -248,15 +247,15 @@ ds <- many1 digit <?> "digit" notFollowedBy (char '.') -- integer must be in canonical format, with no leading plus sign or leading zero- return $! ( s2t sign `T.append` s2t ds)+ return $! ( T.pack sign `T.append` T.pack ds) t_double :: GenParser ParseState T.Text t_double = do sign <- sign_parser <?> "+-"- rest <- try (do { ds <- many1 digit <?> "digit"; char '.'; ds' <- many digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( s2t ds `T.snoc` '.' `T.append` s2t ds' `T.append` e) }) <|>- try (do { char '.'; ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ('.' `T.cons` s2t ds `T.append` e) }) <|>- try (do { ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( s2t ds `T.append` e) })- return $! s2t sign `T.append` rest+ rest <- try (do { ds <- many1 digit <?> "digit"; char '.'; ds' <- many digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( T.pack ds `T.snoc` '.' `T.append` T.pack ds' `T.append` e) }) <|>+ try (do { char '.'; ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ('.' `T.cons` T.pack ds `T.append` e) }) <|>+ try (do { ds <- many1 digit <?> "digit"; e <- t_exponent <?> "exponent"; return ( T.pack ds `T.append` e) })+ return $! T.pack sign `T.append` rest sign_parser :: GenParser ParseState String sign_parser = option "" (oneOf "-+" >>= (\c -> return [c]))@@ -267,18 +266,18 @@ rest <- try (do ds <- many digit <?> "digit"; char '.'; ds' <- option "" (many digit); return (ds ++ ('.':ds'))) <|> try (do { char '.'; ds <- many1 digit <?> "digit"; return ('.':ds) }) <|> many1 digit <?> "digit"- return $ s2t sign `T.append` s2t rest+ return $ T.pack sign `T.append` T.pack rest t_exponent :: GenParser ParseState T.Text t_exponent = do e <- oneOf "eE" s <- option "" (oneOf "-+" >>= \c -> return [c]) ds <- many1 digit;- return $! (e `T.cons` ( s2t s `T.append` s2t ds))+ return $! (e `T.cons` ( T.pack s `T.append` T.pack ds)) t_boolean :: GenParser ParseState T.Text t_boolean =- try (liftM s2t (string "true") <|>- liftM s2t (string "false"))+ try (liftM T.pack (string "true") <|>+ liftM T.pack (string "false")) t_comment :: GenParser ParseState () t_comment =@@ -294,11 +293,11 @@ t_language :: GenParser ParseState T.Text t_language = do initial <- many1 lower;- rest <- many (do {char '-'; cs <- many1 (lower <|> digit); return ( s2t ('-':cs))})- return $! ( s2t initial `T.append` T.concat rest)+ rest <- many (do {char '-'; cs <- many1 (lower <|> digit); return ( T.pack ('-':cs))})+ return $! ( T.pack initial `T.append` T.concat rest) identifier :: GenParser ParseState Char -> GenParser ParseState Char -> GenParser ParseState T.Text-identifier initial rest = initial >>= \i -> many rest >>= \r -> return ( s2t (i:r))+identifier initial rest = initial >>= \i -> many rest >>= \r -> return ( T.pack (i:r)) t_prefixName :: GenParser ParseState T.Text t_prefixName = identifier t_nameStartCharMinusUnderscore t_nameChar@@ -311,7 +310,7 @@ t_relativeURI :: GenParser ParseState T.Text t_relativeURI =- do frag <- liftM (s2t . concat) (many t_ucharacter)+ do frag <- liftM (T.pack . concat) (many t_ucharacter) bUrl <- currBaseUrl dUrl <- currDocUrl return $ absolutizeUrl bUrl dUrl frag@@ -321,9 +320,9 @@ -- when it creates a T.Text it can all be in one chunk. t_ucharacter :: GenParser ParseState String t_ucharacter =- try (liftM t2s unicode_escape) <|>+ try (liftM T.unpack unicode_escape) <|> try (string "\\>") <|>- liftM t2s (non_ctrl_char_except ">")+ liftM T.unpack (non_ctrl_char_except ">") t_nameChar :: GenParser ParseState Char t_nameChar = t_nameStartChar <|> char '-' <|> char '\x00B7' <|> satisfy f@@ -352,7 +351,7 @@ bs1 = return . T.singleton bs :: String -> GenParser ParseState T.Text-bs = return . s2t+bs = return . T.pack t_nameStartChar :: GenParser ParseState Char t_nameStartChar = char '_' <|> t_nameStartCharMinusUnderscore@@ -387,8 +386,8 @@ unicode_escape = (char '\\' >> return (T.singleton '\\')) >> ((char '\\' >> return "\\\\") <|>- (char 'u' >> count 4 t_hex >>= \cs -> return $! "\\u" `T.append` s2t cs) <|>- (char 'U' >> count 8 t_hex >>= \cs -> return $! "\\U" `T.append` s2t cs))+ (char 'u' >> count 4 t_hex >>= \cs -> return $! "\\u" `T.append` T.pack cs) <|>+ (char 'U' >> count 8 t_hex >>= \cs -> return $! "\\U" `T.append` T.pack cs)) non_ctrl_char_except :: String -> GenParser ParseState T.Text non_ctrl_char_except cs =@@ -410,7 +409,7 @@ (_, _ ) -> Map.findWithDefault err2 prefix pms' where err1 = error "Cannot resolve empty QName prefix to a Base URL."- err2 = error ("Cannot resolve QName prefix: " ++ t2s prefix)+ err2 = error ("Cannot resolve QName prefix: " ++ T.unpack prefix) -- Resolve a URL fragment found on the right side of a prefix mapping by converting it to an absolute URL if possible. absolutizeUrl :: Maybe BaseUrl -> Maybe T.Text -> T.Text -> T.Text@@ -429,7 +428,7 @@ {-# INLINE isAbsoluteUri #-} isAbsoluteUri :: T.Text -> Bool-isAbsoluteUri = T.isInfixOf (s2t [':'])+isAbsoluteUri = T.isInfixOf (T.pack [':']) newBaseUrl :: Maybe BaseUrl -> T.Text -> BaseUrl newBaseUrl Nothing url = BaseUrl url@@ -572,7 +571,7 @@ -- Returns either a @ParseFailure@ or a new RDF containing the parsed triples. parseFile' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe T.Text -> String -> IO (Either ParseFailure rdf) parseFile' bUrl docUrl fpath =- TIO.readFile fpath >>= \bs' -> return $ handleResult bUrl (runParser t_turtleDoc initialState (maybe "" t2s docUrl) bs')+ TIO.readFile fpath >>= \bs' -> return $ handleResult bUrl (runParser t_turtleDoc initialState (maybe "" T.unpack docUrl) bs') where initialState = (bUrl, docUrl, 1, PrefixMappings Map.empty, [], [], [], Seq.empty) -- |Parse the given string as a Turtle document. The arguments and return type have the same semantics
src/Text/RDF/RDF4H/TurtleSerializer.hs view
@@ -10,11 +10,8 @@ import Data.RDF.Types import Data.RDF.Query import Data.RDF.Namespace hiding (rdf)-import Data.RDF.Utils import qualified Data.Text as T-import Data.Text.Encoding (encodeUtf8) import qualified Data.Text.IO as T-import qualified Data.ByteString.Char8 as B import Data.Map(Map) import qualified Data.Map as Map import Data.List@@ -61,20 +58,16 @@ writeBase _ Nothing = return () writeBase h (Just (BaseUrl bUrl)) =- hPutStr h "@base " >> hPutChar h '<' >> B.hPutStr h (encodeUtf8 bUrl) >> hPutStr h "> ." >> hPutChar h '\n'+ hPutStr h "@base " >> hPutChar h '<' >> T.hPutStr h bUrl >> hPutStr h "> ." >> hPutChar h '\n' writePrefixes :: Handle -> PrefixMappings -> IO () writePrefixes h pms = mapM_ (writePrefix h) (toPMList pms) >> hPutChar h '\n' writePrefix :: Handle -> (T.Text, T.Text) -> IO () writePrefix h (pre, uri) =- hPutStr h "@prefix " >> B.hPutStr h (encodeUtf8 pre) >> hPutStr h ": " >>- hPutChar h '<' >> B.hPutStr h (encodeUtf8 uri) >> hPutStr h "> ." >> hPutChar h '\n'+ hPutStr h "@prefix " >> T.hPutStr h pre >> hPutStr h ": " >>+ hPutChar h '<' >> T.hPutStr h uri >> hPutStr h "> ." >> hPutChar h '\n' --- We don't really use the map as a map yet, but we reverse the map anyway so that--- it maps from uri to prefix rather than the usual prefix to uri, since we never need--- to look anything up by prefix, where as we do use the uri for determining which--- prefix to use. writeTriples :: Handle -> Maybe T.Text -> PrefixMappings -> Triples -> IO () writeTriples h mdUrl (PrefixMappings pms) ts = mapM_ (writeSubjGroup h mdUrl revPms) (groupBy equalSubjects ts)@@ -120,21 +113,21 @@ in case mdUrl of Nothing -> writeUNodeUri h currUri prefixes Just url -> if url == currUri then hPutStr h "<>" else writeUNodeUri h currUri prefixes- (BNode gId) -> hPutStrRev h gId+ (BNode gId) -> T.hPutStr h gId (BNodeGen i)-> putStr "_:genid" >> hPutStr h (show i) (LNode n) -> writeLValue h n prefixes writeUNodeUri :: Handle -> T.Text -> Map T.Text T.Text -> IO () writeUNodeUri h uri prefixes = case mapping of- Nothing -> hPutChar h '<' >> B.hPutStr h (encodeUtf8 uri) >> hPutChar h '>'- (Just (pre, localName)) -> B.hPutStr h (encodeUtf8 pre) >> hPutChar h ':' >> B.hPutStr h (encodeUtf8 localName)+ Nothing -> hPutChar h '<' >> T.hPutStr h uri >> hPutChar h '>'+ (Just (pre, localName)) -> T.hPutStr h pre >> hPutChar h ':' >> T.hPutStr h localName where mapping = findMapping prefixes uri -- Print prefix mappings to stdout for debugging. _debugPMs :: Map T.Text T.Text -> IO ()-_debugPMs pms = mapM_ (\(k, v) -> B.putStr (encodeUtf8 k) >> putStr "__" >> B.putStrLn (encodeUtf8 v)) (Map.toList pms)+_debugPMs pms = mapM_ (\(k, v) -> T.putStr k >> putStr "__" >> T.putStrLn v) (Map.toList pms) -- Expects a map from uri to prefix, and returns the (prefix, uri_expansion) -- from the mappings such that uri_expansion is a prefix of uri, or Nothing if@@ -148,8 +141,6 @@ where mapping = find (\(k, _) -> T.isPrefixOf k uri) (Map.toList pms) ---_testPms = Map.fromList [(s2b "http://example.com/ex#", s2b "eg")]- writeLValue :: Handle -> LValue -> Map T.Text T.Text -> IO () writeLValue h lv pms = case lv of@@ -159,7 +150,8 @@ T.hPutStr h lang (TypedL lit dtype) -> writeLiteralString h lit >> hPutStr h "^^" >>- writeUNodeUri h (T.reverse dtype) pms+ writeUNodeUri h dtype pms+ -- writeUNodeUri h (T.reverse dtype) pms writeLiteralString:: Handle -> T.Text -> IO () writeLiteralString h bs =@@ -176,7 +168,3 @@ '"' -> b >>= \b' -> when b' (hPutChar h '\\' >> hPutChar h '"') >> return True '\\' -> b >>= \b' -> when b' (hPutChar h '\\' >> hPutChar h '\\') >> return True _ -> b >>= \b' -> when b' (hPutChar h c) >> return True----subj1 = unode $ s2b "http://example.com/subj"---pred1 = unode $ s2b "http://example.com/pred"---obj1 = typedL (s2b "hello, world") (mkFastString $ makeUri xsd $ s2b "")
src/Text/RDF/RDF4H/XmlParser.hs view
@@ -1,24 +1,33 @@-{-# Language Arrows #-}+{-# Language Arrows,OverloadedStrings #-} -- |An parser for the RDF/XML format -- <http://www.w3.org/TR/REC-rdf-syntax/>. module Text.RDF.RDF4H.XmlParser(- parseXmlRDF, getRDF+ XmlParser(XmlParser) ) where import Control.Arrow (Arrow,(>>>),(<<<),(&&&),(***),arr,returnA) import Control.Arrow.ArrowState (ArrowState,nextState) import Data.List (isPrefixOf) import qualified Data.Map as Map (fromList)-import Data.RDF.Types (RDF,Node(BNodeGen),BaseUrl(..),Triple(..),Triples,Subject,Predicate,Object,PrefixMappings(..),ParseFailure(ParseFailure),mkRdf,lnode,plainL,plainLL,typedL,unode,bnode)-import Data.RDF.Utils (s2t,t2s)-import qualified Data.Text as T (Text)+import Text.RDF.RDF4H.ParserUtils+import Data.RDF.Types (RDF,RdfParser(..),Node(BNodeGen),BaseUrl(..),Triple(..),Triples,Subject,Predicate,Object,PrefixMappings(..),ParseFailure(ParseFailure),mkRdf,lnode,plainL,plainLL,typedL,unode,bnode)+import qualified Data.Text as T (Text,pack,unpack)+import qualified Data.Text.IO as TIO import Text.XML.HXT.Core (ArrowXml,XmlTree,IfThen((:->)),(>.),(>>.),first,neg,(<+>),expandURI,getName,getAttrValue,getAttrValue0,getAttrl,hasAttrValue,hasAttr,constA,choiceA,getChildren,ifA,arr2A,second,hasName,isElem,xshow,listA,isA,isText,getText,this,unlistA,orElse,sattr,mkelem,xread,runSLA) --- TODO: Create instance:--- RdfParse XmlParser+-- TODO: write QuickCheck tests for XmlParser instance for RdfParser. +data XmlParser = XmlParser (Maybe BaseUrl) (Maybe T.Text)++-- |'XmlParser' is an instance of 'RdfParser'.+instance RdfParser XmlParser where+ parseString (XmlParser bUrl dUrl) = parseXmlRDF bUrl dUrl + parseFile (XmlParser bUrl dUrl) = parseFile' bUrl dUrl+ parseURL (XmlParser bUrl dUrl) = parseURL' bUrl dUrl++ -- |Global state for the parser data GParseState = GParseState { stateGenId :: Int }@@ -31,6 +40,42 @@ } deriving(Show) +-- |Parse the given file as a XML document. The arguments and return type have the same semantics+-- as 'parseURL', except that the last String argument corresponds to a filesystem location rather+-- than a location URI.+--+-- Returns either a @ParseFailure@ or a new RDF containing the parsed triples.+parseFile' :: forall rdf. (RDF rdf) => Maybe BaseUrl -> Maybe T.Text -> String -> IO (Either ParseFailure rdf)+parseFile' bUrl dUrl fpath =+ TIO.readFile fpath >>= return . parseXmlRDF bUrl dUrl++-- |Parse the document at the given location URL as an XML document, using an optional @BaseUrl@+-- as the base URI, and using the given document URL as the URI of the XML document itself.+--+-- The @BaseUrl@ is used as the base URI within the document for resolving any relative URI references.+-- It may be changed within the document using the @\@base@ directive. At any given point, the current+-- base URI is the most recent @\@base@ directive, or if none, the @BaseUrl@ given to @parseURL@, or +-- if none given, the document URL given to @parseURL@. For example, if the @BaseUrl@ were+-- @http:\/\/example.org\/@ and a relative URI of @\<b>@ were encountered (with no preceding @\@base@ +-- directive), then the relative URI would expand to @http:\/\/example.org\/b@.+--+-- The document URL is for the purpose of resolving references to 'this document' within the document,+-- and may be different than the actual location URL from which the document is retrieved. Any reference+-- to @\<>@ within the document is expanded to the value given here. Additionally, if no @BaseUrl@ is +-- given and no @\@base@ directive has appeared before a relative URI occurs, this value is used as the+-- base URI against which the relative URI is resolved.+--p+-- Returns either a @ParseFailure@ or a new RDF containing the parsed triples.+parseURL' :: forall rdf. (RDF rdf) => + Maybe BaseUrl -- ^ The optional base URI of the document.+ -> Maybe T.Text -- ^ The document URI (i.e., the URI of the document itself); if Nothing, use location URI.+ -> String -- ^ The location URI from which to retrieve the XML document.+ -> IO (Either ParseFailure rdf)+ -- ^ The parse result, which is either a @ParseFailure@ or the RDF+ -- corresponding to the XML document.+parseURL' bUrl docUrl = _parseURL (parseXmlRDF bUrl docUrl)++ -- |Parse a xml T.Text to an RDF representation parseXmlRDF :: forall rdf. (RDF rdf) => Maybe BaseUrl -- ^ The base URL for the RDF if required@@ -40,7 +85,7 @@ parseXmlRDF bUrl dUrl xmlStr = case runParseArrow of (_,r:_) -> Right r _ -> Left (ParseFailure "XML parsing failed")- where runParseArrow = runSLA (xread >>> addMetaData bUrl dUrl >>> getRDF) initState (t2s xmlStr)+ where runParseArrow = runSLA (xread >>> addMetaData bUrl dUrl >>> getRDF) initState (T.unpack xmlStr) initState = GParseState { stateGenId = 0 } -- |Add a root tag to a given XmlTree to appear as if it was read from a readDocument function@@ -51,21 +96,21 @@ ] ++ mkSource dUrlM ++ mkBase bUrlM ) [ arr id ]- where mkSource (Just dUrl) = [ sattr "source" (t2s dUrl) ]+ where mkSource (Just dUrl) = [ sattr "source" (T.unpack dUrl) ] mkSource Nothing = []- mkBase (Just (BaseUrl bUrl)) = [ sattr "transfer-URI" (t2s bUrl) ]+ mkBase (Just (BaseUrl bUrl)) = [ sattr "transfer-URI" (T.unpack bUrl) ] mkBase Nothing = [] -- |Arrow that translates HXT XmlTree to an RDF representation getRDF :: forall rdf a. (RDF rdf, ArrowXml a, ArrowState GParseState a) => a XmlTree rdf getRDF = proc xml -> do rdf <- hasName "rdf:RDF" <<< isElem <<< getChildren -< xml- bUrl <- arr (BaseUrl . s2t) <<< ((getAttrValue0 "xml:base" <<< isElem <<< getChildren) `orElse` getAttrValue "transfer-URI") -< xml+ bUrl <- arr (BaseUrl . T.pack) <<< ((getAttrValue0 "xml:base" <<< isElem <<< getChildren) `orElse` getAttrValue "transfer-URI") -< xml prefixMap <- arr toPrefixMap <<< toAttrMap -< rdf triples <- parseDescription' >. id -< (bUrl, rdf) returnA -< mkRdf triples (Just bUrl) prefixMap where toAttrMap = (getAttrl >>> (getName &&& (getChildren >>> getText))) >. id- toPrefixMap = PrefixMappings . Map.fromList . map (\(n, m) -> (s2t (drop 6 n), s2t m)) . filter (isPrefixOf "xmlns:" . fst)+ toPrefixMap = PrefixMappings . Map.fromList . map (\(n, m) -> (T.pack (drop 6 n), T.pack m)) . filter (isPrefixOf "xmlns:" . fst) -- |Read the initial state from an rdf element parseDescription' :: forall a. (ArrowXml a, ArrowState GParseState a) => a (BaseUrl, XmlTree) Triple@@ -83,9 +128,9 @@ <+> (second (neg (hasName "rdf:Description")) >>> arr2A readTypeTriple)) >>. replaceLiElems [] (1 :: Int) where readTypeTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple- readTypeTriple state = getName >>> arr (Triple (stateSubject state) rdfType . unode . s2t)- replaceLiElems acc n (Triple s p o : rest) | p == (unode . s2t) "rdf:li" =- replaceLiElems (Triple s ((unode . s2t) ("rdf:_" ++ show n)) o : acc) (n + 1) rest+ readTypeTriple state = getName >>> arr (Triple (stateSubject state) rdfType . unode . T.pack)+ replaceLiElems acc n (Triple s p o : rest) | p == (unode . T.pack) "rdf:li" =+ replaceLiElems (Triple s ((unode . T.pack) ("rdf:_" ++ show n)) o : acc) (n + 1) rest replaceLiElems acc n (Triple s p o : rest) = replaceLiElems (Triple s p o : acc) n rest replaceLiElems acc _ [] = acc @@ -93,13 +138,13 @@ parseAsResource :: forall a. (ArrowXml a, ArrowState GParseState a) => Node -> a (LParseState, XmlTree) Triple parseAsResource n = updateState >>> (arr2A parsePredicatesFromAttr- <+> (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2t) p) n))+ <+> (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . T.pack) p) n)) <+> (arr (\s -> s { stateSubject = n }) *** (getChildren >>> isElem) >>> parsePredicatesFromChildren)) -- |Read the attributes of an rdf:Description element. These correspond to the Predicate Object pairs of the Triple parsePredicatesFromAttr :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple parsePredicatesFromAttr state = getAttrl- >>> (getName >>> neg isMetaAttr >>> mkUNode) &&& (getChildren >>> getText >>> arr (lnode . plainL . s2t))+ >>> (getName >>> neg isMetaAttr >>> mkUNode) &&& (getChildren >>> getText >>> arr (lnode . plainL . T.pack)) >>> arr (attachSubject (stateSubject state)) -- | Arrow to determine if special processing is required for an attribute@@ -126,10 +171,10 @@ , this :-> defaultA ] where defaultA = proc (state, predXml) -> do- p <- arr(unode . s2t) <<< getName -< predXml+ p <- arr(unode . T.pack) <<< getName -< predXml t <- arr2A (arr2A . parseObjectsFromChildren) <<< second (second getChildren) -< (state, (p, predXml)) returnA -< t- parsePredicateAttr n = (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . s2t) p) n))+ parsePredicateAttr n = (second getName >>> arr (\(s, p) -> Triple (stateSubject s) ((unode . T.pack) p) n)) <+> (first (arr (\s -> s { stateSubject = n })) >>> arr2A parsePredicatesFromAttr) hasPredicateAttr = getAttrl >>> neg (getName >>> isMetaAttr) @@ -162,7 +207,7 @@ updateState = ifA (second (hasAttr "xml:lang")) (arr2A readLang) (arr id) >>> ifA (second (hasAttr "xml:base")) (arr2A readBase) (arr id) where readLang state = (getAttrValue0 "xml:lang" >>> arr (\lang -> state { stateLang = Just lang } ) ) &&& arr id- readBase state = (getAttrValue0 "xml:base" >>> arr (\base -> state { stateBaseUrl = (BaseUrl . s2t) base } ) ) &&& arr id+ readBase state = (getAttrValue0 "xml:base" >>> arr (\base -> state { stateBaseUrl = (BaseUrl . T.pack) base } ) ) &&& arr id -- |Read a Triple with an rdf:parseType of Literal parseAsLiteralTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple@@ -181,7 +226,7 @@ -- |Read a Triple and it's type when rdf:datatype is available getTypedTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple-getTypedTriple state = nameToUNode &&& (attrExpandURI state "rdf:datatype" &&& xshow getChildren >>> arr (\(t, v) -> mkTypedLiteralNode (s2t t) v))+getTypedTriple state = nameToUNode &&& (attrExpandURI state "rdf:datatype" &&& xshow getChildren >>> arr (\(t, v) -> mkTypedLiteralNode (T.pack t) v)) >>> arr (attachSubject (stateSubject state)) getResourceTriple :: forall a. (ArrowXml a, ArrowState GParseState a)@@ -191,14 +236,14 @@ getNodeIdTriple :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Triple-getNodeIdTriple state = nameToUNode &&& (getAttrValue "rdf:nodeID" >>> arr (bnode . s2t))+getNodeIdTriple state = nameToUNode &&& (getAttrValue "rdf:nodeID" >>> arr (bnode . T.pack)) >>> arr (attachSubject (stateSubject state)) -- |Read a Node from the "rdf:about" property or generate a blank node mkNode :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Node mkNode state = choiceA [ hasAttr "rdf:about" :-> (attrExpandURI state "rdf:about" >>> mkUNode) , hasAttr "rdf:resource" :-> (attrExpandURI state "rdf:resource" >>> mkUNode)- , hasAttr "rdf:nodeID" :-> (getAttrValue "rdf:nodeID" >>> arr (bnode . s2t))+ , hasAttr "rdf:nodeID" :-> (getAttrValue "rdf:nodeID" >>> arr (bnode . T.pack)) , hasAttr "rdf:ID" :-> mkRelativeNode state , this :-> mkBlankNode ]@@ -206,41 +251,41 @@ rdfXmlLiteral :: T.Text rdfFirst,rdfRest,rdfNil,rdfType,rdfStatement,rdfSubject,rdfPredicate,rdfObject :: Node -rdfXmlLiteral = s2t "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"-rdfFirst = (unode . s2t) "rdf:first"-rdfRest = (unode . s2t) "rdf:rest"-rdfNil = (unode . s2t) "rdf:nil"-rdfType = (unode . s2t) "rdf:type"-rdfStatement = (unode . s2t) "rdf:Statement"-rdfSubject = (unode . s2t) "rdf:subject"-rdfPredicate = (unode . s2t) "rdf:predicate"-rdfObject = (unode . s2t) "rdf:object"+rdfXmlLiteral = T.pack "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"+rdfFirst = (unode . T.pack) "rdf:first"+rdfRest = (unode . T.pack) "rdf:rest"+rdfNil = (unode . T.pack) "rdf:nil"+rdfType = (unode . T.pack) "rdf:type"+rdfStatement = (unode . T.pack) "rdf:Statement"+rdfSubject = (unode . T.pack) "rdf:subject"+rdfPredicate = (unode . T.pack) "rdf:predicate"+rdfObject = (unode . T.pack) "rdf:object" nameToUNode :: forall a. (ArrowXml a) => a XmlTree Node nameToUNode = getName >>> mkUNode attrExpandURI :: forall a. (ArrowXml a) => LParseState -> String -> a XmlTree String attrExpandURI state attr = getAttrValue attr &&& baseUrl >>> expandURI- where baseUrl = constA (case stateBaseUrl state of BaseUrl b -> t2s b)+ where baseUrl = constA (case stateBaseUrl state of BaseUrl b -> T.unpack b) -- |Make a UNode from an absolute string mkUNode :: forall a. (Arrow a) => a String Node-mkUNode = arr (unode . s2t)+mkUNode = arr (unode . T.pack) -- |Make a UNode from a rdf:ID element, expanding relative URIs mkRelativeNode :: forall a. (ArrowXml a, ArrowState GParseState a) => LParseState -> a XmlTree Node mkRelativeNode s = (getAttrValue "rdf:ID" >>> arr (\x -> '#':x)) &&& baseUrl- >>> expandURI >>> arr (unode . s2t)- where baseUrl = constA (case stateBaseUrl s of BaseUrl b -> t2s b)+ >>> expandURI >>> arr (unode . T.pack)+ where baseUrl = constA (case stateBaseUrl s of BaseUrl b -> T.unpack b) -- |Make a literal node with the given type and content mkTypedLiteralNode :: T.Text -> String -> Node-mkTypedLiteralNode t content = lnode (typedL (s2t content) t)+mkTypedLiteralNode t content = lnode (typedL (T.pack content) t) -- |Use the given state to create a literal node mkLiteralNode :: LParseState -> String -> Node-mkLiteralNode (LParseState _ (Just lang) _) content = lnode (plainLL (s2t content) (s2t lang))-mkLiteralNode (LParseState _ Nothing _) content = (lnode . plainL . s2t) content+mkLiteralNode (LParseState _ (Just lang) _) content = lnode (plainLL (T.pack content) (T.pack lang))+mkLiteralNode (LParseState _ Nothing _) content = (lnode . plainL . T.pack) content -- |Generate an RDF blank node with incrementing IDs from the arrow state mkBlankNode :: forall a b. (ArrowState GParseState a) => a b Node