diff --git a/Swish/RDF/Datatype.hs b/Swish/RDF/Datatype.hs
--- a/Swish/RDF/Datatype.hs
+++ b/Swish/RDF/Datatype.hs
@@ -1000,7 +1000,7 @@
 --  * supertypes may be introduced retrospectively,
 --
 --  * the relationship expressed with respect to a single datatype
---      cannot indicate hiow to do injections/restrictions between the
+--      cannot indicate how to do injections/restrictions between the
 --      underlying value types.
 --
 --  [@ex@]      is the type of expression with which the datatype may be used.
diff --git a/Swish/RDF/GraphMatch.hs b/Swish/RDF/GraphMatch.hs
--- a/Swish/RDF/GraphMatch.hs
+++ b/Swish/RDF/GraphMatch.hs
@@ -417,6 +417,7 @@
 --
 assignLabelMap :: (Label lb) => [lb] -> LabelMap lb -> LabelMap lb
 assignLabelMap ns lmap = foldl (flip assignLabelMap1) lmap ns
+-- TODO: foldl to foldl' ?
 
 assignLabelMap1 :: (Label lb) => lb -> LabelMap lb -> LabelMap lb
 assignLabelMap1 lab (LabelMap g lvs) = LabelMap g lvs'
@@ -533,7 +534,7 @@
 -- | Return list of distinct labels used in a graph
 
 graphLabels :: (Label lb) => [Arc lb] -> [lb]
-graphLabels gs = nub $ concatMap arcLabels gs
+graphLabels = nub . concatMap arcLabels
 
 {-  OLD CODE:
 graphLabels gs = graphLabels1 gs []
diff --git a/Swish/RDF/N3Formatter.hs b/Swish/RDF/N3Formatter.hs
--- a/Swish/RDF/N3Formatter.hs
+++ b/Swish/RDF/N3Formatter.hs
@@ -90,7 +90,7 @@
 import Swish.Utils.Namespace
     ( ScopedName(..), getScopeURI )
 
-import Data.Char (ord, isDigit)
+import Data.Char (ord, isDigit, toLower)
 
 import Data.List (foldl', delete, groupBy, partition, sort)
 
@@ -795,11 +795,14 @@
       queueFormula lab
       return name
 
--- We assume there that the values are valid (e.g. that lit is syntactically
--- correct).
+-- The canonical notation for xsd:double in XSD, with an upper-case E,
+-- does not match the syntax used in N3, so we need to convert here.     
+-- Rather than converting back to a Double and then displaying that       
+-- we just convert E to e for now.      
 --      
 formatLabel _ (Lit lit (Just dtype)) 
-  | dtype `elem` [xsd_boolean, xsd_decimal, xsd_integer, xsd_double] = return lit
+  | dtype == xsd_double = return $ map toLower lit
+  | dtype `elem` [xsd_boolean, xsd_decimal, xsd_integer] = return lit
   | otherwise = return $ quoteStr lit ++ formatAnnotation dtype
 formatLabel _ (Lit lit Nothing) = return $ quoteStr lit
 
@@ -820,6 +823,9 @@
 There is also no need to restrict the string to the
 ASCII character set; this could be an option but we
 can also leave Unicode as is (or at least convert to UTF-8).
+
+If we use """ to surround the string then we protect the
+last character if it is a " (assuming it isn't protected).
 -}
 
 quoteStr :: String -> String
@@ -829,13 +835,21 @@
       qch = replicate n '"'                              
   in qch ++ qst ++ qch
 
--- if the first element is True then we need to 
--- quote " and new lines.
+-- The boolean flag is True if the string is being displayed
+-- with single quotes, which should mean that there are
+-- no newline or quote characters in the string.
 --
+-- TODO: when flag == False need to worry about n > 2 quotes
+-- in a row.
+--
 quote :: Bool -> String -> String
 quote _     []           = ""
-quote True  ('"': st)    = '\\':'"': quote True  st
-quote True  ('\n':st)    = '\\':'n': quote True  st
+quote False s@(c:'"':[]) | c == '\\'  = s -- handle triple-quoted strings ending in "
+                         | otherwise  = [c, '\\', '"']
+
+-- quote True  ('"': st)    = '\\':'"': quote True  st  -- this should not happen
+-- quote True  ('\n':st)    = '\\':'n': quote True  st  -- this should not happen
+
 quote True  ('\t':st)    = '\\':'t': quote True  st
 quote False ('"': st)    =      '"': quote False st
 quote False ('\n':st)    =     '\n': quote False st
diff --git a/Swish/RDF/N3Parser.hs b/Swish/RDF/N3Parser.hs
--- a/Swish/RDF/N3Parser.hs
+++ b/Swish/RDF/N3Parser.hs
@@ -32,16 +32,6 @@
 --
 --  UTF-8 handling is not really tested.
 --
---  Several items seem to be allowed (from looking at N3 test suites and files
---  'in the wild') that are not given supported by the N3 grammar [1]. We try
---  to support these, including
---
---    - \"@:@\" and \"@base:@\" as valid QNames (ie a blank local component)
---
---    - @true@ and @false@ as well as @\@true@ and @\@false@
---
---    - use of lower-case characters for @\\u@ and @\\U@ escape codes
---
 --  No performance testing has been applied.
 --
 --  Not all N3 grammar elements are supported, including:
@@ -81,6 +71,7 @@
 
 import Swish.RDF.RDFGraph
     ( RDFGraph, RDFLabel(..)
+    , ToRDFLabel(..)
     , NamespaceMap
     , LookupFormula(..) 
     , addArc 
@@ -959,11 +950,21 @@
 numericliteral ::=		|	decimal
 		|	double
 		|	integer
+
+TODO: we could convert via something like
+
+  maybeRead value :: Double >>= Just . toRDFLabel
+
+which would mean we store the canonical XSD value in the
+label, but it is not useful for the xsd:decimal case
+since we currently don't have a Haskell type that
+goes with it.
 -}
 
 numericLiteral :: N3Parser RDFLabel
 numericLiteral =
-  try (mkTypedLit xsd_double <$> n3double)
+  -- try (mkTypedLit xsd_double <$> n3double)
+  try (d2s <$> n3double)
   <|> try (mkTypedLit xsd_decimal <$> n3decimal)
   <|> mkTypedLit xsd_integer <$> n3integer
   <?> "numericliteral"
@@ -984,6 +985,11 @@
            
 n3double :: N3Parser String  
 n3double = (++) <$> n3decimal <*> ( (:) <$> oneOf "eE" <*> n3integer )
+
+-- convert a double, as returned by n3double, into it's
+-- canonical XSD form
+d2s :: String -> RDFLabel
+d2s s = toRDFLabel (read s :: Double)
 
 {-
 propertylist ::=		|	verb object objecttail propertylisttail
diff --git a/Swish/RDF/RDFDatatype.hs b/Swish/RDF/RDFDatatype.hs
--- a/Swish/RDF/RDFDatatype.hs
+++ b/Swish/RDF/RDFDatatype.hs
@@ -146,36 +146,18 @@
     RDFDatatypeVal vt -> ModifierFn vt -> RDFModifierFn
 makeRDFModifierFn dtval fn ivs =
     let
-        ivals = mapM (rdfNodeExtract dtval) ivs
+        ivals = mapM (fromRDFLabel dtval) ivs
         ovals | isJust ivals = fn (fromJust ivals)
               | otherwise    = []
     in
-        fromMaybe [] $ mapM (rdfNodeInject dtval) ovals
-
--- |Extract datatyped value from 'RDFLabel' value, or return @Nothing@.
---
-rdfNodeExtract :: RDFDatatypeVal vt -> RDFLabel -> Maybe vt
-rdfNodeExtract dtval node
-    | isDatatyped dtname node = mapL2V dtmap $ getLiteralText node
-    | otherwise               = Nothing
-    where
-        dtname = tvalName dtval
-        dtmap  = tvalMap  dtval
-
--- |Return new RDF literal node with a representation of the supplied
---  value, or @Nothing@.
---
-rdfNodeInject :: RDFDatatypeVal vt -> vt -> Maybe RDFLabel
-rdfNodeInject dtval val = maybeNode valstr
-    where
-        valstr = mapV2L (tvalMap  dtval) val
-        maybeNode Nothing    = Nothing
-        maybeNode (Just str) = Just $ Lit str (Just (tvalName dtval))
+        fromMaybe [] $ mapM (toRDFLabel dtval) ovals
 
 ------------------------------------------------------------
 --  Helpers to map between datatype values and RDFLabels
 ------------------------------------------------------------
 
+-- | Convert from a typed literal to a Haskell value,
+-- with the possibility of failure.
 fromRDFLabel ::
     RDFDatatypeVal vt -> RDFLabel -> Maybe vt
 fromRDFLabel dtv lab
@@ -185,6 +167,8 @@
         dtnam = tvalName dtv
         dtmap = tvalMap dtv
 
+-- | Convert a Haskell value to a typed literal (label),
+-- with the possibility of failure.
 toRDFLabel :: RDFDatatypeVal vt -> vt -> Maybe RDFLabel
 toRDFLabel dtv =
     liftM (makeDatatypedLiteral dtnam) . mapV2L dtmap
@@ -192,6 +176,7 @@
         dtnam = tvalName dtv
         dtmap = tvalMap dtv
 
+-- | Create a typed literal from the given value.
 makeDatatypedLiteral :: ScopedName -> String -> RDFLabel
 makeDatatypedLiteral dtnam strval =
     Lit strval (Just dtnam)
diff --git a/Swish/RDF/RDFDatatypeXsdInteger.hs b/Swish/RDF/RDFDatatypeXsdInteger.hs
--- a/Swish/RDF/RDFDatatypeXsdInteger.hs
+++ b/Swish/RDF/RDFDatatypeXsdInteger.hs
@@ -10,8 +10,8 @@
 --  Stability   :  experimental
 --  Portability :  H98
 --
---  This module defines the structures used by swish to represent and
---  manipulate RDF datatypes.
+--  This module defines the structures used by Swish to represent and
+--  manipulate RDF @xsd:integer@ datatyped literals.
 --
 --------------------------------------------------------------------------------
 
@@ -155,10 +155,9 @@
 
 -- |relXsdInteger contains arithmetic and other relations for xsd:Integer values.
 --
---  The functions are inspired by those defined by CWM as math: properties.
---  (cf. http://www.w3.org/2000/10/swap/doc/CwmBuiltins.html)
+--  The functions are inspired by those defined by CWM as math: properties
+--  (<http://www.w3.org/2000/10/swap/doc/CwmBuiltins.html>).
 --
-
 relXsdInteger :: [DatatypeRel Integer]
 relXsdInteger =
     [ relXsdIntegerAbs
@@ -293,8 +292,8 @@
 -- |modXsdInteger contains variable binding modifiers for xsd:Integer values.
 --
 --  The functions are selected from those defined by CWM as math:
---  properties.
---  (cf. http://www.w3.org/2000/10/swap/doc/CwmBuiltins.html)
+--  properties
+--  (<http://www.w3.org/2000/10/swap/doc/CwmBuiltins.html>).
 --
 modXsdInteger :: [RDFDatatypeMod Integer]
 modXsdInteger =
diff --git a/Swish/RDF/RDFDatatypeXsdString.hs b/Swish/RDF/RDFDatatypeXsdString.hs
--- a/Swish/RDF/RDFDatatypeXsdString.hs
+++ b/Swish/RDF/RDFDatatypeXsdString.hs
@@ -10,8 +10,8 @@
 --  Stability   :  experimental
 --  Portability :  H98
 --
---  This module defines the structures used by swish to represent and
---  manipulate RDF xsd:string datatyped literals.
+--  This module defines the structures used by Swish to represent and
+--  manipulate RDF @xsd:string@ datatyped literals.
 --
 --------------------------------------------------------------------------------
 
diff --git a/Swish/RDF/RDFGraph.hs b/Swish/RDF/RDFGraph.hs
--- a/Swish/RDF/RDFGraph.hs
+++ b/Swish/RDF/RDFGraph.hs
@@ -79,7 +79,7 @@
     , rdfd_onProperties, rdfd_constraint, rdfd_maxCardinality
     , owl_sameAs, log_implies
     -- , xsd_type
-    , xsd_boolean, xsd_float, xsd_double, xsd_integer
+    , xsd_boolean, xsd_decimal, xsd_float, xsd_double, xsd_integer
     , xsd_dateTime, xsd_date                                                
     )
 
@@ -108,7 +108,7 @@
 import Network.URI (URI, parseURI, uriToString)
 
 import Data.Monoid (Monoid(..))
-import Data.Char (isDigit)
+import Data.Char (isDigit, toLower)
 import Data.List (intersect, union, findIndices)
 import Data.Ord (comparing)
 import Data.String (IsString(..))
@@ -116,7 +116,6 @@
 import System.Locale (defaultTimeLocale)  
 import Text.Printf
 
------------------------------------------------------------
 -- | RDF graph node values
 --
 --  cf. <http://www.w3.org/TR/rdf-concepts/#section-Graph-syntax>
@@ -136,10 +135,6 @@
 --  (c) a \"NoNode\" option is defined.
 --      This might otherwise be handled by @Maybe (RDFLabel g)@.
 --
-
--- TODO: should Lit be split up so that can easily differentiate between
--- a type and a language tag
-
 data RDFLabel =
       Res ScopedName                    -- ^ resource
     | Lit String (Maybe ScopedName)     -- ^ literal [type/language]
@@ -147,14 +142,33 @@
     | Var String                        -- ^ variable (not used in ordinary graphs)
     | NoNode                            -- ^ no node  (not used in ordinary graphs)
 
+-- TODO: should Lit be split up so that can easily differentiate between
+-- a type and a language tag?
+
+-- | Define equality of nodes possibly based on different graph types.
+--
+-- The equality of literals is taken from section 6.5.1 ("Literal
+-- Equality") of the RDF Concepts and Abstract Document,
+-- <http://www.w3.org/TR/2004/REC-rdf-concepts-20040210/#section-Literal-Equality>.
+--
 instance Eq RDFLabel where
-    (==) = labelEq
+    Res q1   == Res q2   = q1 == q2
+    Blank b1 == Blank b2 = b1 == b2
+    Var v1   == Var v2   = v1 == v2
 
+    Lit s1 Nothing   == Lit s2 Nothing   = s1 == s2
+    Lit s1 (Just t1) == Lit s2 (Just t2) = s1 == s2 && (t1 == t2 ||
+                                                        (isLang t1 && isLang t2 &&
+                                                         (map toLower . langTag) t1 == (map toLower . langTag) t2))
+    
+    _  == _ = False
+
 instance Show RDFLabel where
     show (Res sn)           = show sn
     show (Lit st Nothing)   = quote st
     show (Lit st (Just nam))
         | isLang nam = quote st ++ "@"  ++ langTag nam
+        | nam `elem` [xsd_boolean, xsd_double, xsd_decimal, xsd_integer] = st
         | otherwise  = quote st ++ "^^" ++ show nam
     show (Blank ln)         = "_:"++ln
     show (Var ln)           = '?' : ln
@@ -206,6 +220,9 @@
 canonical form described in section 2.3.1 of
 <http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#lexical-space>.
   
+Note that this is very similar to
+'Swish.RDF.RDFDatatype.toRDFLabel' and should be moved into
+a @Swish.RDF.Datatype@ module.
 -}
 
 class ToRDFLabel a where
@@ -233,6 +250,9 @@
 
  - @xsd:date@ to @Day@
 
+Note that this is very similar to
+'Swish.RDF.RDFDatatype.fromRDFLabel' and should be moved into
+a @Swish.RDF.Datatype@ module.
 -}
 
 class FromRDFLabel a where
@@ -277,15 +297,18 @@
   fromRDFLabel (Lit xs Nothing) = Just xs
   fromRDFLabel _ = Nothing
 
+-- | Converts to a literal with a @xsd:boolean@ datatype.
 instance ToRDFLabel Bool where
   toRDFLabel b = Lit (if b then "true" else "false") (Just xsd_boolean)
                                                  
+strToBool :: String -> Maybe Bool
+strToBool s | s `elem` ["1", "true"]  = Just True
+            | s `elem` ["0", "false"] = Just False
+            | otherwise               = Nothing
+
+-- | Converts from a literal with a @xsd:boolean@ datatype.
 instance FromRDFLabel Bool where
-  fromRDFLabel = fLabel conv xsd_boolean
-    where
-      conv s | s `elem` ["1", "true"]  = Just True
-             | s `elem` ["0", "false"] = Just False
-             | otherwise               = Nothing
+  fromRDFLabel = fLabel strToBool xsd_boolean
 
 fromRealFloat :: (RealFloat a, PrintfArg a) => ScopedName -> a -> RDFLabel
 fromRealFloat dtype f | isNaN f      = toL "NaN"
@@ -294,8 +317,8 @@
                         where
                           toL = flip Lit (Just dtype)
 
-toRealFloat :: (RealFloat a, Read a) => (a -> Maybe a) -> ScopedName -> RDFLabel -> Maybe a
-toRealFloat conv = fLabel rconv
+strToRealFloat :: (RealFloat a, Read a) => (a -> Maybe a) -> String -> Maybe a
+strToRealFloat conv = rconv
     where
       rconv "NaN"  = Just (0.0/0.0) -- how best to create a NaN?
       rconv "INF"  = Just (1.0/0.0) -- ditto for Infinity
@@ -306,23 +329,29 @@
         | last istr == '.' = maybeRead (istr ++ "0") >>= conv
         | otherwise        = maybeRead istr >>= conv
       
-instance ToRDFLabel Float where
-  toRDFLabel = fromRealFloat xsd_float
-  
-instance FromRDFLabel Float where
-  fromRDFLabel = toRealFloat conv xsd_float
-    where
-      -- assume that an invalid value (NaN/Inf) from maybeRead means
+strToFloat :: String -> Maybe Float
+strToFloat = 
+  let -- assume that an invalid value (NaN/Inf) from maybeRead means
       -- that the value is out of bounds for Float so we do not
       -- convert
       conv f | isNaN f || isInfinite f = Nothing
              | otherwise               = Just f
+  in strToRealFloat conv
+
+strToDouble :: String -> Maybe Double      
+strToDouble = strToRealFloat Just
+
+instance ToRDFLabel Float where
+  toRDFLabel = fromRealFloat xsd_float
+  
+instance FromRDFLabel Float where
+  fromRDFLabel = fLabel strToFloat xsd_float
                  
 instance ToRDFLabel Double where
   toRDFLabel = fromRealFloat xsd_double
   
 instance FromRDFLabel Double where
-  fromRDFLabel = toRealFloat Just xsd_double
+  fromRDFLabel = fLabel strToDouble xsd_double
   
 -- TODO: are there subtypes of xsd::integer that are  
 --       useful here?  
@@ -341,15 +370,19 @@
 we convert via Integer.
 -}
 
-instance FromRDFLabel Int where
-  fromRDFLabel = fLabel (\istr -> maybeRead istr >>= conv) xsd_integer
-    where
-      conv :: Integer -> Maybe Int
+strToInt :: String -> Maybe Int
+strToInt s = 
+  let conv :: Integer -> Maybe Int
       conv i = 
         let lb = fromIntegral (minBound :: Int)
             ub = fromIntegral (maxBound :: Int)
         in if (i >= lb) && (i <= ub) then Just (fromIntegral i) else Nothing
+  
+  in maybeRead s >>= conv
 
+instance FromRDFLabel Int where
+  fromRDFLabel = fLabel strToInt xsd_integer
+
 instance ToRDFLabel Integer where
   toRDFLabel = tLabel xsd_integer id
 
@@ -436,7 +469,7 @@
 --
 --  Used for hashing, so that equivalent labels always return
 --  the same hash value.
-    
+--    
 showCanon :: RDFLabel -> String
 showCanon (Res sn)           = "<"++getScopedNameURI sn++">"
 showCanon (Lit st (Just nam))
@@ -445,20 +478,6 @@
 showCanon s                  = show s
 
 
--- | Define equality of nodes possibly based on different graph types.
---
--- The version of equality defined here is not strictly RDF abstract syntax
--- equality, but my interpretation of equivalence for the purposes of
--- entailment, in the absence of any specific datatype knowledge other
--- than XML literals.
---
-labelEq :: RDFLabel -> RDFLabel -> Bool
-labelEq (Res q1)            (Res q2)        = q1 == q2
-labelEq (Blank s1)          (Blank s2)      = s1 == s2
-labelEq (Var v1)            (Var v2)        = v1 == v2
-labelEq (Lit s1 t1)         (Lit s2 t2)     = s1 == s2 && t1 == t2
-labelEq _                   _               = False
-
 ---------------------------------------------------------
 --  Selected RDFLabel values
 ---------------------------------------------------------
@@ -682,18 +701,21 @@
 getNamespaces :: NSGraph lb -> NamespaceMap
 getNamespaces = namespaces
 
+-- | Replace the namespace information in the graph.
 setNamespaces      :: NamespaceMap -> NSGraph lb -> NSGraph lb
 setNamespaces ns g = g { namespaces=ns }
 
 getFormulae :: NSGraph lb -> FormulaMap lb
 getFormulae = formulae
 
+-- | Replace the formulae in the graph.
 setFormulae      :: FormulaMap lb -> NSGraph lb -> NSGraph lb
 setFormulae fs g = g { formulae=fs }
 
 getFormula     :: (Label lb) => NSGraph lb -> lb -> Maybe (NSGraph lb)
 getFormula g l = mapFindMaybe l (formulae g)
 
+-- | Add (or replace) a formula.
 setFormula     :: (Label lb) => Formula lb -> NSGraph lb -> NSGraph lb
 setFormula f g = g { formulae=mapReplaceOrAdd f (formulae g) }
 
@@ -706,7 +728,8 @@
     setArcs as g = g { statements=as }
     containedIn = error "containedIn for LDGraph NSGraph lb is undefined!" -- TODO: should there be one defined?
 
--- Optimized method to add arc .. don't check for duplicates.
+-- | Add an arc to the graph. It does not check for duplicates
+-- nor does it relabel any blank nodes in the input arc.
 addArc :: (Label lb) => Arc lb -> NSGraph lb -> NSGraph lb
 addArc ar gr = gr { statements=addSetElem ar (statements gr) }
 
@@ -751,7 +774,7 @@
         pp = "\n    " ++ p
 
 grEq :: (Label lb) => NSGraph lb -> NSGraph lb -> Bool
-grEq g1 g2 = fst ( grMatchMap g1 g2 )
+grEq g1 = fst . grMatchMap g1
 
 grMatchMap :: (Label lb) =>
     NSGraph lb -> NSGraph lb -> (Bool, LabelMap (ScopedLabel lb))
@@ -765,7 +788,8 @@
 --  needed to neep variable nodes from the two graphs distinct in
 --  the resulting graph.
 --        
---  Currently formulae are not preserved across a merge.
+--  Currently formulae are not guaranteed to be preserved across a
+--  merge.
 --        
 merge :: (Label lb) => NSGraph lb -> NSGraph lb -> NSGraph lb
 merge gr1 gr2 =
diff --git a/swish.cabal b/swish.cabal
--- a/swish.cabal
+++ b/swish.cabal
@@ -1,5 +1,5 @@
 Name:               swish
-Version:            0.3.1.0
+Version:            0.3.1.1
 Stability:          experimental
 License:            LGPL
 License-file:       LICENSE 
@@ -45,6 +45,19 @@
   * Complete, ready-to-run, command-line and script-driven programs.
   .
   Major Changes:
+  .
+  [Version 0.3.1.1] Bug fixes for N3 format: strings ending in a 
+  double quote character are now written out correctly and
+  @xsd:double@ values are not written using XSD canonical form/capital
+  @E@ but with a lower-case @e@. On input of N3,
+  literals that match @xsd:double@ are converted to XSD canonical form
+  (as stored in 'RDFLabel'), which can make simple textual comparison
+  of literals fail. The 'Eq' instance of 'RDFLabel' now ignores the
+  case of the language tag for literals and the 'Show' instance 
+  uses XSD canonical form for @xsd:boolean@, @xsd:integer@,
+  @xsd:decimal@ and @xsd:double@ literals. 
+  Noted that the 'ToRDFLable' and 'FromRDFLabel' classes replicate
+  existing functionality in the "Swish.RDF.RDFDatatype" module.
   .
   [Version 0.3.1.0] Added the `Swish.RDF.RDFGraph.ToRDFLabel` and
   `Swish.RDF.RDFGraph.FromRDFLabel` classes and the 
diff --git a/tests/N3FormatterTest.hs b/tests/N3FormatterTest.hs
--- a/tests/N3FormatterTest.hs
+++ b/tests/N3FormatterTest.hs
@@ -25,12 +25,11 @@
 
 import Swish.RDF.RDFGraph
     ( RDFGraph
-    , RDFLabel(..), ToRDFLabel(..)
+    , RDFLabel(..)
     , NSGraph(..)
     , NamespaceMap
     , LookupFormula(..)
-    , emptyRDFGraph, toRDFGraph
-      -- Export selected RDFLabel values
+    , emptyRDFGraph, toRDFGraph, toRDFTriple
     , res_rdf_type, res_rdf_first, res_rdf_rest, res_rdf_nil
     , res_owl_sameAs
     )
@@ -45,6 +44,9 @@
 
 import Swish.RDF.Vocabulary (langName)
 
+import Data.Monoid (Monoid(..))
+import Data.String (IsString(..))
+
 import Test.HUnit
     ( Test(TestCase,TestList)
     , assertEqual, runTestTT )
@@ -630,16 +632,26 @@
 
 -- datatype/literal graphs
 
-graph_l1, graph_l2, graph_l3 :: RDFGraph
+graph_l1, graph_l2, graph_l3, graph_l4 :: RDFGraph
 graph_l1 = toGraph [arc s1 p1 lfr]
 graph_l2 = toGraph [arc s1 p1 lfoobar]
 graph_l3 = 
-  let gtmp = toGraph [arc s1 p1 (toRDFLabel (12::Int)),
-                      arc s1 p1 (toRDFLabel (23.4::Float)),
-                      arc s1 p1 (toRDFLabel ((-2.304e-108)::Double)),
-                      arc s1 p1 (toRDFLabel True)
-                      ]
+  let tf a = toRDFTriple s1 p1 a
+      gtmp = toGraph [ tf True
+                     , tf (12::Int)
+                       
+                       -- so, issue over comparing -2.304e-108 and value read in from string
+                       -- due to comparing a ScopedName instance built from a RDFLabel
+                       -- as the hash used in the comparison is based on the Show value
+                       -- but then why isn't this a problem for Float
+                       
+                     , tf ((-2.304e-108)::Double)
+                     , tf (23.4::Float)  
+                     ]
   in gtmp { namespaces = mapAdd (namespaces gtmp) (Namespace "xsd" "http://www.w3.org/2001/XMLSchema#") }
+graph_l4 = toGraph [ toRDFTriple s1 p1 "A string with \"quotes\""
+                   , toRDFTriple s2 p2 (Lit "A typed string with \"quotes\"" (Just (fromString "urn:a#b")))
+                   ]                    
                     
 ------------------------------------------------------------
 --  Trivial formatter tests
@@ -868,11 +880,17 @@
 simpleN3Graph_l3 =
   "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" ++ 
   commonPrefixes ++ 
-  "\n" ++ -- TODO: why do we need this?
-  "base1:s1 base1:p1 -2.304E-108,\n" ++ 
-  "                  12,\n" ++ 
-  "                  \"2.34E1\"^^xsd:float,                  true .\n"
-  
+  "\n" ++ -- TODO: why do we need this newline?
+  "base1:s1 base1:p1 \"2.34E1\"^^xsd:float,\n" ++ 
+  "                  -2.304e-108,\n" ++ 
+  "                  12,                  true .\n"
+
+simpleN3Graph_l4 :: String
+simpleN3Graph_l4 =
+  commonPrefixes ++
+  "base1:s1 base1:p1 \"\"\"A string with \"quotes\\\"\"\"\" .\n" ++
+  "base2:s2 base2:p2 \"\"\"A typed string with \"quotes\\\"\"\"\"^^<urn:a#b> .\n"
+
 trivialTestSuite :: Test
 trivialTestSuite = TestList
  [ formatTest "trivialTest01" g1np simpleN3Graph_g1_01
@@ -904,6 +922,7 @@
  , formatTest "lit1"   graph_l1   simpleN3Graph_l1  
  , formatTest "lit2"   graph_l2   simpleN3Graph_l2
  , formatTest "lit3"   graph_l3   simpleN3Graph_l3
+ , formatTest "lit4"   graph_l4   simpleN3Graph_l4
    
  , formatTest "trivialTestx4" x4 exoticN3Graph_x4
  , formatTest "trivialTestx5" x5 exoticN3Graph_x5
@@ -962,8 +981,8 @@
     where
         out     = formatGraphAsString gr
         (pe,pg) = case parseN3fromString out of
-            Right g -> ("",g)
-            Left  s -> (s,emptyRDFGraph)
+            Right g -> ("", g)
+            Left  s -> (s, mempty)
 
 --  Full round trip from graph source.  This test may pick up some errors
 --  the bnode generation logic that are not tested by hand-assembled graph
@@ -977,12 +996,12 @@
       ]
     where
         (_,gr) = case parseN3fromString grstr of
-            Right g -> ("",g)
-            Left  s -> (s,emptyRDFGraph)
+            Right g -> ("", g)
+            Left  s -> (s, mempty)
         out     = formatGraphAsString gr
         (pe,pg) = case parseN3fromString out of
-            Right g -> ("",g)
-            Left  s -> (s,emptyRDFGraph)
+            Right g -> ("", g)
+            Left  s -> (s, mempty)
 
 roundTripTestSuite :: Test
 roundTripTestSuite = TestList
@@ -996,6 +1015,7 @@
   , roundTripTest "l1"    graph_l1
   , roundTripTest "l2"    graph_l2
   , roundTripTest "l3"    graph_l3
+  , roundTripTest "l4"    graph_l4
       
     -- roundTripTest07 = roundTripTest "07" g1f1 -- formula is a named node
   , roundTripTest "08" g1f2
@@ -1008,6 +1028,11 @@
     -- roundTripTest17 = fullRoundTripTest "17" simpleN3Graph_g1_07 -- TODO: :- with named node for formula
   , fullRoundTripTest "18" simpleN3Graph_g1_08
   
+  , fullRoundTripTest "l1"    simpleN3Graph_l1
+  , fullRoundTripTest "l2"    simpleN3Graph_l2
+  , fullRoundTripTest "l3"    simpleN3Graph_l3
+  , fullRoundTripTest "l4"    simpleN3Graph_l4
+      
   ]
 
 ------------------------------------------------------------
diff --git a/tests/N3ParserTest.hs b/tests/N3ParserTest.hs
--- a/tests/N3ParserTest.hs
+++ b/tests/N3ParserTest.hs
@@ -1191,7 +1191,7 @@
 bOne  = Lit "1" $ Just xsd_integer
 b20   = Lit "2.0" $ Just xsd_decimal
 b221  = Lit "-2.21" $ Just xsd_decimal
-b23e4 = Lit "-2.3e-4" $ Just xsd_double
+b23e4 = Lit "-2.3E-4" $ Just xsd_double
 
 lit_g4 :: RDFGraph
 lit_g4 = mempty {
