diff --git a/examples/ParseURLs.hs b/examples/ParseURLs.hs
new file mode 100644
--- /dev/null
+++ b/examples/ParseURLs.hs
@@ -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
diff --git a/rdf4h.cabal b/rdf4h.cabal
--- a/rdf4h.cabal
+++ b/rdf4h.cabal
@@ -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
diff --git a/src/Data/RDF.hs b/src/Data/RDF.hs
--- a/src/Data/RDF.hs
+++ b/src/Data/RDF.hs
@@ -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
diff --git a/src/Data/RDF/Types.hs b/src/Data/RDF/Types.hs
--- a/src/Data/RDF/Types.hs
+++ b/src/Data/RDF/Types.hs
@@ -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)
diff --git a/src/Data/RDF/Utils.hs b/src/Data/RDF/Utils.hs
deleted file mode 100644
--- a/src/Data/RDF/Utils.hs
+++ /dev/null
@@ -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)
-
diff --git a/src/Rdf4hParseMain.hs b/src/Rdf4hParseMain.hs
--- a/src/Rdf4hParseMain.hs
+++ b/src/Rdf4hParseMain.hs
@@ -1,3 +1,8 @@
+{-# LANGUAGE OverloadedStrings,
+             RankNTypes,
+             ScopedTypeVariables,
+             MultiParamTypeClasses #-}
+
 module Main where
 
 import Data.RDF.Types
diff --git a/src/Text/RDF/RDF4H/Interact.hs b/src/Text/RDF/RDF4H/Interact.hs
--- a/src/Text/RDF/RDF4H/Interact.hs
+++ b/src/Text/RDF/RDF4H/Interact.hs
@@ -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()
 
diff --git a/src/Text/RDF/RDF4H/NTriplesSerializer.hs b/src/Text/RDF/RDF4H/NTriplesSerializer.hs
--- a/src/Text/RDF/RDF4H/NTriplesSerializer.hs
+++ b/src/Text/RDF/RDF4H/NTriplesSerializer.hs
@@ -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
 
diff --git a/src/Text/RDF/RDF4H/ParserUtils.hs b/src/Text/RDF/RDF4H/ParserUtils.hs
--- a/src/Text/RDF/RDF4H/ParserUtils.hs
+++ b/src/Text/RDF/RDF4H/ParserUtils.hs
@@ -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,
diff --git a/src/Text/RDF/RDF4H/TurtleParser.hs b/src/Text/RDF/RDF4H/TurtleParser.hs
--- a/src/Text/RDF/RDF4H/TurtleParser.hs
+++ b/src/Text/RDF/RDF4H/TurtleParser.hs
@@ -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 
diff --git a/src/Text/RDF/RDF4H/TurtleSerializer.hs b/src/Text/RDF/RDF4H/TurtleSerializer.hs
--- a/src/Text/RDF/RDF4H/TurtleSerializer.hs
+++ b/src/Text/RDF/RDF4H/TurtleSerializer.hs
@@ -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 "")
diff --git a/src/Text/RDF/RDF4H/XmlParser.hs b/src/Text/RDF/RDF4H/XmlParser.hs
--- a/src/Text/RDF/RDF4H/XmlParser.hs
+++ b/src/Text/RDF/RDF4H/XmlParser.hs
@@ -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
