diff --git a/Data/Geo/OSM.hs b/Data/Geo/OSM.hs
--- a/Data/Geo/OSM.hs
+++ b/Data/Geo/OSM.hs
@@ -1,80 +1,127 @@
+-- | OpenStreetMap API v0.6 DTD <http://wiki.openstreetmap.org/wiki/API_v0.6/DTD>
 module Data.Geo.OSM(
                 module Text.XML.HXT.Arrow,
+                module Data.Geo.OSM.Api,
+                module Data.Geo.OSM.Area,
                 module Data.Geo.OSM.Bound,
                 module Data.Geo.OSM.Bounds,
+                module Data.Geo.OSM.ChangesetE,
+                module Data.Geo.OSM.GpxFile,
+                module Data.Geo.OSM.Home,
                 module Data.Geo.OSM.Member,
                 module Data.Geo.OSM.MemberType,
                 module Data.Geo.OSM.Nd,
                 module Data.Geo.OSM.Node,
                 module Data.Geo.OSM.NodeWayRelation,
                 module Data.Geo.OSM.OSM,
+                module Data.Geo.OSM.OSMChildren,
+                module Data.Geo.OSM.Preferences,
                 module Data.Geo.OSM.Relation,
                 module Data.Geo.OSM.Tag,
+                module Data.Geo.OSM.Tracepoints,
+                module Data.Geo.OSM.UserE,
+                module Data.Geo.OSM.VersionE,
                 module Data.Geo.OSM.Way,
+                module Data.Geo.OSM.Waynodes,
+                module Data.Geo.OSM.Accessor.AccountCreated,
+                module Data.Geo.OSM.Accessor.Ar,
                 module Data.Geo.OSM.Accessor.BoundOrs,
                 module Data.Geo.OSM.Accessor.Box,
                 module Data.Geo.OSM.Accessor.Changeset,
+                module Data.Geo.OSM.Accessor.DisplayName,
                 module Data.Geo.OSM.Accessor.Generator,
+                module Data.Geo.OSM.Accessor.Hm,
                 module Data.Geo.OSM.Accessor.Id,
                 module Data.Geo.OSM.Accessor.K,
                 module Data.Geo.OSM.Accessor.Lat,
                 module Data.Geo.OSM.Accessor.Lon,
+                module Data.Geo.OSM.Accessor.Maximum,
                 module Data.Geo.OSM.Accessor.Maxlat,
                 module Data.Geo.OSM.Accessor.Maxlon,
                 module Data.Geo.OSM.Accessor.Members,
+                module Data.Geo.OSM.Accessor.Minimum,
                 module Data.Geo.OSM.Accessor.Minlat,
                 module Data.Geo.OSM.Accessor.Minlon,
                 module Data.Geo.OSM.Accessor.Mtype,
+                module Data.Geo.OSM.Accessor.Name,
                 module Data.Geo.OSM.Accessor.Nds,
                 module Data.Geo.OSM.Accessor.NodeWayRelations,
                 module Data.Geo.OSM.Accessor.Origin,
+                module Data.Geo.OSM.Accessor.Pending,
+                module Data.Geo.OSM.Accessor.PerPage,
                 module Data.Geo.OSM.Accessor.Ref,
                 module Data.Geo.OSM.Accessor.Role,
                 module Data.Geo.OSM.Accessor.Tags,
                 module Data.Geo.OSM.Accessor.Timestamp,
+                module Data.Geo.OSM.Accessor.Tpoints,
                 module Data.Geo.OSM.Accessor.Uid,
                 module Data.Geo.OSM.Accessor.User,
                 module Data.Geo.OSM.Accessor.Version,
                 module Data.Geo.OSM.Accessor.V,
-                module Data.Geo.OSM.Accessor.Visible
+                module Data.Geo.OSM.Accessor.Visible,
+                module Data.Geo.OSM.Accessor.Wnodes,
+                module Data.Geo.OSM.Accessor.Zoom
               ) where
 
 
 import Text.XML.HXT.Arrow
+import Data.Geo.OSM.Api
+import Data.Geo.OSM.Area
 import Data.Geo.OSM.Bound
 import Data.Geo.OSM.Bounds
+import Data.Geo.OSM.ChangesetE
+import Data.Geo.OSM.GpxFile
+import Data.Geo.OSM.Home
 import Data.Geo.OSM.Member
 import Data.Geo.OSM.MemberType
 import Data.Geo.OSM.Nd
 import Data.Geo.OSM.Node
 import Data.Geo.OSM.NodeWayRelation
 import Data.Geo.OSM.OSM
+import Data.Geo.OSM.OSMChildren
+import Data.Geo.OSM.Preferences
 import Data.Geo.OSM.Relation
 import Data.Geo.OSM.Tag
+import Data.Geo.OSM.Tracepoints
+import Data.Geo.OSM.UserE
+import Data.Geo.OSM.VersionE
 import Data.Geo.OSM.Way
+import Data.Geo.OSM.Waynodes
+import Data.Geo.OSM.Accessor.AccountCreated
+import Data.Geo.OSM.Accessor.Ar
 import Data.Geo.OSM.Accessor.BoundOrs
 import Data.Geo.OSM.Accessor.Box
 import Data.Geo.OSM.Accessor.Changeset
+import Data.Geo.OSM.Accessor.DisplayName
 import Data.Geo.OSM.Accessor.Generator
+import Data.Geo.OSM.Accessor.Hm
 import Data.Geo.OSM.Accessor.Id
 import Data.Geo.OSM.Accessor.K
 import Data.Geo.OSM.Accessor.Lat
 import Data.Geo.OSM.Accessor.Lon
+import Data.Geo.OSM.Accessor.Maximum
 import Data.Geo.OSM.Accessor.Maxlat
 import Data.Geo.OSM.Accessor.Maxlon
 import Data.Geo.OSM.Accessor.Members
+import Data.Geo.OSM.Accessor.Minimum
 import Data.Geo.OSM.Accessor.Minlat
 import Data.Geo.OSM.Accessor.Minlon
 import Data.Geo.OSM.Accessor.Mtype
+import Data.Geo.OSM.Accessor.Name
 import Data.Geo.OSM.Accessor.Nds
 import Data.Geo.OSM.Accessor.NodeWayRelations
 import Data.Geo.OSM.Accessor.Origin
+import Data.Geo.OSM.Accessor.Pending
+import Data.Geo.OSM.Accessor.PerPage
 import Data.Geo.OSM.Accessor.Ref
 import Data.Geo.OSM.Accessor.Role
 import Data.Geo.OSM.Accessor.Tags
 import Data.Geo.OSM.Accessor.Timestamp
+import Data.Geo.OSM.Accessor.Tpoints
 import Data.Geo.OSM.Accessor.Uid
 import Data.Geo.OSM.Accessor.User
 import Data.Geo.OSM.Accessor.Version
 import Data.Geo.OSM.Accessor.V
 import Data.Geo.OSM.Accessor.Visible
+import Data.Geo.OSM.Accessor.Wnodes
+import Data.Geo.OSM.Accessor.Zoom
diff --git a/Data/Geo/OSM/Accessor/Accessor.hs b/Data/Geo/OSM/Accessor/Accessor.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Accessor.hs
@@ -0,0 +1,8 @@
+module Data.Geo.OSM.Accessor.Accessor(
+                                       using
+                                     ) where
+
+import Control.Monad.Instances()
+
+using :: (a -> d) -> (c -> a -> b) -> a -> (d -> c) -> b
+using f g = flip =<< (g .) . flip id . f
diff --git a/Data/Geo/OSM/Accessor/AccountCreated.hs b/Data/Geo/OSM/Accessor/AccountCreated.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/AccountCreated.hs
@@ -0,0 +1,11 @@
+-- | Values with a @account_created@ string accessor.
+module Data.Geo.OSM.Accessor.AccountCreated where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class AccountCreated a where
+  accountCreated :: a -> String
+  setAccountCreated :: String -> a -> a
+
+  usingAccountCreated :: a -> (String -> String) -> a
+  usingAccountCreated = accountCreated `using` setAccountCreated
diff --git a/Data/Geo/OSM/Accessor/Ar.hs b/Data/Geo/OSM/Accessor/Ar.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Ar.hs
@@ -0,0 +1,12 @@
+-- | Values with a @area@ string accessor.
+module Data.Geo.OSM.Accessor.Ar where
+
+import Data.Geo.OSM.Area
+import Data.Geo.OSM.Accessor.Accessor
+
+class Ar a where
+  ar :: a -> Area
+  setAr :: Area -> a -> a
+
+  usingArea :: a -> (Area -> Area) -> a
+  usingArea = ar `using` setAr
diff --git a/Data/Geo/OSM/Accessor/BoundOrs.hs b/Data/Geo/OSM/Accessor/BoundOrs.hs
--- a/Data/Geo/OSM/Accessor/BoundOrs.hs
+++ b/Data/Geo/OSM/Accessor/BoundOrs.hs
@@ -6,3 +6,13 @@
 
 class BoundOrs a where
   boundOrs :: a -> x -> (Bound -> x) -> (Bounds -> x) -> x
+  setBoundOrs :: Maybe (Either Bound Bounds) -> a -> a
+
+  setBound :: Bound -> a -> a
+  setBound = setBoundOrs . Just . Left
+
+  setBounds :: Bounds -> a -> a
+  setBounds = setBoundOrs . Just . Right
+
+  usingBoundOrs :: a -> (Maybe (Either Bound Bounds) -> Maybe (Either Bound Bounds)) -> a
+  usingBoundOrs a f = setBoundOrs (f (boundOrs a Nothing (Just . Left) (Just . Right))) a
diff --git a/Data/Geo/OSM/Accessor/Box.hs b/Data/Geo/OSM/Accessor/Box.hs
--- a/Data/Geo/OSM/Accessor/Box.hs
+++ b/Data/Geo/OSM/Accessor/Box.hs
@@ -1,5 +1,11 @@
 -- | Values with a @box@ string accessor.
 module Data.Geo.OSM.Accessor.Box where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Box a where
   box :: a -> String
+  setBox :: String -> a -> a
+
+  usingBox :: a -> (String -> String) -> a
+  usingBox = box `using` setBox
diff --git a/Data/Geo/OSM/Accessor/Changeset.hs b/Data/Geo/OSM/Accessor/Changeset.hs
--- a/Data/Geo/OSM/Accessor/Changeset.hs
+++ b/Data/Geo/OSM/Accessor/Changeset.hs
@@ -1,5 +1,17 @@
 -- | Values with a @changeset@ optional string accessor.
 module Data.Geo.OSM.Accessor.Changeset where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Changeset a where
   changeset :: a -> Maybe String
+  setChangeset :: Maybe String -> a -> a
+
+  setChangeset' :: String -> a -> a
+  setChangeset' = setChangeset . return
+
+  usingChangeset :: a -> (Maybe String -> Maybe String) -> a
+  usingChangeset = changeset `using` setChangeset
+
+  usingChangeset' :: a -> (String -> String) -> a
+  usingChangeset' = (. fmap) . usingChangeset
diff --git a/Data/Geo/OSM/Accessor/DisplayName.hs b/Data/Geo/OSM/Accessor/DisplayName.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/DisplayName.hs
@@ -0,0 +1,11 @@
+-- | Values with a @display_name@ string accessor.
+module Data.Geo.OSM.Accessor.DisplayName where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class DisplayName a where
+  displayName :: a -> String
+  setDisplayName :: String -> a -> a
+
+  usingDisplayName :: a -> (String -> String) -> a
+  usingDisplayName = displayName `using` setDisplayName
diff --git a/Data/Geo/OSM/Accessor/Generator.hs b/Data/Geo/OSM/Accessor/Generator.hs
--- a/Data/Geo/OSM/Accessor/Generator.hs
+++ b/Data/Geo/OSM/Accessor/Generator.hs
@@ -1,5 +1,17 @@
 -- | Values with a @generator@ optional string accessor.
 module Data.Geo.OSM.Accessor.Generator where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Generator a where
   generator :: a -> Maybe String
+  setGenerator :: Maybe String -> a -> a
+
+  setGenerator' :: String -> a -> a
+  setGenerator' = setGenerator . return
+
+  usingGenerator :: a -> (Maybe String -> Maybe String) -> a
+  usingGenerator = generator `using` setGenerator
+
+  usingGenerator' :: a -> (String -> String) -> a
+  usingGenerator' = (. fmap) . usingGenerator
diff --git a/Data/Geo/OSM/Accessor/Hm.hs b/Data/Geo/OSM/Accessor/Hm.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Hm.hs
@@ -0,0 +1,18 @@
+-- | Values with a @home@ optional string accessor.
+module Data.Geo.OSM.Accessor.Hm where
+
+import Data.Geo.OSM.Accessor.Accessor
+import Data.Geo.OSM.Home
+
+class Hm a where
+  hm :: a -> Maybe Home
+  setHm :: Maybe Home -> a -> a
+
+  setHm' :: Home -> a -> a
+  setHm' = setHm . return
+
+  usingHm :: a -> (Maybe Home -> Maybe Home) -> a
+  usingHm = hm `using` setHm
+
+  usingHm' :: a -> (Home -> Home) -> a
+  usingHm' = (. fmap) . usingHm
diff --git a/Data/Geo/OSM/Accessor/Id.hs b/Data/Geo/OSM/Accessor/Id.hs
--- a/Data/Geo/OSM/Accessor/Id.hs
+++ b/Data/Geo/OSM/Accessor/Id.hs
@@ -1,5 +1,12 @@
 -- | Values with a @id@ string accessor.
 module Data.Geo.OSM.Accessor.Id where
 
+import Data.Geo.OSM.Accessor.Accessor
+import Prelude hiding (id)
+
 class Id a where
   id :: a -> String
+  setId :: String -> a -> a
+
+  updateId :: a -> (String -> String) -> a
+  updateId = id `using` setId
diff --git a/Data/Geo/OSM/Accessor/K.hs b/Data/Geo/OSM/Accessor/K.hs
--- a/Data/Geo/OSM/Accessor/K.hs
+++ b/Data/Geo/OSM/Accessor/K.hs
@@ -1,5 +1,11 @@
 -- | Values with a @k@ string accessor.
 module Data.Geo.OSM.Accessor.K where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class K a where
   k :: a -> String
+  setK :: String -> a -> a
+
+  usingK :: a -> (String -> String) -> a
+  usingK = k `using` setK
diff --git a/Data/Geo/OSM/Accessor/Lat.hs b/Data/Geo/OSM/Accessor/Lat.hs
--- a/Data/Geo/OSM/Accessor/Lat.hs
+++ b/Data/Geo/OSM/Accessor/Lat.hs
@@ -1,5 +1,11 @@
 -- | Values with a @lat@ string accessor.
 module Data.Geo.OSM.Accessor.Lat where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Lat a where
   lat :: a -> String
+  setLat :: String -> a -> a
+
+  usingLat :: a -> (String -> String) -> a
+  usingLat = lat `using` setLat
diff --git a/Data/Geo/OSM/Accessor/Lon.hs b/Data/Geo/OSM/Accessor/Lon.hs
--- a/Data/Geo/OSM/Accessor/Lon.hs
+++ b/Data/Geo/OSM/Accessor/Lon.hs
@@ -1,5 +1,11 @@
 -- | Values with a @lon@ string accessor.
 module Data.Geo.OSM.Accessor.Lon where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Lon a where
   lon :: a -> String
+  setLon :: String -> a -> a
+
+  usingLon :: a -> (String -> String) -> a
+  usingLon = lon `using` setLon
diff --git a/Data/Geo/OSM/Accessor/Maximum.hs b/Data/Geo/OSM/Accessor/Maximum.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Maximum.hs
@@ -0,0 +1,12 @@
+-- | Values with a @maximum@ string accessor.
+module Data.Geo.OSM.Accessor.Maximum where
+
+import Data.Geo.OSM.Accessor.Accessor
+import Prelude hiding (maximum)
+
+class Maximum a where
+  maximum :: a -> String
+  setMaximum :: String -> a -> a
+
+  usingMaximum :: a -> (String -> String) -> a
+  usingMaximum = maximum  `using` setMaximum
diff --git a/Data/Geo/OSM/Accessor/Maxlat.hs b/Data/Geo/OSM/Accessor/Maxlat.hs
--- a/Data/Geo/OSM/Accessor/Maxlat.hs
+++ b/Data/Geo/OSM/Accessor/Maxlat.hs
@@ -1,5 +1,11 @@
 -- | Values with a @maxlat@ string accessor.
 module Data.Geo.OSM.Accessor.Maxlat where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Maxlat a where
   maxlat :: a -> String
+  setMaxlat :: String -> a -> a
+
+  usingMaxlat :: a -> (String -> String) -> a
+  usingMaxlat = maxlat  `using` setMaxlat
diff --git a/Data/Geo/OSM/Accessor/Maxlon.hs b/Data/Geo/OSM/Accessor/Maxlon.hs
--- a/Data/Geo/OSM/Accessor/Maxlon.hs
+++ b/Data/Geo/OSM/Accessor/Maxlon.hs
@@ -1,5 +1,11 @@
 -- -- | Values with a @maxlon@ string accessor.
 module Data.Geo.OSM.Accessor.Maxlon where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Maxlon a where
   maxlon :: a -> String
+  setMaxlon :: String -> a -> a
+
+  usingMaxlon :: a -> (String -> String) -> a
+  usingMaxlon = maxlon `using` setMaxlon
diff --git a/Data/Geo/OSM/Accessor/Members.hs b/Data/Geo/OSM/Accessor/Members.hs
--- a/Data/Geo/OSM/Accessor/Members.hs
+++ b/Data/Geo/OSM/Accessor/Members.hs
@@ -2,6 +2,17 @@
 module Data.Geo.OSM.Accessor.Members where
 
 import Data.Geo.OSM.Member
+import Data.Geo.OSM.Accessor.Accessor
 
 class Members a where
   members :: a -> [Member]
+  setMembers :: [Member] -> a -> a
+
+  setMember :: Member -> a -> a
+  setMember = setMembers . return
+
+  usingMembers :: a -> ([Member] -> [Member]) -> a
+  usingMembers = members `using` setMembers
+
+  usingMember :: a -> (Member -> Member) -> a
+  usingMember = (. map) . usingMembers
diff --git a/Data/Geo/OSM/Accessor/Minimum.hs b/Data/Geo/OSM/Accessor/Minimum.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Minimum.hs
@@ -0,0 +1,12 @@
+-- | Values with a @minimum@ string accessor.
+module Data.Geo.OSM.Accessor.Minimum where
+
+import Data.Geo.OSM.Accessor.Accessor
+import Prelude hiding (minimum)
+
+class Minimum a where
+  minimum :: a -> String
+  setMinimum :: String -> a -> a
+
+  usingMinimum :: a -> (String -> String) -> a
+  usingMinimum = minimum  `using` setMinimum
diff --git a/Data/Geo/OSM/Accessor/Minlat.hs b/Data/Geo/OSM/Accessor/Minlat.hs
--- a/Data/Geo/OSM/Accessor/Minlat.hs
+++ b/Data/Geo/OSM/Accessor/Minlat.hs
@@ -1,5 +1,11 @@
 -- | Values with a @minlat@ string accessor.
 module Data.Geo.OSM.Accessor.Minlat where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Minlat a where
   minlat :: a -> String
+  setMinlat :: String -> a -> a
+
+  usingMinlat :: a -> (String -> String) -> a
+  usingMinlat = minlat `using` setMinlat
diff --git a/Data/Geo/OSM/Accessor/Minlon.hs b/Data/Geo/OSM/Accessor/Minlon.hs
--- a/Data/Geo/OSM/Accessor/Minlon.hs
+++ b/Data/Geo/OSM/Accessor/Minlon.hs
@@ -1,5 +1,11 @@
 -- | Values with a @minlon@ string accessor.
 module Data.Geo.OSM.Accessor.Minlon where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Minlon a where
   minlon :: a -> String
+  setMinlon :: String -> a -> a
+
+  usingMinlon :: a -> (String -> String) -> a
+  usingMinlon = minlon `using` setMinlon
diff --git a/Data/Geo/OSM/Accessor/Mtype.hs b/Data/Geo/OSM/Accessor/Mtype.hs
--- a/Data/Geo/OSM/Accessor/Mtype.hs
+++ b/Data/Geo/OSM/Accessor/Mtype.hs
@@ -2,6 +2,11 @@
 module Data.Geo.OSM.Accessor.Mtype where
 
 import Data.Geo.OSM.MemberType
+import Data.Geo.OSM.Accessor.Accessor
 
 class Mtype a where
   mtype :: a -> MemberType
+  setMtype :: MemberType -> a -> a
+
+  usingMtype :: a -> (MemberType -> MemberType) -> a
+  usingMtype = mtype `using` setMtype
diff --git a/Data/Geo/OSM/Accessor/Name.hs b/Data/Geo/OSM/Accessor/Name.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Name.hs
@@ -0,0 +1,11 @@
+-- -- | Values with a @name@ string accessor.
+module Data.Geo.OSM.Accessor.Name where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class Name a where
+  name :: a -> String
+  setName :: String -> a -> a
+
+  usingName :: a -> (String -> String) -> a
+  usingName = name `using` setName
diff --git a/Data/Geo/OSM/Accessor/Nds.hs b/Data/Geo/OSM/Accessor/Nds.hs
--- a/Data/Geo/OSM/Accessor/Nds.hs
+++ b/Data/Geo/OSM/Accessor/Nds.hs
@@ -2,6 +2,17 @@
 module Data.Geo.OSM.Accessor.Nds where
 
 import Data.Geo.OSM.Nd
+import Data.Geo.OSM.Accessor.Accessor
 
 class Nds a where
   nds :: a -> [Nd]
+  setNds :: [Nd] -> a -> a
+
+  setNd :: Nd -> a -> a
+  setNd = setNds . return
+
+  usingNds :: a -> ([Nd] -> [Nd]) -> a
+  usingNds = nds `using` setNds
+
+  usingNd :: a -> (Nd -> Nd) -> a
+  usingNd = (. map) . usingNds
diff --git a/Data/Geo/OSM/Accessor/NodeWayRelations.hs b/Data/Geo/OSM/Accessor/NodeWayRelations.hs
--- a/Data/Geo/OSM/Accessor/NodeWayRelations.hs
+++ b/Data/Geo/OSM/Accessor/NodeWayRelations.hs
@@ -5,9 +5,29 @@
 import Data.Geo.OSM.Node
 import Data.Geo.OSM.Way
 import Data.Geo.OSM.Relation
+import Data.Geo.OSM.Accessor.Accessor
 
 class NodeWayRelations a where
   nwrs :: a -> [NodeWayRelation]
+  setNwrs :: [NodeWayRelation] -> a -> a
+
+  setNwr :: NodeWayRelation -> a -> a
+  setNwr = setNwrs . return
+
+  usingNwrs :: a -> ([NodeWayRelation] -> [NodeWayRelation]) -> a
+  usingNwrs = nwrs `using` setNwrs
+
+  usingNwr :: a -> (NodeWayRelation -> NodeWayRelation) -> a
+  usingNwr = (. map) . usingNwrs
+
+  usingNode :: a -> (Node -> Node) -> a
+  usingNode a f = usingNwr a (\p -> foldNodeWayRelation p (node' . f) way' relation')
+
+  usingWay :: a -> (Way -> Way) -> a
+  usingWay a f = usingNwr a (\p -> foldNodeWayRelation p node' (way' . f) relation')
+
+  usingRelation :: a -> (Relation -> Relation) -> a
+  usingRelation a f = usingNwr a (\p -> foldNodeWayRelation p node' way' (relation' . f))
 
 nodes :: (NodeWayRelations a) => a -> [Node]
 nodes k = nwrs k >>= \t -> foldNodeWayRelation t return (const []) (const [])
diff --git a/Data/Geo/OSM/Accessor/Origin.hs b/Data/Geo/OSM/Accessor/Origin.hs
--- a/Data/Geo/OSM/Accessor/Origin.hs
+++ b/Data/Geo/OSM/Accessor/Origin.hs
@@ -1,5 +1,17 @@
 -- | Values with a @origin@ optional string accessor.
 module Data.Geo.OSM.Accessor.Origin where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Origin a where
   origin :: a -> Maybe String
+  setOrigin :: Maybe String -> a -> a
+
+  setOrigin' :: String -> a -> a
+  setOrigin' = setOrigin . return
+
+  usingOrigin :: a -> (Maybe String -> Maybe String) -> a
+  usingOrigin = origin `using` setOrigin
+
+  usingOrigin' :: a -> (String -> String) -> a
+  usingOrigin' = (. fmap) . usingOrigin
diff --git a/Data/Geo/OSM/Accessor/Pending.hs b/Data/Geo/OSM/Accessor/Pending.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Pending.hs
@@ -0,0 +1,11 @@
+-- -- | Values with a @pending@ boolean accessor.
+module Data.Geo.OSM.Accessor.Pending where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class Pending a where
+  pending :: a -> Bool
+  setPending :: Bool -> a -> a
+
+  usingPending :: a -> (Bool -> Bool) -> a
+  usingPending = pending `using` setPending
diff --git a/Data/Geo/OSM/Accessor/PerPage.hs b/Data/Geo/OSM/Accessor/PerPage.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/PerPage.hs
@@ -0,0 +1,11 @@
+-- | Values with a @per_page@ string accessor.
+module Data.Geo.OSM.Accessor.PerPage where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class PerPage a where
+  perPage :: a -> String
+  setPerPage :: String -> a -> a
+
+  usingPerPage :: a -> (String -> String) -> a
+  usingPerPage = perPage `using` setPerPage
diff --git a/Data/Geo/OSM/Accessor/Public.hs b/Data/Geo/OSM/Accessor/Public.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Public.hs
@@ -0,0 +1,11 @@
+-- -- | Values with a @public@ boolean accessor.
+module Data.Geo.OSM.Accessor.Public where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class Public a where
+  public :: a -> Bool
+  setPublic :: Bool -> a -> a
+
+  usingPublic :: a -> (Bool -> Bool) -> a
+  usingPublic = public `using` setPublic
diff --git a/Data/Geo/OSM/Accessor/Ref.hs b/Data/Geo/OSM/Accessor/Ref.hs
--- a/Data/Geo/OSM/Accessor/Ref.hs
+++ b/Data/Geo/OSM/Accessor/Ref.hs
@@ -1,5 +1,11 @@
 -- | Values with a @ref@ string accessor.
 module Data.Geo.OSM.Accessor.Ref where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Ref a where
   ref :: a -> String
+  setRef :: String -> a -> a
+
+  usingRef :: a -> (String -> String) -> a
+  usingRef = ref `using` setRef
diff --git a/Data/Geo/OSM/Accessor/Role.hs b/Data/Geo/OSM/Accessor/Role.hs
--- a/Data/Geo/OSM/Accessor/Role.hs
+++ b/Data/Geo/OSM/Accessor/Role.hs
@@ -1,5 +1,11 @@
 -- | Values with a @role@ string accessor.
 module Data.Geo.OSM.Accessor.Role where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Role a where
   role :: a -> String
+  setRole :: String -> a -> a
+
+  usingRole :: a -> (String -> String) -> a
+  usingRole = role `using` setRole
diff --git a/Data/Geo/OSM/Accessor/Tags.hs b/Data/Geo/OSM/Accessor/Tags.hs
--- a/Data/Geo/OSM/Accessor/Tags.hs
+++ b/Data/Geo/OSM/Accessor/Tags.hs
@@ -8,12 +8,29 @@
 import Control.Arrow
 import Data.Foldable
 import Prelude hiding (any)
+import Data.Geo.OSM.Accessor.Accessor
 
 class Tags a where
   tags :: a -> [Tag]
+  setTags :: [Tag] -> a -> a
 
+  setTag :: Tag -> a -> a
+  setTag = setTags . return
+
+  usingTags :: a -> ([Tag] -> [Tag]) -> a
+  usingTags = tags `using` setTags
+
+  usingTag :: a -> (Tag -> Tag) -> a
+  usingTag = (. map) . usingTags
+
+  usingTag' :: a -> ((String, String) -> (String, String)) -> a
+  usingTag' a f = usingTag a (\t -> uncurry tag (f (k t, v t)))
+
 tagMap :: (Tags a) => a -> M.Map String String
 tagMap = M.fromList . map (k &&& v) . tags
+
+tagValue :: (Tags a) => a -> String -> Maybe String
+tagValue = flip lookup . map (k &&& v) . tags
 
 hasTagValue :: (Tags a) => String -> String -> a -> Bool
 hasTagValue k' v' n = any (== v') (k' `M.lookup` tagMap n)
diff --git a/Data/Geo/OSM/Accessor/Timestamp.hs b/Data/Geo/OSM/Accessor/Timestamp.hs
--- a/Data/Geo/OSM/Accessor/Timestamp.hs
+++ b/Data/Geo/OSM/Accessor/Timestamp.hs
@@ -1,5 +1,13 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+
 -- | Values with a @timestamp@ optional string accessor.
 module Data.Geo.OSM.Accessor.Timestamp where
 
-class Timestamp a where
-  timestamp :: a -> Maybe String
+import Data.Geo.OSM.Accessor.Accessor
+
+class Timestamp a b | a -> b where
+  timestamp :: a -> b
+  setTimestamp :: b -> a -> a
+
+  usingTimestamp :: a -> (b -> b) -> a
+  usingTimestamp = timestamp `using` setTimestamp
diff --git a/Data/Geo/OSM/Accessor/Tpoints.hs b/Data/Geo/OSM/Accessor/Tpoints.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Tpoints.hs
@@ -0,0 +1,12 @@
+-- | Values with a @tracepoints@ string accessor.
+module Data.Geo.OSM.Accessor.Tpoints where
+
+import Data.Geo.OSM.Tracepoints
+import Data.Geo.OSM.Accessor.Accessor
+
+class Tpoints a where
+  tpoints :: a -> Tracepoints
+  setTpoints :: Tracepoints -> a -> a
+
+  usingTpoints :: a -> (Tracepoints -> Tracepoints) -> a
+  usingTpoints = tpoints `using` setTpoints
diff --git a/Data/Geo/OSM/Accessor/Uid.hs b/Data/Geo/OSM/Accessor/Uid.hs
--- a/Data/Geo/OSM/Accessor/Uid.hs
+++ b/Data/Geo/OSM/Accessor/Uid.hs
@@ -1,5 +1,17 @@
 -- | Values with a @uid@ optional string accessor.
 module Data.Geo.OSM.Accessor.Uid where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Uid a where
   uid :: a -> Maybe String
+  setUid :: Maybe String -> a -> a
+
+  setUid' :: String -> a -> a
+  setUid' = setUid . return
+
+  usingUid :: a -> (Maybe String -> Maybe String) -> a
+  usingUid = uid `using` setUid
+
+  usingUid' :: a -> (String -> String) -> a
+  usingUid' = (. fmap) . usingUid
diff --git a/Data/Geo/OSM/Accessor/User.hs b/Data/Geo/OSM/Accessor/User.hs
--- a/Data/Geo/OSM/Accessor/User.hs
+++ b/Data/Geo/OSM/Accessor/User.hs
@@ -1,5 +1,13 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+
 -- | Values with a @user@ optional string accessor.
 module Data.Geo.OSM.Accessor.User where
 
-class User a where
-  user :: a -> Maybe String
+import Data.Geo.OSM.Accessor.Accessor
+
+class User a b | a -> b where
+  user :: a -> b
+  setUser :: b -> a -> a
+
+  usingUser :: a -> (b -> b) -> a
+  usingUser = user `using` setUser
diff --git a/Data/Geo/OSM/Accessor/V.hs b/Data/Geo/OSM/Accessor/V.hs
--- a/Data/Geo/OSM/Accessor/V.hs
+++ b/Data/Geo/OSM/Accessor/V.hs
@@ -1,5 +1,11 @@
 -- | Values with a @v@ string accessor.
 module Data.Geo.OSM.Accessor.V where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class V a where
   v :: a -> String
+  setV :: String -> a -> a
+
+  usingV :: a -> (String -> String) -> a
+  usingV = v `using` setV
diff --git a/Data/Geo/OSM/Accessor/Version.hs b/Data/Geo/OSM/Accessor/Version.hs
--- a/Data/Geo/OSM/Accessor/Version.hs
+++ b/Data/Geo/OSM/Accessor/Version.hs
@@ -1,5 +1,13 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+
 -- | Values with a @version@ string accessor.
 module Data.Geo.OSM.Accessor.Version where
 
-class Version a where
-  version :: a -> String
+import Data.Geo.OSM.Accessor.Accessor
+
+class Version a b | a -> b where
+  version :: a -> b
+  setVersion :: b -> a -> a
+
+  usingVersion :: a -> (b -> b) -> a
+  usingVersion = version `using` setVersion
diff --git a/Data/Geo/OSM/Accessor/Visible.hs b/Data/Geo/OSM/Accessor/Visible.hs
--- a/Data/Geo/OSM/Accessor/Visible.hs
+++ b/Data/Geo/OSM/Accessor/Visible.hs
@@ -1,5 +1,17 @@
 -- | Values with a @visible@ boolean accessor.
 module Data.Geo.OSM.Accessor.Visible where
 
+import Data.Geo.OSM.Accessor.Accessor
+
 class Visible a where
   visible :: a -> Bool
+  setVisible :: Bool -> a -> a
+
+  makeVisible :: a -> a
+  makeVisible = setVisible True
+
+  makeInvisible :: a -> a
+  makeInvisible = setVisible False
+
+  usingVisible :: a -> (Bool -> Bool) -> a
+  usingVisible = visible `using` setVisible
diff --git a/Data/Geo/OSM/Accessor/Wnodes.hs b/Data/Geo/OSM/Accessor/Wnodes.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Wnodes.hs
@@ -0,0 +1,12 @@
+-- | Values with a @waynodes@ string accessor.
+module Data.Geo.OSM.Accessor.Wnodes where
+
+import Data.Geo.OSM.Waynodes
+import Data.Geo.OSM.Accessor.Accessor
+
+class Wnodes a where
+  wnodes :: a -> Waynodes
+  setWnodes :: Waynodes -> a -> a
+
+  usingWnodes :: a -> (Waynodes -> Waynodes) -> a
+  usingWnodes = wnodes `using` setWnodes
diff --git a/Data/Geo/OSM/Accessor/Zoom.hs b/Data/Geo/OSM/Accessor/Zoom.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Accessor/Zoom.hs
@@ -0,0 +1,11 @@
+-- | Values with a @zoom@ string accessor.
+module Data.Geo.OSM.Accessor.Zoom where
+
+import Data.Geo.OSM.Accessor.Accessor
+
+class Zoom a where
+  zoom :: a -> String
+  setZoom :: String -> a -> a
+
+  usingZoom :: a -> (String -> String) -> a
+  usingZoom = zoom  `using` setZoom
diff --git a/Data/Geo/OSM/Api.hs b/Data/Geo/OSM/Api.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Api.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
+
+-- | The @api@ element of a OSM file.
+module Data.Geo.OSM.Api(
+                         Api,
+                         api
+                       ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.VersionE
+import Data.Geo.OSM.Area
+import Data.Geo.OSM.Tracepoints
+import Data.Geo.OSM.Waynodes
+import Data.Geo.OSM.Accessor.Version
+import Data.Geo.OSM.Accessor.Ar
+import Data.Geo.OSM.Accessor.Tpoints
+import Data.Geo.OSM.Accessor.Wnodes
+
+-- | The @api@ element of a OSM file.
+data Api = Api VersionE Area Tracepoints Waynodes
+  deriving Eq
+
+-- | Constructs a @api@ with version, area, tracepoints and waynodes.
+api :: VersionE -- ^ The @version@ element.
+       -> Area -- ^ The @area@ element.
+       -> Tracepoints -- ^ The @tracepoints@ element.
+       -> Waynodes -- ^ The @waynodes@ element.
+       -> Api
+api = Api
+
+instance XmlPickler Api where
+  xpickle = xpElem "api" (xpWrap (\(version', area', tracepoints', waypoints') -> api version' area' tracepoints' waypoints', \(Api version' area' tracepoints' waynodes') -> (version', area', tracepoints', waynodes')) (xp4Tuple (xpElem "version" xpickle) (xpElem "area" xpickle) (xpElem "tracepoints" xpickle) (xpElem "waynodes" xpickle)))
+
+instance Show Api where
+  show = showPickled []
+
+instance Version Api VersionE where
+  version (Api x _ _ _) = x
+  setVersion a (Api _ b c d) = api a b c d
+
+instance Ar Api where
+  ar (Api _ x _ _) = x
+  setAr b (Api a _ c d) = api a b c d
+
+instance Tpoints Api where
+  tpoints (Api _ _ x _) = x
+  setTpoints c (Api a b _ d) = api a b c d
+
+instance Wnodes Api where
+  wnodes (Api _ _ _ x) = x
+  setWnodes d (Api a b c _) = api a b c d
diff --git a/Data/Geo/OSM/Area.hs b/Data/Geo/OSM/Area.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Area.hs
@@ -0,0 +1,28 @@
+-- | The @area@ element of a OSM file.
+module Data.Geo.OSM.Area(
+                          Area,
+                          area
+                        ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Accessor.Maximum
+
+-- | The @area@ element of a OSM file.
+newtype Area = Area String
+  deriving Eq
+
+-- | Constructs a @area@ with maximum.
+area :: String -- ^ The @area@ element.
+        -> Area
+area = Area
+
+instance XmlPickler Area where
+  xpickle = xpElem "area" (xpWrap (area, \(Area r) -> r) (xpAttr "maximum" xpText))
+
+instance Show Area where
+  show = showPickled []
+
+instance Maximum Area where
+  maximum (Area x) = x
+  setMaximum a (Area _) = area a
diff --git a/Data/Geo/OSM/Bound.hs b/Data/Geo/OSM/Bound.hs
--- a/Data/Geo/OSM/Bound.hs
+++ b/Data/Geo/OSM/Bound.hs
@@ -14,16 +14,18 @@
   deriving Eq
 
 instance XmlPickler Bound where
-  xpickle = xpElem "bound" (xpWrap (uncurry Bound, \(Bound b o) -> (b, o)) (xpPair (xpAttr "box" xpText) (xpOption (xpAttr "origin" xpText))))
+  xpickle = xpElem "bound" (xpWrap (uncurry bound, \(Bound b o) -> (b, o)) (xpPair (xpAttr "box" xpText) (xpOption (xpAttr "origin" xpText))))
 
 instance Show Bound where
   show = showPickled []
 
 instance Box Bound where
   box (Bound x _) = x
+  setBox a (Bound _ b) = bound a b
 
 instance Origin Bound where
   origin (Bound _ x) = x
+  setOrigin b (Bound a _) = bound a b
 
 -- | Constructs a bound with a box and origin attributes.
 bound :: String -- ^ The @box@ attribute.
diff --git a/Data/Geo/OSM/Bounds.hs b/Data/Geo/OSM/Bounds.hs
--- a/Data/Geo/OSM/Bounds.hs
+++ b/Data/Geo/OSM/Bounds.hs
@@ -17,7 +17,7 @@
   deriving Eq
 
 instance XmlPickler Bounds where
-  xpickle = xpElem "bounds" (xpWrap (\(minlat', minlon', maxlat', maxlon', origin') -> Bounds minlat' minlon' maxlat' maxlon' origin', \(Bounds minlat' minlon' maxlat' maxlon' origin') -> (minlat', minlon', maxlat', maxlon', origin'))
+  xpickle = xpElem "bounds" (xpWrap (\(minlat', minlon', maxlat', maxlon', origin') -> bounds minlat' minlon' maxlat' maxlon' origin', \(Bounds minlat' minlon' maxlat' maxlon' origin') -> (minlat', minlon', maxlat', maxlon', origin'))
                               (xp5Tuple (xpAttr "minlat" xpText) (xpAttr "minlon" xpText) (xpAttr "maxlat" xpText) (xpAttr "maxlon" xpText) (xpOption (xpAttr "origin" xpText))))
 
 instance Show Bounds where
@@ -25,18 +25,23 @@
 
 instance Minlat Bounds where
   minlat (Bounds x _ _ _ _) = x
+  setMinlat a (Bounds _ b c d e) = bounds a b c d e
 
 instance Minlon Bounds where
   minlon (Bounds _ x _ _ _) = x
+  setMinlon b (Bounds a _ c d e) = bounds a b c d e
 
 instance Maxlat Bounds where
   maxlat (Bounds _ _ x _ _) = x
+  setMaxlat c (Bounds a b _ d e) = bounds a b c d e
 
 instance Maxlon Bounds where
   maxlon (Bounds _ _ _ x _) = x
+  setMaxlon d (Bounds a b c _ e) = bounds a b c d e
 
 instance Origin Bounds where
   origin (Bounds _ _ _ _ x) = x
+  setOrigin e (Bounds a b c d _) = bounds a b c d e
 
 -- | Constructs a bounds with a minlat, minlon, maxlat, maxlon and origin attributes.
 bounds :: String -- ^ The @minlat@ attribute.
diff --git a/Data/Geo/OSM/ChangesetE.hs b/Data/Geo/OSM/ChangesetE.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/ChangesetE.hs
@@ -0,0 +1,29 @@
+-- | The @changeset@ element of a OSM file.
+module Data.Geo.OSM.ChangesetE(
+                                ChangesetE,
+                                changesetE
+                              ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Tag
+import Data.Geo.OSM.Accessor.Tags
+
+-- | The @changeset@ element of a OSM file.
+newtype ChangesetE = ChangesetE [Tag]
+  deriving Eq
+
+-- | Constructs a @changeset@ with tags.
+changesetE :: [Tag] -- ^ The list of tags (@tag@ elements).
+              -> ChangesetE
+changesetE = ChangesetE
+
+instance XmlPickler ChangesetE where
+  xpickle = xpElem "changeset" (xpWrap (changesetE, \(ChangesetE r) -> r) (xpList xpickle))
+
+instance Show ChangesetE where
+  show = showPickled []
+
+instance Tags ChangesetE where
+  tags (ChangesetE x) = x
+  setTags a (ChangesetE _) = changesetE a
diff --git a/Data/Geo/OSM/GpxFile.hs b/Data/Geo/OSM/GpxFile.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/GpxFile.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
+
+-- | The @gpx_file@ element of a OSM file.
+module Data.Geo.OSM.GpxFile(
+                             GpxFile,
+                             gpxFile
+                           ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Char
+import Data.Geo.OSM.Accessor.Id
+import Data.Geo.OSM.Accessor.Name
+import Data.Geo.OSM.Accessor.Lat
+import Data.Geo.OSM.Accessor.Lon
+import Data.Geo.OSM.Accessor.User
+import Data.Geo.OSM.Accessor.Public
+import Data.Geo.OSM.Accessor.Pending
+import Data.Geo.OSM.Accessor.Timestamp
+
+-- | The @gpx_file@ element of a OSM file.
+data GpxFile = GpxFile String String String String String Bool Bool String
+  deriving Eq
+
+-- | Constructs a @gpx_file@ with an id, name, lat, lon, user, public, pending and timestamp.
+gpxFile
+  :: String -- ^ The @id@ attribute.
+     -> String -- ^ The @name@ attribute.
+     -> String -- ^ The @lat@ attribute.
+     -> String -- ^ The @lon@ attribute.
+     -> String -- ^ The @user@ attribute.
+     -> Bool -- ^ The @public@ attribute.
+     -> Bool -- ^ The @pending@ attribute.
+     -> String -- ^ The @timestamp@ attribute.
+     -> GpxFile
+gpxFile = GpxFile
+
+instance XmlPickler GpxFile where
+  xpickle = let b = xpWrapMaybe (\s -> case fmap toLower s of "true" -> Just True
+                                                              "false" -> Just False
+                                                              _ -> Nothing, (fmap toLower) . show)
+            in xpElem "gpx_file" (xpWrap (\(id', name', lat', lon', user', public', pending', timestamp') -> gpxFile id' name' lat' lon' user' public' pending' timestamp', undefined) (xp8Tuple (xpAttr "id" xpText) (xpAttr "name" xpText) (xpAttr "lat" xpText) (xpAttr "lon" xpText) (xpAttr "user" xpText) (xpDefault False (b (xpAttr "public" xpText))) (xpDefault False (b (xpAttr "pending" xpText))) (xpAttr "timestamp" xpText)))
+
+instance Show GpxFile where
+  show = showPickled []
+
+instance Id GpxFile where
+  id (GpxFile x _ _ _ _ _ _ _) = x
+  setId a (GpxFile _ b c d e f g h) = gpxFile a b c d e f g h
+
+instance Name GpxFile where
+  name (GpxFile _ x _ _ _ _ _ _) = x
+  setName b (GpxFile a _ c d e f g h) = gpxFile a b c d e f g h
+
+instance Lat GpxFile where
+  lat (GpxFile _ _ x _ _ _ _ _) = x
+  setLat c (GpxFile a b _ d e f g h) = gpxFile a b c d e f g h
+
+instance Lon GpxFile where
+  lon (GpxFile _ _ _ x _ _ _ _) = x
+  setLon d (GpxFile a b c _ e f g h) = gpxFile a b c d e f g h
+
+instance User GpxFile String where
+  user (GpxFile _ _ _ _ x _ _ _) = x
+  setUser e (GpxFile a b c d _ f g h) = gpxFile a b c d e f g h
+
+instance Public GpxFile where
+  public (GpxFile _ _ _ _ _ x _ _) = x
+  setPublic f (GpxFile a b c d e _ g h) = gpxFile a b c d e f g h
+
+instance Pending GpxFile where
+  pending (GpxFile _ _ _ _ _ _ x _) = x
+  setPending g (GpxFile a b c d e f _ h) = gpxFile a b c d e f g h
+
+instance Timestamp GpxFile String where
+  timestamp (GpxFile _ _ _ _ _ _ _ x) = x
+  setTimestamp h (GpxFile a b c d e f g _) = gpxFile a b c d e f g h
diff --git a/Data/Geo/OSM/Home.hs b/Data/Geo/OSM/Home.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Home.hs
@@ -0,0 +1,40 @@
+-- | The @home@ element of a OSM file.
+module Data.Geo.OSM.Home(
+                          Home,
+                          home
+                        ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Accessor.Lat
+import Data.Geo.OSM.Accessor.Lon
+import Data.Geo.OSM.Accessor.Zoom
+
+-- | The @home@ element of a OSM file.
+data Home = Home String String String
+  deriving Eq
+
+-- | Constructs a @home@ with lat, lon and zoom.
+home :: String -- ^ The @lat@ attribute.
+        -> String -- ^ The @lon@ attribute.
+        -> String -- ^ The @zoom@ attribute.
+        -> Home
+home = Home
+
+instance XmlPickler Home where
+  xpickle = xpElem "home" (xpWrap (\(lat', lon', zoom') -> home lat' lon' zoom', \(Home lat' lon' zoom') -> (lat', lon', zoom')) (xpTriple (xpAttr "lat" xpText) (xpAttr "lon" xpText) (xpAttr "zoom" xpText)))
+
+instance Show Home where
+  show = showPickled []
+
+instance Lat Home where
+  lat (Home x _ _) = x
+  setLat a (Home _ b c) = home a b c
+
+instance Lon Home where
+  lon (Home _ x _) = x
+  setLon b (Home a _ c) = home a b c
+
+instance Zoom Home where
+  zoom (Home _ _ x) = x
+  setZoom c (Home a b _) = home a b c
diff --git a/Data/Geo/OSM/Member.hs b/Data/Geo/OSM/Member.hs
--- a/Data/Geo/OSM/Member.hs
+++ b/Data/Geo/OSM/Member.hs
@@ -16,7 +16,7 @@
   deriving Eq
 
 instance XmlPickler Member where
-  xpickle = xpElem "member" (xpWrap (\(mtype', mref', mrole') -> Member mtype' mref' mrole', \(Member mtype' mref' mrole') -> (mtype', mref', mrole'))
+  xpickle = xpElem "member" (xpWrap (\(mtype', mref', mrole') -> member mtype' mref' mrole', \(Member mtype' mref' mrole') -> (mtype', mref', mrole'))
                               (xpTriple xpickle (xpAttr "ref" xpText) (xpAttr "role" xpText)))
 
 instance Show Member where
@@ -24,12 +24,15 @@
 
 instance Mtype Member where
   mtype (Member x _ _) = x
+  setMtype a (Member _ b c) = member a b c
 
 instance Ref Member where
   ref (Member _ x _) = x
+  setRef b (Member a _ c) = member a b c
 
 instance Role Member where
   role (Member _ _ x) = x
+  setRole c (Member a b _) = member a b c
 
 -- | Constructs a member with a type, ref and role.
 member :: MemberType -- ^ The member @type@ attribute.
diff --git a/Data/Geo/OSM/MemberType.hs b/Data/Geo/OSM/MemberType.hs
--- a/Data/Geo/OSM/MemberType.hs
+++ b/Data/Geo/OSM/MemberType.hs
@@ -9,7 +9,6 @@
 
 import Text.XML.HXT.Arrow
 import Text.XML.HXT.Extras
-import Control.Applicative
 import Data.Char
 
 -- | The @type@ attribute of a @member@ element of a OSM file.
@@ -27,10 +26,10 @@
 foldMemberType RelationType _ _ x = x
 
 instance XmlPickler MemberType where
-  xpickle = xpWrapMaybe (\s -> case toLower <$> s of "way" -> Just WayType
-                                                     "node" -> Just NodeType
-                                                     "relation" -> Just RelationType
-                                                     _ -> Nothing,
+  xpickle = xpWrapMaybe (\s -> case fmap toLower s of "way" -> Just WayType
+                                                      "node" -> Just NodeType
+                                                      "relation" -> Just RelationType
+                                                      _ -> Nothing,
                          \t -> case t of WayType -> "way"
                                          NodeType -> "node"
                                          RelationType -> "relation") (xpAttr "type" xpText)
diff --git a/Data/Geo/OSM/NWRCommon.hs b/Data/Geo/OSM/NWRCommon.hs
--- a/Data/Geo/OSM/NWRCommon.hs
+++ b/Data/Geo/OSM/NWRCommon.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+
 -- | The common attributes between the @node@, @way@ and @relation@ elements.
 module Data.Geo.OSM.NWRCommon(
                           NWRCommon,
@@ -22,7 +24,7 @@
   deriving Eq
 
 instance XmlPickler NWRCommon where
-  xpickle = xpWrap (\(a, b, c, d, e, f) -> NWRCommon a b c d e f, \(NWRCommon a b c d e f) -> (a, b, c, d, e, f))
+  xpickle = xpWrap (\(a, b, c, d, e, f) -> nwrCommon a b c d e f, \(NWRCommon a b c d e f) -> (a, b, c, d, e, f))
               (xp6Tuple (xpAttr "id" xpText)
                         (xpList xpickle)
                         (xpOption (xpAttr "changeset" xpText))
@@ -37,24 +39,31 @@
 
 instance Id NWRCommon where
   id (NWRCommon x _ _ _ _ _) = x
+  setId a (NWRCommon _ b c d e f) = nwrCommon a b c d e f
 
 instance Tags NWRCommon where
   tags (NWRCommon _ x _ _ _ _) = x
+  setTags b (NWRCommon a _ c d e f) = nwrCommon a b c d e f
 
 instance Changeset NWRCommon where
   changeset (NWRCommon _ _ x _ _ _) = x
+  setChangeset c (NWRCommon a b _ d e f) = nwrCommon a b c d e f
 
 instance Visible NWRCommon where
   visible (NWRCommon _ _ _ x _ _) = x
+  setVisible d (NWRCommon a b c _ e f) = nwrCommon a b c d e f
 
-instance User NWRCommon where
+instance User NWRCommon (Maybe String) where
   user (NWRCommon _ _ _ _ (x, _) _) = x
+  setUser e (NWRCommon a b c d ee f) = nwrCommon a b c d ((first . const) e ee) f
 
 instance Uid NWRCommon where
   uid (NWRCommon _ _ _ _ (_, x) _) = x
+  setUid e (NWRCommon a b c d ee f) = nwrCommon a b c d ((second . const) e ee) f
 
-instance Timestamp NWRCommon where
+instance Timestamp NWRCommon (Maybe String) where
   timestamp (NWRCommon _ _ _ _ _ x) = x
+  setTimestamp f (NWRCommon a b c d e _) = nwrCommon a b c d e f
 
 -- | Constructs with id, list of tags, changeset, visible, user&uid and timestamp.
 nwrCommon :: String -- ^ The @id@ attribute.
diff --git a/Data/Geo/OSM/Nd.hs b/Data/Geo/OSM/Nd.hs
--- a/Data/Geo/OSM/Nd.hs
+++ b/Data/Geo/OSM/Nd.hs
@@ -13,13 +13,14 @@
   deriving Eq
 
 instance XmlPickler Nd where
-  xpickle = xpElem "nd" (xpWrap (Nd, \(Nd r) -> r) (xpAttr "ref" xpText))
+  xpickle = xpElem "nd" (xpWrap (nd, \(Nd r) -> r) (xpAttr "ref" xpText))
 
 instance Show Nd where
   show = showPickled []
 
 instance Ref Nd where
   ref (Nd x) = x
+  setRef a (Nd _) = nd a
 
 -- | Constructs a nd with a ref.
 nd :: String -- ^ The @ref@ attribute.
diff --git a/Data/Geo/OSM/Node.hs b/Data/Geo/OSM/Node.hs
--- a/Data/Geo/OSM/Node.hs
+++ b/Data/Geo/OSM/Node.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+
 -- | The @node@ element of a OSM file.
 module Data.Geo.OSM.Node(
                      Node,
@@ -32,30 +34,39 @@
 
 instance Lat Node where
   lat (Node x _ _) = x
+  setLat a (Node _ b c) = Node a b c
 
 instance Lon Node where
   lon (Node _ x _) = x
+  setLon b (Node a _ c) = Node a b c
 
 instance Id Node where
   id (Node _ _ x) = id x
+  setId c (Node a b cc) = Node a b (nwrCommon c (tags cc) (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Tags Node where
   tags (Node _ _ x) = tags x
+  setTags c (Node a b cc) = Node a b (nwrCommon (id cc) c (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Changeset Node where
   changeset (Node _ _ x) = changeset x
+  setChangeset c (Node a b cc) = Node a b (nwrCommon (id cc) (tags cc) c (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Visible Node where
   visible (Node _ _ x) = visible x
+  setVisible c (Node a b cc) = Node a b (nwrCommon (id cc) (tags cc) (changeset cc) c (user cc, uid cc) (timestamp cc))
 
-instance User Node where
+instance User Node (Maybe String) where
   user (Node _ _ x) = user x
+  setUser c (Node a b cc) = Node a b (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (c, uid cc) (timestamp cc))
 
 instance Uid Node where
   uid (Node _ _ x) = uid x
+  setUid c (Node a b cc) = Node a b (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, c) (timestamp cc))
 
-instance Timestamp Node where
+instance Timestamp Node (Maybe String) where
   timestamp (Node _ _ x) = timestamp x
+  setTimestamp c (Node a b cc) = Node a b (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, uid cc) c)
 
 -- | Constructs a node with a lat, lon, id, list of tags, changeset, visible, user&uid and timestamp.
 node :: String -- ^ The @lat@ attribute.
diff --git a/Data/Geo/OSM/OSM.hs b/Data/Geo/OSM/OSM.hs
--- a/Data/Geo/OSM/OSM.hs
+++ b/Data/Geo/OSM/OSM.hs
@@ -1,12 +1,26 @@
--- | The @osm@ element of a OSM file, which is the root element.
+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
+
+-- | The @osm@ element of a OSM file, which is the root element. <http://wiki.openstreetmap.org/wiki/API_v0.6/DTD>
 module Data.Geo.OSM.OSM(
                     OSM,
-                    osm
+                    osm,
+                    readOsmFile,
+                    readOsmFiles,
+                    interactOSMIO,
+                    interactsOSMIO,
+                    interactOSMIO',
+                    interactsOSMIO',
+                    interactOSM,
+                    interactsOSM,
+                    interactOSM',
+                    interactsOSM'
                   ) where
 
 import Text.XML.HXT.Arrow
 import Text.XML.HXT.Extras
-import Data.Geo.OSM.NodeWayRelation
+import Control.Monad
+import Data.List
+import Data.Geo.OSM.OSMChildren
 import Data.Geo.OSM.Bound
 import Data.Geo.OSM.Bounds
 import Data.Geo.OSM.Accessor.Version
@@ -15,37 +29,122 @@
 import Data.Geo.OSM.Accessor.NodeWayRelations
 
 -- | The @osm@ element of a OSM file, which is the root element.
-data OSM = OSM String (Maybe String) (Maybe (Either Bound Bounds)) [NodeWayRelation]
+data OSM = OSM String (Maybe String) (Maybe (Either Bound Bounds)) OSMChildren
   deriving Eq
 
 instance XmlPickler OSM where
-  xpickle = xpElem "osm" (xpWrap (\(version', generator', bound', nwr') -> OSM version' generator' bound' nwr', \(OSM version' generator' bound' nwr') -> (version', generator', bound', nwr'))
+  xpickle = xpElem "osm" (xpWrap (\(version', generator', bound', nwr') -> osm version' generator' bound' nwr', \(OSM version' generator' bound' nwr') -> (version', generator', bound', nwr'))
               (xp4Tuple (xpAttr "version" xpText)
                         (xpOption (xpAttr "generator" xpText))
                         (xpOption (xpAlt (either (const 0) (const 1)) [xpWrap (Left, \(Left b) -> b) xpickle, xpWrap (Right, \(Right b) -> b) xpickle]))
-                        (xpList1 xpickle)))
+                        xpickle))
 
 instance Show OSM where
   show = showPickled []
 
-instance Version OSM where
+instance Version OSM String where
   version (OSM x _ _ _) = x
+  setVersion a (OSM _ b c d) = osm a b c d
 
 instance Generator OSM where
   generator (OSM _ x _ _) = x
+  setGenerator b (OSM a _  c d) = osm a b c d
 
 instance BoundOrs OSM where
   boundOrs (OSM _ _ x _) n b bs = case x of Nothing -> n
                                             Just (Left b') -> b b'
                                             Just (Right b') -> bs b'
+  setBoundOrs c (OSM a b _ d) = osm a b c d
 
 instance NodeWayRelations OSM where
-  nwrs (OSM _ _ _ x) = x
+  nwrs (OSM _ _ _ x) = let t = const []
+                       in foldOSMChildren t t t t t id x
+  setNwrs d (OSM a b c _) = osm a b c (osmNodeWayRelation d)
 
 -- | Constructs a osm with a version, bound or bounds, and node attributes and way or relation elements.
 osm :: String -- ^ The @version@ attribute.
        -> Maybe String -- ^ The @generator@ attribute.
        -> Maybe (Either Bound Bounds) -- ^ The @bound@ or @bounds@ elements.
-       -> [NodeWayRelation] -- ^ The @node@, @way@ or @relation@ elements.
+       -> OSMChildren -- ^ The child elements.
        -> OSM
 osm = OSM
+
+-- | Reads an OSM file into a list of @OSM@ values removing whitespace.
+readOsmFile :: FilePath -> IO [OSM]
+readOsmFile = runX . xunpickleDocument (xpickle :: PU OSM) [(a_remove_whitespace, v_1)]
+
+-- | Reads 0 or more OSM files into a list of @OSM@ values removing whitespace.
+readOsmFiles :: [FilePath] -> IO [OSM]
+readOsmFiles = fmap join . (mapM readOsmFile)
+
+-- | Reads a OSM file, executes the given function on the XML, then writes the given file.
+interactOSMIO' :: Attributes -- ^ The options for reading the OSM file.
+                  -> FilePath -- ^ The OSM file to read.
+                  -> (OSM -> IO OSM) -- ^ The function to execute on the XML that is read.
+                  -> Attributes -- ^ The options for writing the OSM file.
+                  -> FilePath -- ^ The OSM file to write.
+                  -> IO ()
+interactOSMIO' froma from f toa to = runX (xunpickleDocument (xpickle :: PU OSM) froma from >>> arrIO f >>> xpickleDocument (xpickle :: PU OSM) toa to) >> return ()
+
+-- | Reads a OSM file, executes the given functions on the XML, then writes the given file.
+interactsOSMIO' :: Attributes -- ^ The options for reading the OSM file.
+                   -> FilePath -- ^ The OSM file to read.
+                   -> [OSM -> IO OSM] -- ^ The function to execute on the XML that is read.
+                   -> Attributes -- ^ The options for writing the OSM file.
+                   -> FilePath -- ^ The OSM file to write.
+                   -> IO ()
+interactsOSMIO' froma from = interactOSMIO' froma from . sumIO'
+
+-- | Reads a OSM file removing whitespace, executes the given function on the XML, then writes the given file with indentation.
+interactOSMIO :: FilePath -- ^ The OSM file to read.
+                 -> (OSM -> IO OSM) -- ^ The function to execute on the XML that is read.
+                 -> FilePath -- ^ The OSM file to write.
+                 -> IO ()
+interactOSMIO from f = interactOSMIO' [(a_remove_whitespace, v_1)] from f [(a_indent, v_1)]
+
+-- | Reads a OSM file removing whitespace, executes the given functions on the XML, then writes the given file with indentation.
+interactsOSMIO :: FilePath -- ^ The OSM file to read.
+                  -> [OSM -> IO OSM] -- ^ The function to execute on the XML that is read.
+                  -> FilePath -- ^ The OSM file to write.
+                  -> IO ()
+interactsOSMIO from = interactOSMIO from . sumIO'
+
+-- | Reads a OSM file, executes the given function on the XML, then writes the given file.
+interactOSM' :: Attributes -- ^ The options for reading the OSM file.
+                -> FilePath -- ^ The OSM file to read.
+                -> (OSM -> OSM) -- ^ The function to execute on the XML that is read.
+                -> Attributes -- ^ The options for writing the OSM file.
+                -> FilePath -- ^ The OSM file to write.
+                -> IO ()
+interactOSM' froma from f = interactOSMIO' froma from (return . f)
+
+-- | Reads a OSM file, executes the given functions on the XML, then writes the given file.
+interactsOSM' :: Attributes -- ^ The options for reading the OSM file.
+                 -> FilePath -- ^ The OSM file to read.
+                 -> [OSM -> OSM] -- ^ The functions to execute on the XML that is read.
+                 -> Attributes -- ^ The options for writing the OSM file.
+                 -> FilePath -- ^ The OSM file to write.
+                 -> IO ()
+interactsOSM' froma from = interactOSM' froma from . sum'
+
+-- | Reads a OSM file removing whitespace, executes the given function on the XML, then writes the given file with indentation.
+interactOSM :: FilePath -- ^ The OSM file to read.
+               -> (OSM -> OSM) -- ^ The function to execute on the XML that is read.
+               -> FilePath -- ^ The OSM file to write.
+               -> IO ()
+interactOSM from f = interactOSMIO from (return . f)
+
+-- | Reads a OSM file removing whitespace, executes the given functions on the XML, then writes the given file with indentation.
+interactsOSM :: FilePath -- ^ The OSM file to read.
+                -> [OSM -> OSM] -- ^ The function to execute on the XML that is read.
+                -> FilePath -- ^ The OSM file to write.
+                -> IO ()
+interactsOSM from = interactOSM from . sum'
+
+-- not exported
+
+sum' :: [a -> a] -> a -> a
+sum' = foldl' (.) id
+
+sumIO' :: (Monad m) => [a -> m a] -> a -> m a
+sumIO' x = foldl' (>=>) return x
diff --git a/Data/Geo/OSM/OSMChildren.hs b/Data/Geo/OSM/OSMChildren.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/OSMChildren.hs
@@ -0,0 +1,76 @@
+-- | The children elements of the @osm@ element of a OSM file.
+module Data.Geo.OSM.OSMChildren(
+                                 OSMChildren,
+                                 osmUser,
+                                 osmGpxFile,
+                                 osmApi,
+                                 osmChangeset,
+                                 osmNodeWayRelation,
+                                 foldOSMChildren
+                               ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.UserE
+import Data.Geo.OSM.Preferences
+import Data.Geo.OSM.GpxFile
+import Data.Geo.OSM.Api
+import Data.Geo.OSM.ChangesetE
+import Data.Geo.OSM.NodeWayRelation
+
+-- | The children elements of the @osm@ element of a OSM file.
+data OSMChildren = UserE UserE | Preferences Preferences | GpxFile GpxFile | Api Api | ChangesetE ChangesetE | NWR [NodeWayRelation]
+  deriving Eq
+
+instance XmlPickler OSMChildren where
+  xpickle = xpAlt (\r -> case r of UserE _       -> 0
+                                   Preferences _ -> 1
+                                   GpxFile _     -> 2
+                                   Api _         -> 3
+                                   ChangesetE _  -> 4
+                                   NWR _         -> 5) [xpWrap (UserE, \(UserE u) -> u) xpickle,
+                                                        xpWrap (Preferences, \(Preferences p) -> p) xpickle,
+                                                        xpWrap (GpxFile, \(GpxFile f) -> f) xpickle,
+                                                        xpWrap (Api, \(Api a) -> a) xpickle,
+                                                        xpWrap (ChangesetE, \(ChangesetE c) -> c) xpickle,
+                                                        xpWrap (NWR, \(NWR k) -> k) (xpList xpickle)]
+
+instance Show OSMChildren where
+  show = showPickled []
+
+-- | A @user@ element.
+osmUser :: UserE -> OSMChildren
+osmUser = UserE
+
+-- | A @gpx_file@ element.
+osmGpxFile :: GpxFile -> OSMChildren
+osmGpxFile = GpxFile
+
+-- | A @api@ element.
+osmApi :: Api -> OSMChildren
+osmApi = Api
+
+-- | A @changeset@ element.
+osmChangeset :: ChangesetE -> OSMChildren
+osmChangeset = ChangesetE
+
+-- | A list of @node@, @way@ or @relation@ elements.
+osmNodeWayRelation :: [NodeWayRelation] -> OSMChildren
+osmNodeWayRelation = NWR
+
+-- | Folds OSM child elements (catamorphism).
+foldOSMChildren
+  :: (UserE -> a) -- ^ If a @user@ element.
+     -> (Preferences -> a) -- ^ If a @preferences@ element.
+     -> (GpxFile -> a) -- ^ If a @gpx_file@ element.
+     -> (Api -> a) -- ^ If a @api@ element.
+     -> (ChangesetE -> a) -- ^ If a @changeset@ element.
+     -> ([NodeWayRelation] -> a) -- ^ If a list of @node@, @way@ or @relation@ elements.
+     -> OSMChildren -- ^ The disjunctive type of child elements.
+     -> a
+foldOSMChildren z _ _ _ _ _ (UserE u) = z u
+foldOSMChildren _ z _ _ _ _ (Preferences p) = z p
+foldOSMChildren _ _ z _ _ _ (GpxFile f) = z f
+foldOSMChildren _ _ _ z _ _ (Api a) = z a
+foldOSMChildren _ _ _ _ z _ (ChangesetE c) = z c
+foldOSMChildren _ _ _ _ _ z (NWR k) = z k
diff --git a/Data/Geo/OSM/Preferences.hs b/Data/Geo/OSM/Preferences.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Preferences.hs
@@ -0,0 +1,29 @@
+-- | The @preferences@ element of a OSM file.
+module Data.Geo.OSM.Preferences(
+                                 Preferences,
+                                 preferences
+                               ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Tag
+import Data.Geo.OSM.Accessor.Tags
+
+-- | The @preferences@ element of a OSM file.
+newtype Preferences = Preferences [Tag]
+  deriving Eq
+
+-- | Constructs a @preferences@ with tags.
+preferences :: [Tag] -- ^ The list of tags (@tag@ elements).
+               -> Preferences
+preferences = Preferences
+
+instance XmlPickler Preferences where
+  xpickle = xpElem "preferences" (xpWrap (preferences, \(Preferences r) -> r) (xpList xpickle))
+
+instance Show Preferences where
+  show = showPickled []
+
+instance Tags Preferences where
+  tags (Preferences x) = x
+  setTags a (Preferences _) = preferences a
diff --git a/Data/Geo/OSM/Relation.hs b/Data/Geo/OSM/Relation.hs
--- a/Data/Geo/OSM/Relation.hs
+++ b/Data/Geo/OSM/Relation.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+
 -- | The @relation@ element of a OSM file.
 module Data.Geo.OSM.Relation(
                          Relation,
@@ -32,27 +34,35 @@
 
 instance Members Relation where
   members (Relation x _) = x
+  setMembers a (Relation _ c) = Relation a c
 
 instance Id Relation where
   id (Relation _ x) = id x
+  setId c (Relation a cc) = Relation a (nwrCommon c (tags cc) (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Tags Relation where
   tags (Relation _ x) = tags x
+  setTags c (Relation a cc) = Relation a (nwrCommon (id cc) c (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Changeset Relation where
   changeset (Relation _ x) = changeset x
+  setChangeset c (Relation a cc) = Relation a (nwrCommon (id cc) (tags cc) c (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Visible Relation where
   visible (Relation _ x) = visible x
+  setVisible c (Relation a cc) = Relation a (nwrCommon (id cc) (tags cc) (changeset cc) c (user cc, uid cc) (timestamp cc))
 
-instance User Relation where
+instance User Relation (Maybe String) where
   user (Relation _ x) = user x
+  setUser c (Relation a cc) = Relation a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (c, uid cc) (timestamp cc))
 
 instance Uid Relation where
   uid (Relation _ x) = uid x
+  setUid c (Relation a cc) = Relation a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, c) (timestamp cc))
 
-instance Timestamp Relation where
+instance Timestamp Relation (Maybe String) where
   timestamp (Relation _ x) = timestamp x
+  setTimestamp c (Relation a cc) = Relation a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, uid cc) c)
 
 -- | Constructs a relation with a list of members, id, list of tags, changeset, visible, user&uid and timestamp.
 relation :: [Member] -- ^ The list of members (@member@ elements).
diff --git a/Data/Geo/OSM/Tag.hs b/Data/Geo/OSM/Tag.hs
--- a/Data/Geo/OSM/Tag.hs
+++ b/Data/Geo/OSM/Tag.hs
@@ -14,16 +14,18 @@
   deriving Eq
 
 instance XmlPickler Tag where
-  xpickle = xpElem "tag" (xpWrap (uncurry Tag, \(Tag k' v') -> (k', v')) (xpPair (xpAttr "k" xpText) (xpAttr "v" xpText)))
+  xpickle = xpElem "tag" (xpWrap (uncurry tag, \(Tag k' v') -> (k', v')) (xpPair (xpAttr "k" xpText) (xpAttr "v" xpText)))
 
 instance Show Tag where
   show = showPickled []
 
 instance K Tag where
   k (Tag x _) = x
+  setK a (Tag _ b) = tag a b
 
 instance V Tag where
   v (Tag _ x) = x
+  setV b (Tag a _) = tag a b
 
 -- | Constructs a tag with a key and value.
 tag :: String -- ^ The key (@k@ attribute).
diff --git a/Data/Geo/OSM/Tracepoints.hs b/Data/Geo/OSM/Tracepoints.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Tracepoints.hs
@@ -0,0 +1,28 @@
+-- | The @tracepoints@ element of a OSM file.
+module Data.Geo.OSM.Tracepoints(
+                                 Tracepoints,
+                                 tracepoints
+                               ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Accessor.PerPage
+
+-- | The @tracepoints@ element of a OSM file.
+newtype Tracepoints = Tracepoints String
+  deriving Eq
+
+-- | Constructs a @tracepoints@ with per_page.
+tracepoints :: String -- ^ The @per_page@ attribute.
+               -> Tracepoints
+tracepoints = Tracepoints
+
+instance XmlPickler Tracepoints where
+  xpickle = xpElem "tracepoints" (xpWrap (tracepoints, \(Tracepoints r) -> r) (xpAttr "per_page" xpText))
+
+instance Show Tracepoints where
+  show = showPickled []
+
+instance PerPage Tracepoints where
+  perPage (Tracepoints x) = x
+  setPerPage a (Tracepoints _) = tracepoints a
diff --git a/Data/Geo/OSM/UserE.hs b/Data/Geo/OSM/UserE.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/UserE.hs
@@ -0,0 +1,41 @@
+-- | The @user@ element of a OSM file.
+module Data.Geo.OSM.UserE(
+                           UserE,
+                           userE
+                         ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Home
+import Data.Geo.OSM.Accessor.Hm
+import Data.Geo.OSM.Accessor.DisplayName
+import Data.Geo.OSM.Accessor.AccountCreated
+
+-- | The @user@ element of a OSM file.
+data UserE = UserE (Maybe Home) String String
+  deriving Eq
+
+-- | Constructs a @user@ with an optional home, display_name and account_created.
+userE :: Maybe Home -- ^ The @home@ element.
+         -> String -- ^ The @display_name@ attribute.
+         -> String -- ^ The @account_created@ attribute.
+         -> UserE
+userE = UserE
+
+instance XmlPickler UserE where
+  xpickle = xpElem "user" (xpWrap (\(home', dn', ac') -> userE home' dn' ac', \(UserE home' dn' ac') -> (home', dn', ac')) (xpTriple (xpOption (xpElem "home" xpickle)) (xpAttr "display_name" xpText) (xpAttr "account_created" xpText)))
+
+instance Show UserE where
+  show = showPickled []
+
+instance Hm UserE where
+  hm (UserE x _ _) = x
+  setHm a (UserE _ b c) = userE a b c
+
+instance DisplayName UserE where
+  displayName (UserE _ x _) = x
+  setDisplayName b (UserE a _ c) = userE a b c
+
+instance AccountCreated UserE where
+  accountCreated (UserE _ _ x) = x
+  setAccountCreated c (UserE a b _) = userE a b c
diff --git a/Data/Geo/OSM/VersionE.hs b/Data/Geo/OSM/VersionE.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/VersionE.hs
@@ -0,0 +1,34 @@
+-- | The @version@ element of a OSM file.
+module Data.Geo.OSM.VersionE(
+                               VersionE,
+                               versionE
+                            ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Accessor.Minimum
+import Data.Geo.OSM.Accessor.Maximum
+
+-- | The @version@ element of a OSM file.
+data VersionE = VersionE String String
+  deriving Eq
+
+-- | Constructs a @version@ with minimum and maximum.
+versionE :: String -- ^ The @minimum@ attribute.
+            -> String -- ^ The @maximum@ attribute.
+            -> VersionE
+versionE = VersionE
+
+instance XmlPickler VersionE where
+  xpickle = xpElem "version" (xpWrap (uncurry versionE, \(VersionE min' max') -> (min', max')) (xpPair (xpAttr "minimum" xpText) (xpAttr "maximum" xpText)))
+
+instance Show VersionE where
+  show = showPickled []
+
+instance Minimum VersionE where
+  minimum (VersionE x _) = x
+  setMinimum a (VersionE _ b) = versionE a b
+
+instance Maximum VersionE where
+  maximum (VersionE _ x) = x
+  setMaximum b (VersionE a _) = versionE a b
diff --git a/Data/Geo/OSM/Way.hs b/Data/Geo/OSM/Way.hs
--- a/Data/Geo/OSM/Way.hs
+++ b/Data/Geo/OSM/Way.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+
 -- | The @way@ element of a OSM file.
 module Data.Geo.OSM.Way(
                     Way,
@@ -32,27 +34,35 @@
 
 instance Nds Way where
   nds (Way x _) = x
+  setNds a (Way _ c) = Way a c
 
 instance Id Way where
   id (Way _ x) = id x
+  setId c (Way a cc) = Way a (nwrCommon c (tags cc) (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Tags Way where
   tags (Way _ x) = tags x
+  setTags c (Way a cc) = Way a (nwrCommon (id cc) c (changeset cc) (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Changeset Way where
   changeset (Way _ x) = changeset x
+  setChangeset c (Way a cc) = Way a (nwrCommon (id cc) (tags cc) c (visible cc) (user cc, uid cc) (timestamp cc))
 
 instance Visible Way where
   visible (Way _ x) = visible x
+  setVisible c (Way a cc) = Way a (nwrCommon (id cc) (tags cc) (changeset cc) c (user cc, uid cc) (timestamp cc))
 
-instance User Way where
+instance User Way (Maybe String) where
   user (Way _ x) = user x
+  setUser c (Way a cc) = Way a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (c, uid cc) (timestamp cc))
 
 instance Uid Way where
   uid (Way _ x) = uid x
+  setUid c (Way a cc) = Way a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, c) (timestamp cc))
 
-instance Timestamp Way where
+instance Timestamp Way (Maybe String) where
   timestamp (Way _ x) = timestamp x
+  setTimestamp c (Way a cc) = Way a (nwrCommon (id cc) (tags cc) (changeset cc) (visible cc) (user cc, uid cc) c)
 
 -- | Constructs a way with a list of nds, id, list of tags, changeset, visible, user&uid and timestamp.
 way :: [Nd] -- ^ The list of nds (@nd@ elements).
diff --git a/Data/Geo/OSM/Waynodes.hs b/Data/Geo/OSM/Waynodes.hs
new file mode 100644
--- /dev/null
+++ b/Data/Geo/OSM/Waynodes.hs
@@ -0,0 +1,28 @@
+-- | The @waynodes@ element of a OSM file.
+module Data.Geo.OSM.Waynodes(
+                              Waynodes,
+                              waynodes
+                            ) where
+
+import Text.XML.HXT.Arrow
+import Text.XML.HXT.Extras
+import Data.Geo.OSM.Accessor.Maximum
+
+-- | The @waynodes@ element of a OSM file.
+newtype Waynodes = Waynodes String
+  deriving Eq
+
+-- | Constructs a @waynodes@ with maximum.
+waynodes :: String -- ^ The @maximum@ attribute.
+            -> Waynodes
+waynodes = Waynodes
+
+instance XmlPickler Waynodes where
+  xpickle = xpElem "waynodes" (xpWrap (waynodes, \(Waynodes r) -> r) (xpAttr "maximum" xpText))
+
+instance Show Waynodes where
+  show = showPickled []
+
+instance Maximum Waynodes where
+  maximum (Waynodes x) = x
+  setMaximum a (Waynodes _) = waynodes a
diff --git a/OSM.cabal b/OSM.cabal
--- a/OSM.cabal
+++ b/OSM.cabal
@@ -1,10 +1,10 @@
 Name:                OSM
-Version:             0.3
+Version:             0.4.0
 License:             BSD3
 License-File:        LICENSE
 Synopsis:            Parse OpenStreetMap files
 Description:         Parse OpenStreetMap http:\/\/osm.org/ files using HXT into data structures.
-                     The Geo.OSM module is the core module that exports all others.
+                     The Data.Geo.OSM module is the core module that exports all others.
 Homepage:            http://code.google.com/p/geo-osm/
 Category:            Utils
 Author:              Tony Morris
@@ -12,7 +12,6 @@
 Copyright:           2009 Tony Morris
 build-type:          Simple
 cabal-version:       >= 1.2
-extra-source-files:  etc/Example.hs, etc/MountBarney.osm
 
 Flag small_base
   Description:     Choose the new, split-up base package.
@@ -25,41 +24,66 @@
 
   GHC-Options:    -Wall
   Exposed-Modules: Data.Geo.OSM
-                   Data.Geo.OSM.Tag
+                   Data.Geo.OSM.Api
+                   Data.Geo.OSM.Area
+                   Data.Geo.OSM.Bound
+                   Data.Geo.OSM.Bounds
+                   Data.Geo.OSM.ChangesetE
+                   Data.Geo.OSM.GpxFile
+                   Data.Geo.OSM.Home
                    Data.Geo.OSM.Nd
+                   Data.Geo.OSM.Node
+                   Data.Geo.OSM.NodeWayRelation
                    Data.Geo.OSM.NWRCommon
                    Data.Geo.OSM.MemberType
                    Data.Geo.OSM.Member
-                   Data.Geo.OSM.Way
-                   Data.Geo.OSM.Node
-                   Data.Geo.OSM.Relation
-                   Data.Geo.OSM.Bounds
-                   Data.Geo.OSM.Bound
-                   Data.Geo.OSM.NodeWayRelation
                    Data.Geo.OSM.OSM
-                   Data.Geo.OSM.Accessor.K
-                   Data.Geo.OSM.Accessor.V
-                   Data.Geo.OSM.Accessor.Ref
-                   Data.Geo.OSM.Accessor.Mtype
-                   Data.Geo.OSM.Accessor.Role
-                   Data.Geo.OSM.Accessor.Id
-                   Data.Geo.OSM.Accessor.Tags
+                   Data.Geo.OSM.OSMChildren
+                   Data.Geo.OSM.Preferences
+                   Data.Geo.OSM.Relation
+                   Data.Geo.OSM.Tag
+                   Data.Geo.OSM.Tracepoints
+                   Data.Geo.OSM.UserE
+                   Data.Geo.OSM.VersionE
+                   Data.Geo.OSM.Way
+                   Data.Geo.OSM.Waynodes
+                   Data.Geo.OSM.Accessor.Accessor
+                   Data.Geo.OSM.Accessor.AccountCreated
+                   Data.Geo.OSM.Accessor.Ar
+                   Data.Geo.OSM.Accessor.BoundOrs
+                   Data.Geo.OSM.Accessor.Box
                    Data.Geo.OSM.Accessor.Changeset
-                   Data.Geo.OSM.Accessor.Visible
-                   Data.Geo.OSM.Accessor.User
-                   Data.Geo.OSM.Accessor.Uid
-                   Data.Geo.OSM.Accessor.Timestamp
-                   Data.Geo.OSM.Accessor.Nds
+                   Data.Geo.OSM.Accessor.DisplayName
+                   Data.Geo.OSM.Accessor.Generator
+                   Data.Geo.OSM.Accessor.Hm
+                   Data.Geo.OSM.Accessor.Id
+                   Data.Geo.OSM.Accessor.K
                    Data.Geo.OSM.Accessor.Lat
                    Data.Geo.OSM.Accessor.Lon
                    Data.Geo.OSM.Accessor.Members
-                   Data.Geo.OSM.Accessor.Minlat
+                   Data.Geo.OSM.Accessor.Maximum
                    Data.Geo.OSM.Accessor.Maxlat
-                   Data.Geo.OSM.Accessor.Minlon
                    Data.Geo.OSM.Accessor.Maxlon
+                   Data.Geo.OSM.Accessor.Minimum
+                   Data.Geo.OSM.Accessor.Minlat
+                   Data.Geo.OSM.Accessor.Minlon
+                   Data.Geo.OSM.Accessor.Mtype
+                   Data.Geo.OSM.Accessor.Name
+                   Data.Geo.OSM.Accessor.Nds
+                   Data.Geo.OSM.Accessor.NodeWayRelations
                    Data.Geo.OSM.Accessor.Origin
-                   Data.Geo.OSM.Accessor.Box
+                   Data.Geo.OSM.Accessor.Pending
+                   Data.Geo.OSM.Accessor.PerPage
+                   Data.Geo.OSM.Accessor.Public
+                   Data.Geo.OSM.Accessor.Ref
+                   Data.Geo.OSM.Accessor.Role
+                   Data.Geo.OSM.Accessor.Tags
+                   Data.Geo.OSM.Accessor.Timestamp
+                   Data.Geo.OSM.Accessor.Tpoints
+                   Data.Geo.OSM.Accessor.User
+                   Data.Geo.OSM.Accessor.Uid
+                   Data.Geo.OSM.Accessor.V
                    Data.Geo.OSM.Accessor.Version
-                   Data.Geo.OSM.Accessor.Generator
-                   Data.Geo.OSM.Accessor.BoundOrs
-                   Data.Geo.OSM.Accessor.NodeWayRelations
+                   Data.Geo.OSM.Accessor.Visible
+                   Data.Geo.OSM.Accessor.Wnodes
+                   Data.Geo.OSM.Accessor.Zoom
diff --git a/etc/Example.hs b/etc/Example.hs
deleted file mode 100644
--- a/etc/Example.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-import Geo.OSM
-
--- Return all nodes tagged as camp-sites (tourism=camp_site) in the given OSM file.
-campSites :: FilePath -> IO [Node]
-campSites f = let p = filter ("tourism" `hasTagValue` "camp_site") . (nodes =<<)
-              in fmap p (runX (xunpickleDocument (xpickle :: PU OSM) [(a_remove_whitespace, v_1)] f))
-
-
-
-{-
-
-
-*Main> campSites "MountBarney.osm"
-[<node lat="-28.309999" lon="152.460006" id="316587114" changeset="108027" user="Spindoc Bob" uid="11037" timestamp="2008-12-04T11:00:06Z"><tag k="name" v="Koreelah Creek Campground - Koreelah NP"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2131914" lon="152.4264518" id="596132847" changeset="3406101" user="Tony Morris" uid="66376" timestamp="2009-12-19T11:19:14Z"><tag k="name" v="Emu Creek"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.389999" lon="152.61" id="316587113" changeset="108027" user="Spindoc Bob" uid="11037" timestamp="2008-12-04T11:00:05Z"><tag k="name" v="Woodenbong Campground"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2819309" lon="152.690921" id="440615858" changeset="3405819" user="Tony Morris" uid="66376" timestamp="2009-12-19T10:37:58Z"><tag k="name" v="Rum Jungle"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2812388" lon="152.6916212" id="596096271" changeset="3405991" user="Tony Morris" uid="66376" timestamp="2009-12-19T11:02:19Z"><tag k="name" v="Old Hut Site"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2961173" lon="152.7150912" id="596098699" changeset="3405772" user="Tony Morris" uid="66376" timestamp="2009-12-19T10:31:22Z"><tag k="name" v="Site 10"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.299066" lon="152.7198659" id="596098700" changeset="3405772" user="Tony Morris" uid="66376" timestamp="2009-12-19T10:31:22Z"><tag k="name" v="Site 9"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2056648" lon="152.6679486" id="442564691" changeset="1844269" user="Tony Morris" uid="66376" timestamp="2009-07-16T12:44:51Z"><tag k="tourism" v="camp_site"/></node>,<node lat="-28.219999" lon="152.86" id="316607159" changeset="108027" user="Spindoc Bob" uid="11037" timestamp="2008-12-04T11:57:12Z"><tag k="name" v="EM Tilley Park"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.209999" lon="152.770004" id="316607169" changeset="1824310" user="Tony Morris" uid="66376" timestamp="2009-07-14T08:21:51Z"><tag k="name" v="Flanagan Reserve"/><tag k="tourism" v="camp_site"/></node>,<node lat="-28.2" lon="152.779998" id="316607407" changeset="108027" user="Spindoc Bob" uid="11037" timestamp="2008-12-04T11:57:28Z"><tag k="name" v="Bigriggen Park Reserve"/><tag k="tourism" v="camp_site"/></node>]
-
-
--}
diff --git a/etc/MountBarney.osm b/etc/MountBarney.osm
deleted file mode 100644
# file too large to diff: etc/MountBarney.osm
