diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/pangraph.cabal b/pangraph.cabal
new file mode 100644
--- /dev/null
+++ b/pangraph.cabal
@@ -0,0 +1,48 @@
+name:                 pangraph
+version:              0.1.1.5
+synopsis:             A set of parsers for graph languages.
+description:          A package allowing parsing of graph files into graph library datatypes. With aim the cope with large networks and provide translations between graph libraries. Like a pandoc but for graphs. This is my first library so any feedback and help is appreicated. For example use please see the homepage.
+homepage:             https://github.com/tuura/pangraph#readme
+license:              BSD3
+license-file:         LICENSE
+author:               Joe Scott
+maintainer:           joseph-scott@hotmail.co.uk
+copyright:            2017 Joe Scott
+category:             graphs, library, data-structures, parser, xml
+build-type:           Simple
+cabal-version:        >=1.10
+tested-with:          GHC==8.0.2
+
+library
+  hs-source-dirs:     src
+  exposed-modules:    Pangraph
+                   ,  Pangraph.Containers
+                   ,  Pangraph.GraphML.Parser
+                   ,  Pangraph.GraphML.Writer
+                   ,  Pangraph.Internal.XMLTemplate
+                   ,  Pangraph.Examples.Reading
+                   ,  Pangraph.Examples.Writing
+                   ,  Pangraph.Examples.ToContainersGraph
+                   ,  Pangraph.Examples.SampleGraph
+  build-depends:      base >= 4.8 && < 5
+                   ,  bytestring
+                   ,  hexml
+                   ,  containers
+                   ,  algebraic-graphs
+  default-language:   Haskell2010
+  GHC-options:        -Wall -fwarn-tabs
+
+test-suite pangraph-test
+  type:               exitcode-stdio-1.0
+  hs-source-dirs:     test
+  main-is:            Main.hs
+  other-modules:      Show
+                   ,  GraphML
+                   ,  Containers
+  build-depends:      base >= 4.8 && < 5
+                   ,  pangraph
+                   ,  bytestring
+                   ,  HUnit
+                   ,  containers
+  default-language:   Haskell2010
+  GHC-options:        -Wall -fwarn-tabs -fbreak-on-exception
diff --git a/src/Pangraph.hs b/src/Pangraph.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph.hs
@@ -0,0 +1,142 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Pangraph (
+    -- * Abstract Types
+    Pangraph, Edge, Vertex, Attribute,
+    Key, Value, VertexID, EdgeID,
+
+    -- * Constructors
+    makePangraph, makeEdge, makeVertex,
+
+    -- * Pangraph Getters
+    edgeList, vertexList, lookupVertex, lookupEdge,
+
+    -- * Getters on Vertex and Edge
+    edgeAttributes, vertexAttributes,
+    edgeEndpoints, edgeID, vertexID
+
+) where
+
+import Data.Maybe            (mapMaybe)
+import Data.Map.Strict       (Map)
+import qualified Data.Map.Strict  as Map
+import qualified Data.ByteString  as BS
+import qualified Algebra.Graph.Class as Alga
+
+-- | The 'Pangraph' type is the core intermediate type between abstract representations of graphs.
+data Pangraph = Pangraph
+  { vertices' :: Map VertexID Vertex
+  , edges' :: Map EdgeID Edge
+  } deriving (Eq)
+-- | A Vertex holds ['Attribute'] and must have a unique 'VertexID' to be constructed with 'makeVertex'.
+data Vertex = Vertex
+  { vertexID' :: VertexID
+  , vertexAttributes' :: [Attribute]
+  } deriving (Eq)
+-- | Edges also reqiure ['Attribute'] and a tuple of 'Vertex' passed as connections to be constructed with 'makeEdge'
+data Edge = Edge
+  { edgeID' :: Maybe EdgeID
+  , edgeAttributes' :: [Attribute]
+  , endpoints' :: (Vertex, Vertex)
+  } deriving (Eq)
+
+-- | A type exposed for lookup in the resulting lists.
+type EdgeID = Int
+-- | A field that is Maybe internally is exposed for lookup.
+type VertexID = BS.ByteString
+-- | The type alias for storage of fields.
+type Attribute = (Key, Value)
+-- | The 'Key' in the tuple that makes up 'Attribute'.
+type Key = BS.ByteString
+-- | The 'Value' in the tuple that makes up 'Attribute'.
+type Value = BS.ByteString
+
+type MalformedEdge = (Edge, (Maybe Vertex, Maybe Vertex))
+
+instance Show Pangraph where
+  show p = "makePangraph " ++ show (Map.elems (vertices' p)) ++ " " ++ show (Map.elems (edges' p))
+
+instance Show Vertex where
+  show (Vertex i as) = unwords ["makeVertex", show i, show as]
+
+instance Show Edge where
+  show (Edge _ as e) = unwords ["makeEdge", show as, show e]
+
+instance Alga.ToGraph Pangraph where
+    type ToVertex Pangraph = Vertex
+    toGraph p = Alga.graph (vertexList p) (map edgeEndpoints $ edgeList p)
+
+-- * List based constructors
+
+-- | Takes lists of 'Vertex' and 'Edge' to produce 'Just Pangraph' if the graph is correctly formed.
+makePangraph :: [Vertex] -> [Edge] -> Maybe Pangraph
+makePangraph vs es = case verifyGraph vertexMap es of
+  [] -> Just $ Pangraph vertexMap edgeMap
+  _ -> Nothing
+  where
+    vertexMap :: Map VertexID Vertex
+    vertexMap = Map.fromList $ zip (map vertexID vs) vs
+    edgeMap :: Map EdgeID Edge
+    edgeMap = Map.fromList indexEdges
+    indexEdges :: [(EdgeID, Edge)]
+    indexEdges = map (\ (i, Edge _ as a) -> (i, Edge (Just i) as a )) $ zip [0..] es
+
+verifyGraph :: Map VertexID Vertex -> [Edge] -> [MalformedEdge]
+verifyGraph vs = mapMaybe (\e -> lookupEndpoints (e, edgeEndpoints e))
+  where
+    lookupEndpoints :: (Edge, (Vertex, Vertex)) ->  Maybe MalformedEdge
+    lookupEndpoints (e, (v1,v2)) =
+      case (Map.lookup (vertexID v1) vs, Map.lookup (vertexID v2) vs) of
+        (Just _ , Just _)  -> Nothing
+        (Nothing, Just _)  -> Just (e, (Just v1, Nothing))
+        (Just _ , Nothing) -> Just (e, (Nothing, Just v2))
+        (Nothing, Nothing) -> Just (e, (Just v1, Just v2))
+
+-- | Edge constructor
+makeEdge :: [Attribute] -> (Vertex, Vertex) -> Edge
+makeEdge = Edge Nothing
+
+-- | Vertex constructor
+makeVertex :: VertexID -> [Attribute] -> Vertex
+makeVertex = Vertex
+
+-- * Pangraph Getters
+
+-- | Returns the ['Edge'] from a 'Pangraph' instance
+edgeList :: Pangraph -> [Edge]
+edgeList p = Map.elems $ edges' p
+
+-- | Returns the ['Vertex'] from a 'Pangraph' instance
+vertexList :: Pangraph -> [Vertex]
+vertexList p = Map.elems $ vertices' p
+
+-- | Lookup of the 'EdgeID' in a 'Pangraph'. Complexity: /O(log n)/
+lookupEdge :: EdgeID -> Pangraph -> Maybe Edge
+lookupEdge key p = Map.lookup key $ edges' p
+
+-- | Lookup of the 'VertexID' in a 'Pangraph'. Complexity: /O(log n)/
+lookupVertex :: VertexID -> Pangraph -> Maybe Vertex
+lookupVertex key p = Map.lookup key $ vertices' p
+
+-- * Getters on 'Edge' and 'Vertex'
+
+-- | Returns the ['Attribute'] of an 'Edge'
+edgeAttributes :: Edge -> [Attribute]
+edgeAttributes = edgeAttributes'
+
+-- | Returns the ['Attribute'] list of an 'Edge'
+vertexAttributes :: Vertex -> [Attribute]
+vertexAttributes = vertexAttributes'
+
+-- | Returns the endpoint of tupled 'Vertex' of an 'Edge'
+edgeEndpoints :: Edge -> (Vertex, Vertex)
+edgeEndpoints = endpoints'
+
+-- | Returns the EdgeID if it has one. 'Edge's are given a new 'EdgeID' when they are passed and retrived from a 'Pangraph'
+edgeID :: Edge -> Maybe EdgeID
+edgeID = edgeID'
+
+-- | Returns a 'VertexID'
+vertexID :: Vertex -> VertexID
+vertexID = vertexID'
diff --git a/src/Pangraph/Containers.hs b/src/Pangraph/Containers.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Containers.hs
@@ -0,0 +1,39 @@
+module Pangraph.Containers
+    ( convert
+    ) where
+
+import Pangraph
+import qualified Data.Graph as CGraph
+
+import Data.Maybe       (fromMaybe)
+import Data.List        (groupBy, sort)
+import Control.Arrow    ((***))
+
+import Data.Map.Strict  (Map)
+import qualified Data.Map.Strict as Map
+
+-- | Transforms a 'Pangraph' in a 'CGraph.Graph'.
+convert :: Pangraph -> (CGraph.Graph, CGraph.Vertex -> (Vertex, VertexID, [VertexID]), VertexID -> Maybe CGraph.Vertex)
+convert p = CGraph.graphFromEdges getVertices
+  where
+    -- A helper function for getting the IDs of endpoints.
+    edgeEndpointIDs :: Edge -> (VertexID, VertexID)
+    edgeEndpointIDs e = (vertexID *** vertexID) $ edgeEndpoints e
+
+    -- Create an Edge Map using VertexID grouping edge sources together.
+    edgeMap :: Map VertexID [VertexID]
+    edgeMap = (Map.fromList . groupIDs) $ map edgeEndpointIDs $ edgeList p
+
+    -- Lookup the edges for this vertex. Returning empty list on Nothing.
+    vertexConnections :: Vertex -> [VertexID]
+    vertexConnections v = fromMaybe [] (Map.lookup (vertexID v) edgeMap)
+
+    -- Convert Pangraph Vertex into a form ready to collect Edges from the Pangraph
+    getVertices :: [(Vertex, VertexID, [VertexID])]
+    getVertices = map (\v ->(v, vertexID v, vertexConnections v)) $ vertexList p
+
+groupIDs :: [(VertexID, VertexID)] -> [(VertexID, [VertexID])]
+groupIDs vs = map (\ts -> (fst $ head ts, map snd ts)) groupedEdges
+  where
+    groupedEdges :: [[(VertexID, VertexID)]]
+    groupedEdges = groupBy (\a b -> fst a == fst b) $ sort vs
diff --git a/src/Pangraph/Examples/Reading.hs b/src/Pangraph/Examples/Reading.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Examples/Reading.hs
@@ -0,0 +1,13 @@
+module Pangraph.Examples.Reading where
+
+import Prelude hiding (readFile)
+
+import Data.ByteString (readFile)
+
+import qualified Pangraph.GraphML.Parser as GraphML
+
+main :: IO ()
+main = do
+  fileName <- getLine
+  file <- readFile fileName
+  print (GraphML.parse file)
diff --git a/src/Pangraph/Examples/SampleGraph.hs b/src/Pangraph/Examples/SampleGraph.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Examples/SampleGraph.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Pangraph.Examples.SampleGraph
+    ( smallGraph
+    ) where
+
+import Pangraph
+
+smallGraph :: Pangraph
+smallGraph = case graph of
+  Just p  -> p
+  Nothing -> error "Small graph literal failed to construct."
+  where
+    graph =
+      makePangraph
+        [makeVertex "n0" [("id","n0")]
+        ,makeVertex "n1" [("id","n1")]
+        ,makeVertex "n2" [("id","n2")]]
+        [makeEdge [("source","n0"),("target","n2")]
+          (makeVertex "n0" [("id","n0")]
+          ,makeVertex "n2" [("id","n2")])]
diff --git a/src/Pangraph/Examples/ToContainersGraph.hs b/src/Pangraph/Examples/ToContainersGraph.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Examples/ToContainersGraph.hs
@@ -0,0 +1,9 @@
+module Pangraph.Examples.ToContainersGraph where
+
+import Pangraph.Containers(convert)
+import Pangraph.Examples.SampleGraph(smallGraph)
+
+main :: IO ()
+main =
+  -- Transform to Containers Data.Graph and print.
+  print $ ((\(a,_,_) -> a) . convert) smallGraph
diff --git a/src/Pangraph/Examples/Writing.hs b/src/Pangraph/Examples/Writing.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Examples/Writing.hs
@@ -0,0 +1,8 @@
+module Pangraph.Examples.Writing where
+
+import Pangraph.GraphML.Writer(write)
+import Pangraph.Examples.SampleGraph(smallGraph)
+
+main :: IO ()
+main =
+  print $ write smallGraph
diff --git a/src/Pangraph/GraphML/Parser.hs b/src/Pangraph/GraphML/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/GraphML/Parser.hs
@@ -0,0 +1,20 @@
+module Pangraph.GraphML.Parser (
+parse,
+unsafeParse
+) where
+
+import Data.Maybe
+import qualified Data.ByteString            as BS
+import qualified Pangraph                   as P
+import qualified Text.XML.Hexml as H
+import qualified Pangraph.Internal.XMLTemplate       as PT
+
+-- * Parsing
+
+-- | Returns 'Pangraph' if it can be parsed from a raw GraphML file.
+parse :: BS.ByteString -> Maybe P.Pangraph
+parse file = either (const Nothing) (PT.hexmlToPangraph PT.graphMLTemplate) (H.parse file)
+
+-- | Like 'parse' except it throws an error on Nothing, which is when parsing fails.
+unsafeParse :: BS.ByteString -> P.Pangraph
+unsafeParse file = fromMaybe (error "Parse failed") (parse file)
diff --git a/src/Pangraph/GraphML/Writer.hs b/src/Pangraph/GraphML/Writer.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/GraphML/Writer.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Pangraph.GraphML.Writer
+( write
+) where
+
+import Pangraph
+import Prelude hiding(concat)
+import Data.ByteString(ByteString, append, concat)
+import Data.ByteString.Char8(pack)
+
+
+-- | Serialise a 'Pangraph' into a GraphML file producing a 'ByteString'.
+write :: Pangraph -> ByteString
+write p = concat $
+    writeHeader  0 :
+    writeGraphML 0 :
+    writeGraphTag 1 :
+    [] ++
+    map (writeNode 2) (vertexList p) ++
+    map (writeEdge 2) (edgeList p) ++
+    [closingTags]
+
+writeHeader :: Int -> ByteString
+writeHeader _ = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+
+writeGraphML :: Int -> ByteString
+writeGraphML _ = "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" \
+  \xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+
+writeGraphTag :: Int -> ByteString
+writeGraphTag i = getIndentBS i `append` "<graph id=\"G\" edgedefault=\"undirected\">\n"
+
+writeNode :: Int -> Vertex -> ByteString
+writeNode i v = concat [getIndentBS i, "<node", nodesAtts, "/>\n"]
+  where
+    nodesAtts :: ByteString
+    nodesAtts = concat $ map writeAttribute (vertexAttributes v)
+
+writeEdge :: Int -> Edge -> ByteString
+writeEdge i e = concat [getIndentBS i, "<edge", edgeAtts, "/>\n"]
+  where
+    edgeAtts :: ByteString
+    edgeAtts = concat $ map writeAttribute (edgeAttributes e)
+
+writeAttribute :: Attribute -> ByteString
+writeAttribute (a,b) = concat [" ",  a, "=\"",  b, "\""]
+
+closingTags :: ByteString
+closingTags = append (getIndentBS 1) $ append "</graph>\n" "</graphml>"
+
+-- Where i is the level of indentation.
+getIndentBS :: Int -> ByteString
+getIndentBS i = pack $ replicate (2*i) ' '
diff --git a/src/Pangraph/Internal/XMLTemplate.hs b/src/Pangraph/Internal/XMLTemplate.hs
new file mode 100644
--- /dev/null
+++ b/src/Pangraph/Internal/XMLTemplate.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Pangraph.Internal.XMLTemplate
+( Template,
+  graphMLTemplate,
+  hexmlToPangraph
+) where
+
+import Data.Maybe
+
+import qualified Pangraph as P
+
+import qualified Text.XML.Hexml as H
+import qualified Data.ByteString as BS
+
+-- A list of places to find vertices and extractEdges.
+data Template = XML [VertexRule] [EdgeRule]
+-- A list of the locations of tags and which elements to take from them.
+newtype EdgeRule = EdgeRule [(Path, Element)]
+newtype VertexRule = VertexRule [(Path, Element)]
+
+type Path = [BS.ByteString]
+type Element = [BS.ByteString]
+type HexmlVertex = H.Node
+
+-- A template for graphML, it extracts the vertices and edges.
+graphMLTemplate :: Template
+graphMLTemplate = XML
+  [VertexRule [( ["graphml", "graph", "node"], ["id"])]]
+  [EdgeRule [( ["graphml", "graph", "edge"], ["source", "target"] )]]
+
+hexmlToPangraph :: Template -> HexmlVertex -> Maybe P.Pangraph
+hexmlToPangraph (XML nt et) root = P.makePangraph n e
+  where
+    -- Map all the given rules over the XML tree for vertices
+    n = concatMap (extractVertices root "id") nt
+    -- Map all the given rules over the XML tree for edges
+    e = concatMap (extractEdges (assocVertices n) root ) et
+    assocVertices :: [P.Vertex] -> [(P.VertexID, P.Vertex)]
+    assocVertices vs = zip (map P.vertexID vs) vs
+
+-- Applies the Vertex rule to the Hexml root node, returning a list of pangraph vertices found.
+extractVertices :: HexmlVertex -> BS.ByteString -> VertexRule -> [P.Vertex]
+extractVertices hexml idElement (VertexRule pe) = concatMap (makeVertex hexml idElement) pe
+
+makeVertex :: HexmlVertex -> BS.ByteString -> (Path, Element) -> [P.Vertex]
+makeVertex hexml idElement (path, element) = map (\as -> P.makeVertex (idElem as) as) attList
+  where
+    idElem :: [P.Attribute] -> P.VertexID
+    idElem list =  fromMaybe (error $ "Fatal: node missing id value: " ++ show list)
+      (lookup idElement list)
+
+
+    attList :: [[P.Attribute]]
+    attList = map (getAttributePairs element) $ resolvePath path hexml
+
+-- Applies the edge rule to the Hexml root edge, returning a list of pangraph extractEdges found.
+extractEdges:: [(P.VertexID, P.Vertex)] -> HexmlVertex -> EdgeRule -> [P.Edge]
+extractEdges verticesAssoc hexml (EdgeRule pe) = concatMap (makeEdge verticesAssoc hexml) pe
+
+makeEdge :: [(P.VertexID, P.Vertex)] ->  HexmlVertex -> (Path, Element) -> [P.Edge]
+makeEdge verticesAssoc hexml (path, element) = map (\as -> P.makeEdge as (getPrimitives as)) attList
+  where
+    getPrimitives :: [P.Attribute] -> (P.Vertex, P.Vertex)
+    getPrimitives list = case (lookup src list, lookup dst list) of
+      (Just srcID, Just dstID) ->
+        case (lookup srcID verticesAssoc, lookup dstID verticesAssoc) of
+          (Just vertexSrc, Just vertexDst) -> (vertexSrc, vertexDst)
+          _ -> error $ "Fatal: Edge endpoints are not vertices: " ++ show list
+      _ -> error $ "Fatal: Edge endpoints not found in attribute list: " ++ show list
+    attList :: [[P.Attribute]]
+    attList = map (getAttributePairs element) $ resolvePath path hexml
+    src = "source"
+    dst = "target"
+
+resolvePath:: Path -> HexmlVertex -> [HexmlVertex]
+resolvePath [] h = [h]
+resolvePath bs h = concatMap (resolvePath (tail bs)) children
+  where
+    children :: [HexmlVertex]
+    children = H.childrenBy h $ head bs
+
+getAttributePairs:: Element -> HexmlVertex -> [P.Attribute]
+getAttributePairs e h = map toAttribute $  mapMaybe (H.attributeBy h) e
+  where
+    toAttribute :: H.Attribute -> P.Attribute
+    toAttribute a = (H.attributeName a, H.attributeValue a)
diff --git a/test/Containers.hs b/test/Containers.hs
new file mode 100644
--- /dev/null
+++ b/test/Containers.hs
@@ -0,0 +1,13 @@
+module Containers
+    ( containersTests
+    ) where
+
+import Test.HUnit
+import Pangraph.Examples.SampleGraph(smallGraph)
+import Pangraph.Containers(convert)
+
+containersTests :: [Test]
+containersTests = [case1]
+
+case1 :: Test
+case1 = TestCase $ assertEqual "Containers Convert case 1" ("array (0,2) [(0,[2]),(1,[]),(2,[])]") $ (show . (\(a,_,_) -> a) . convert) smallGraph
diff --git a/test/GraphML.hs b/test/GraphML.hs
new file mode 100644
--- /dev/null
+++ b/test/GraphML.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module GraphML (
+graphmlTests
+) where
+
+import Test.HUnit
+
+import Data.Maybe
+
+import Pangraph
+import Pangraph.GraphML.Parser
+import Pangraph.GraphML.Writer
+
+graphmlTests :: [Test]
+graphmlTests = [case1, case2]
+
+case1 :: Test
+case1 =
+  let
+    file = parse "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
+            \<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\
+            \    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\
+            \    xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\
+            \     http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\
+            \  <graph id=\"G\" edgedefault=\"undirected\">\
+            \    <node id=\"n0\"/>\
+            \    <node id=\"n1\"/>\
+            \    <node id=\"n2\"/>\
+            \    <edge id=\"e1\" source=\"n0\" target=\"n2\"/>\
+            \    </graph>\
+            \</graphml>"
+    sampleVertices = [
+                      makeVertex "n0" [ ("id","n0")],
+                      makeVertex "n1" [ ("id","n1")],
+                      makeVertex "n2" [ ("id","n2")]]
+    graph = makePangraph sampleVertices
+      [makeEdge
+        [("source","n0"),("target","n2")]
+        (head sampleVertices, sampleVertices !! 2)]
+  in TestCase $ assertEqual "GraphML Parse case 1" (graph :: Maybe Pangraph) file
+
+case2 :: Test
+case2 =
+  let
+    sampleVertices = [
+                      makeVertex "n0" [ ("id","n0")],
+                      makeVertex "n1" [ ("id","n1")],
+                      makeVertex "n2" [ ("id","n2")]]
+    graph = makePangraph sampleVertices
+      [makeEdge
+        [("source","n0"),("target","n2")]
+        (head sampleVertices, sampleVertices !! 2)]
+    justGraph = fromMaybe (error "Sample graph failed to compile") graph
+  in TestCase $ assertEqual "GraphML Write case 1" (graph :: Maybe Pangraph) (parse $ write justGraph)
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,10 @@
+module Main where
+
+import GraphML
+import Show
+import Containers
+
+import Test.HUnit
+
+main :: IO Counts
+main = runTestTT $ TestList $ concat [graphmlTests, showTests, containersTests]
diff --git a/test/Show.hs b/test/Show.hs
new file mode 100644
--- /dev/null
+++ b/test/Show.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Show (
+showTests
+) where
+
+import Data.Maybe
+import Test.HUnit
+import Pangraph
+
+
+showTests :: [Test]
+showTests = [case1]
+
+case1 :: Test
+case1 =
+  let
+    literal = "makePangraph [makeVertex \"0\" \
+    \[(\"id\",\"0\")],makeVertex \"1\" \
+    \[(\"id\",\"1\")]] [makeEdge \
+    \[(\"source\",\"0\"),(\"target\",\"1\")] \
+    \(makeVertex \"0\" \
+    \[(\"id\",\"0\")],makeVertex \"1\" [(\"id\",\"1\")])]"
+    sampleVertices = [makeVertex "0" [("id","0")]
+                     ,makeVertex "1" [ ("id","1")]]
+    graph = show $ fromMaybe
+             (error "Sample graph failed to build") $
+             makePangraph
+               sampleVertices [
+               makeEdge
+                 [("source","0"), ("target","1")]
+                 (head sampleVertices, sampleVertices !! 1)
+             ]
+  in TestCase $ assertEqual "Show instance case 1" literal (graph :: String)
