diff --git a/crates/xml/derive/src/field.rs b/crates/xml/derive/src/field.rs index 8a6f302..3c7302d 100644 --- a/crates/xml/derive/src/field.rs +++ b/crates/xml/derive/src/field.rs @@ -246,6 +246,25 @@ impl Field { }) } + pub fn namespace_branch(&self) -> Option { + if self.attrs.xml_ty != FieldType::Namespace { + return None; + } + let builder_field_ident = self.builder_field_ident(); + + let value = quote! { + if let ::quick_xml::name::ResolveResult::Bound(ns) = &ns { + Some(rustical_xml::ValueDeserialize::deserialize(&String::from_utf8_lossy(ns.0.as_ref()))?) + } else { + None + } + }; + + Some(quote! { + builder.#builder_field_ident = #value; + }) + } + pub fn tagname_branch(&self) -> Option { if self.attrs.xml_ty != FieldType::TagName { return None; diff --git a/crates/xml/derive/src/xml_struct.rs b/crates/xml/derive/src/xml_struct.rs index e4a9eab..bb0d5c3 100644 --- a/crates/xml/derive/src/xml_struct.rs +++ b/crates/xml/derive/src/xml_struct.rs @@ -1,5 +1,5 @@ -use crate::attrs::{FieldType, StructAttrs}; use crate::Field; +use crate::attrs::{FieldType, StructAttrs}; use core::panic; use darling::FromDeriveInput; use quote::quote; @@ -115,6 +115,7 @@ impl NamedStruct { self.fields.iter().filter_map(Field::text_branch).collect(); let attr_field_branches = self.fields.iter().filter_map(Field::attr_branch); let tagname_field_branches = self.fields.iter().filter_map(Field::tagname_branch); + let namespace_field_branches = self.fields.iter().filter_map(Field::namespace_branch); let builder_field_builds = self.fields.iter().map(Field::builder_field_build); @@ -144,6 +145,7 @@ impl NamedStruct { let (ns, name) = reader.resolve_element(start.name()); #(#tagname_field_branches);* + #(#namespace_field_branches);* for attr in start.attributes() { let attr = attr?; diff --git a/crates/xml/tests/de_struct.rs b/crates/xml/tests/de_struct.rs index bcc1a5d..9838a43 100644 --- a/crates/xml/tests/de_struct.rs +++ b/crates/xml/tests/de_struct.rs @@ -342,3 +342,32 @@ fn test_struct_tuple() { } ); } + +#[test] +fn test_struct_untagged_ns() { + #[derive(Debug, XmlDeserialize, XmlRootTag, PartialEq)] + #[xml(root = b"document")] + struct Document { + #[xml(ty = "untagged")] + child: Child, + } + + #[derive(Debug, XmlDeserialize, PartialEq, Default)] + struct Child( + #[xml(ty = "tag_name")] String, + #[xml(ty = "namespace")] Option, + ); + + let doc = Document::parse_str( + r#" + + "#, + ) + .unwrap(); + assert_eq!( + doc, + Document { + child: Child("test".to_owned(), Some("hello".to_string())) + } + ); +}