diff --git a/instant-xml-macros/src/ser.rs b/instant-xml-macros/src/ser.rs index b036a18..7ea8e51 100644 --- a/instant-xml-macros/src/ser.rs +++ b/instant-xml-macros/src/ser.rs @@ -298,7 +298,9 @@ fn named_field( attributes.extend(quote!( #error - serializer.write_attr(#tag, #ns, &self.#field_name)?; + if self.#field_name.present() { + serializer.write_attr(#tag, #ns, &self.#field_name)?; + } )); return Ok(()); } diff --git a/instant-xml/src/impls.rs b/instant-xml/src/impls.rs index 5b90b36..ea5e237 100644 --- a/instant-xml/src/impls.rs +++ b/instant-xml/src/impls.rs @@ -453,6 +453,10 @@ impl ToXml for Option { None => Ok(()), } } + + fn present(&self) -> bool { + self.is_some() + } } fn encode(input: &str) -> Result, Error> { diff --git a/instant-xml/src/lib.rs b/instant-xml/src/lib.rs index 8c52888..5de63c4 100644 --- a/instant-xml/src/lib.rs +++ b/instant-xml/src/lib.rs @@ -20,6 +20,10 @@ pub trait ToXml { field: Option>, serializer: &mut Serializer, ) -> Result<(), Error>; + + fn present(&self) -> bool { + true + } } impl<'a, T: ToXml + ?Sized> ToXml for &'a T { diff --git a/instant-xml/tests/option.rs b/instant-xml/tests/option.rs index e776a93..17dcc47 100644 --- a/instant-xml/tests/option.rs +++ b/instant-xml/tests/option.rs @@ -17,3 +17,24 @@ fn option_vec() { assert_eq!(xml, to_string(&v).unwrap()); assert_eq!(v, from_str(xml).unwrap()); } + +#[derive(Debug, Eq, FromXml, PartialEq, ToXml)] +struct Bar<'a> { + #[xml(attribute, borrow)] + maybe: Option<&'a str>, +} + +#[test] +fn option_borrow() { + let v = Bar { maybe: Some("a") }; + let xml = r#""#; + + assert_eq!(xml, to_string(&v).unwrap()); + assert_eq!(v, from_str(xml).unwrap()); + + let v = Bar { maybe: None }; + let xml = r#""#; + + assert_eq!(xml, to_string(&v).unwrap()); + assert_eq!(v, from_str(xml).unwrap()); +}