diff --git a/assets/tiled_base64_zstandard.tmx b/assets/tiled_base64_zstandard.tmx
index 3fba1dd76844ba6a0922959030aa15f979d12e45..8be916f9c5add82ed78bfccd53e180eac9352618 100644
--- a/assets/tiled_base64_zstandard.tmx
+++ b/assets/tiled_base64_zstandard.tmx
@@ -15,6 +15,11 @@
   <properties>
    <property name="prop1" value="12"/>
    <property name="prop2" value="some text"/>
+   <property name="prop3">Line 1
+Line 2
+Line 3,
+  etc
+   </property>
   </properties>
   <data encoding="base64" compression="zstd">
    KLUv/WBAm6UFAPgjAAAAIREtLgAAAC8RACMfHy0tLi0tLSMjIyMjIyMjSaBguwAAg0JmtQEFA2qvb+Al6lHUO91VvxpMveegXVabfkkjaEj1wZVZeNWPbSrdISdZk1b145uYEEFAvQmwiF5zTMi2QsOb9Vhv7ZxsK27ZJBXC9lYf2mVdhuqWjb8/hITgZAMw1ctxfXIOXBaofKbranfWDTtJ/Xyz7E2ZNWzVKauthC4r26Ry1TnnDqtmvUfyDw==
diff --git a/src/properties.rs b/src/properties.rs
index 088eaa1a4265671d6eee3da53834ef412e921377..dfc2976d81ef399ea14ea4ce768f186234341042 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -87,7 +87,7 @@ pub(crate) fn parse_properties<R: Read>(
     let mut p = HashMap::new();
     parse_tag!(parser, "properties", {
         "property" => |attrs:Vec<OwnedAttribute>| {
-            let ((t, mut v), k) = get_attrs!(
+            let ((t, v_attr), k) = get_attrs!(
                 attrs,
                 optionals: [
                     ("type", property_type, |v| Some(v)),
@@ -99,19 +99,19 @@ pub(crate) fn parse_properties<R: Read>(
                 TiledError::MalformedAttributes("property must have a name and a value".to_string())
             );
             let t = t.unwrap_or("string".into());
-            if v.is_none() {
-                v = Some(match parser.next().map_err(TiledError::XmlDecodingError)? {
-                    XmlEvent::Characters(s) => {
-                        Ok(s)
-                    }
-                    XmlEvent::EndElement { name, .. } => {
-                        Err(TiledError::MalformedAttributes("property must have a name and a value".to_string()))
-                    }
-                    _ => Err(TiledError::MalformedAttributes("?".to_string()))
-                }?);
-            }
+            
+            let v = match v_attr {
+                Some(val) => val,
+                None => {
+                    // if the "value" attribute was missing, might be a multiline string
+                    match parser.next().map_err(TiledError::XmlDecodingError)? {
+                        XmlEvent::Characters(s) => Ok(s),
+                        _ => Err(TiledError::MalformedAttributes(format!("property '{}' is missing a value", k))),
+                    }?
+                }
+            };
 
-            p.insert(k, PropertyValue::new(t, v.expect("Missing value"))?);
+            p.insert(k, PropertyValue::new(t, v)?);
             Ok(())
         },
     });