diff --git a/src/lib.rs b/src/lib.rs
index eae2b310cc2ae546335425ef8fbb3fa4e6046196..7f1d4b821611aef47dbfadb925f80770f783057b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -325,11 +325,11 @@ pub struct Tileset {
 impl Tileset {
     fn new<R: Read>(parser: &mut EventReader<R>, attrs: Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> {
         Tileset::new_internal(parser, &attrs)
-            .or_else(|_| { Tileset::new_external(&attrs, map_path) })
+            .or_else(|_| { Tileset::new_reference(&attrs, map_path) })
     }
 
     fn new_internal<R: Read>(parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> {
-        let ((s, m), (g, n, w, h)) = get_attrs!(
+        let ((spacing, margin), (first_gid, name, width, height)) = get_attrs!(
            attrs,
            optionals: [("spacing", spacing, |v:String| v.parse().ok()),
                        ("margin", margin, |v:String| v.parse().ok())],
@@ -351,17 +351,17 @@ impl Tileset {
                         Ok(())
                    });
 
-        Ok(Tileset {first_gid: g,
-                    name: n,
-                    tile_width: w, tile_height: h,
-                    spacing: s.unwrap_or(0),
-                    margin: m.unwrap_or(0),
+        Ok(Tileset {first_gid: first_gid,
+                    name: name,
+                    tile_width: width, tile_height: height,
+                    spacing: spacing.unwrap_or(0),
+                    margin: margin.unwrap_or(0),
                     images: images,
                     tiles: tiles})
     }
 
-    fn new_external(attrs: &Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> {
-        let ((), (g, source)) = get_attrs!(
+    fn new_reference(attrs: &Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> {
+        let ((), (first_gid, source)) = get_attrs!(
            attrs,
            optionals: [],
            required: [("firstgid", first_gid, |v:String| v.parse().ok()),
@@ -370,12 +370,16 @@ impl Tileset {
 
         let tileset_path = map_path.ok_or(TiledError::Other("Maps with external tilesets must know their file location.  See parse_with_path(Path).".to_string()))?.with_file_name(source);
         let file = File::open(&tileset_path).map_err(|_| TiledError::Other(format!("External tileset file not found: {:?}", tileset_path)))?;
+        Tileset::new_external(file, first_gid)
+    }
+
+    fn new_external<R: Read>(file: R, first_gid: u32) -> Result<Tileset, TiledError> {
         let mut tileset_parser = EventReader::new(file);
         loop {
             match try!(tileset_parser.next().map_err(TiledError::XmlDecodingError)) {
                 XmlEvent::StartElement {name, attributes, ..}  => {
                     if name.local_name == "tileset" {
-                        return Tileset::parse_external_tileset(g, &mut tileset_parser, &attributes)
+                        return Tileset::parse_external_tileset(first_gid, &mut tileset_parser, &attributes)
                     }
                 }
                 XmlEvent::EndDocument => return Err(TiledError::PrematureEnd("Tileset Document ended before map was parsed".to_string())),
@@ -384,8 +388,8 @@ impl Tileset {
         }
     }
 
-    fn parse_external_tileset<R: Read>(g: u32, parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> {
-        let ((s, m), (n, w, h)) = get_attrs!(
+    fn parse_external_tileset<R: Read>(first_gid: u32, parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> {
+        let ((spacing, margin), (name, width, height)) = get_attrs!(
             attrs,
             optionals: [("spacing", spacing, |v:String| v.parse().ok()),
                         ("margin", margin, |v:String| v.parse().ok())],
@@ -406,11 +410,11 @@ impl Tileset {
                        Ok(())
                    });
 
-        Ok(Tileset {first_gid: g,
-                    name: n,
-                    tile_width: w, tile_height: h,
-                    spacing: s.unwrap_or(0),
-                    margin: m.unwrap_or(0),
+        Ok(Tileset {first_gid: first_gid,
+                    name: name,
+                    tile_width: width, tile_height: height,
+                    spacing: spacing.unwrap_or(0),
+                    margin: margin.unwrap_or(0),
                     images: images,
                     tiles: tiles})
     }
@@ -800,3 +804,12 @@ pub fn parse_file(path: &Path) -> Result<Map, TiledError> {
 pub fn parse<R: Read>(reader: R) -> Result<Map, TiledError> {
     parse_impl(reader, None)
 }
+
+/// Parse a buffer hopefully containing the contents of a Tiled tileset.
+///
+/// External tilesets do not have a firstgid attribute.  That lives in the
+/// map. You must pass in `first_gid`.  If you do not need to use gids for anything,
+/// passing in 1 will work fine.
+pub fn parse_tileset<R: Read>(reader: R, first_gid: u32) -> Result<Tileset, TiledError> {
+    Tileset::new_external(reader, first_gid)
+}
diff --git a/tests/lib.rs b/tests/lib.rs
index 233ba7f84014a988ea17fd848576619ff1fd32db..6ac8a9990b7c20ab8b63e5ba2b704bc68eabea60 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -2,7 +2,7 @@ extern crate tiled;
 
 use std::path::Path;
 use std::fs::File;
-use tiled::{Map, TiledError, parse, parse_file};
+use tiled::{Map, TiledError, parse, parse_file, parse_tileset};
 
 fn read_from_file(p: &Path) -> Result<Map, TiledError> {
     let file = File::open(p).unwrap();
@@ -30,3 +30,10 @@ fn test_external_tileset() {
     let e = read_from_file_with_path(&Path::new("assets/tiled_base64_external.tmx")).unwrap();
     assert_eq!(r, e);
 }
+
+#[test]
+fn test_just_tileset() {
+    let r = read_from_file(&Path::new("assets/tiled_base64.tmx")).unwrap();
+    let t = parse_tileset(File::open(Path::new("assets/tilesheet.tsx")).unwrap(), 1).unwrap();
+    assert_eq!(r.tilesets[0], t);
+}