Skip to content

Commit de52d04

Browse files
authored
fix: Fixes broken enforce_prefix option. (#129)
1 parent 271ba65 commit de52d04

File tree

5 files changed

+147
-3
lines changed

5 files changed

+147
-3
lines changed

xmlity-derive/src/ser/serialize/element.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ impl<T: Fn(syn::Expr) -> syn::Expr> SerializeBuilder for RecordSerializeElementB
223223
let preferred_prefix_setting = preferred_prefix.as_ref().map::<Stmt, _>(|preferred_prefix| parse_quote! {
224224
::xmlity::ser::SerializeElement::preferred_prefix(&mut #ser_element_ident, ::core::option::Option::Some(#preferred_prefix))?;
225225
});
226-
let enforce_prefix_setting = Some(*enforce_prefix).filter(|&enforce_prefix| enforce_prefix).map::<Stmt, _>(|enforce_prefix| parse_quote! {
226+
let enforce_prefix_setting = enforce_prefix.then(|| parse_quote!(
227+
::xmlity::ser::IncludePrefix::WhenNecessaryForPreferredPrefix
228+
)).map::<Stmt, _>(|enforce_prefix: syn::Expr| parse_quote! {
227229
::xmlity::ser::SerializeElement::include_prefix(&mut #ser_element_ident, #enforce_prefix)?;
228230
});
229231

xmlity-derive/src/ser/serialize_attribute.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ impl SerializeAttributeBuilder for StructSerializeAttributeBuilder<'_> {
215215
let preferred_prefix_setting = preferred_prefix.as_ref().map::<Stmt, _>(|preferred_prefix| parse_quote! {
216216
::xmlity::ser::SerializeAttributeAccess::preferred_prefix(&mut #access_ident, ::core::option::Option::Some(#preferred_prefix))?;
217217
});
218-
let enforce_prefix_setting = Some(*enforce_prefix).filter(|&enforce_prefix| enforce_prefix).map::<Stmt, _>(|enforce_prefix| parse_quote! {
218+
let enforce_prefix_setting = enforce_prefix.then(|| {
219+
parse_quote!(::xmlity::ser::IncludePrefix::WhenNecessaryForPreferredPrefix)
220+
}).map::<Stmt, _>(|enforce_prefix: syn::Expr| parse_quote! {
219221
::xmlity::ser::SerializeAttributeAccess::include_prefix(&mut #access_ident, #enforce_prefix)?;
220222
});
221223

xmlity-quick-xml/src/ser.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,13 @@ impl<'a> NamespaceScopeContainer<'a> {
188188
let existing_prefix = self.find_matching_namespace(namespace);
189189

190190
if let Some(existing_prefix) = existing_prefix {
191-
return (existing_prefix.clone(), None);
191+
if (always_declare == IncludePrefix::WhenNecessaryForPreferredPrefix
192+
&& preferred_prefix
193+
.is_none_or(|preferred_prefix| preferred_prefix == existing_prefix))
194+
|| always_declare == IncludePrefix::Never
195+
{
196+
return (existing_prefix.clone(), None);
197+
}
192198
}
193199
}
194200

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
use crate::define_serialize_test;
2+
use xmlity::{Serialize, SerializeAttribute};
3+
4+
/// Test struct with enforce_prefix = false (default behavior)
5+
#[derive(Debug, PartialEq, Serialize)]
6+
#[xelement(
7+
name = "test",
8+
namespace = "http://example.com/test",
9+
preferred_prefix = "pref"
10+
)]
11+
pub struct TestElementNoEnforce {
12+
value: String,
13+
}
14+
15+
/// Test struct with enforce_prefix = true
16+
#[derive(Debug, PartialEq, Serialize)]
17+
#[xelement(
18+
name = "test",
19+
namespace = "http://example.com/test",
20+
preferred_prefix = "pref",
21+
enforce_prefix = true
22+
)]
23+
pub struct TestElementEnforcePrefix {
24+
value: String,
25+
}
26+
27+
/// Test struct for attribute serialization with enforce_prefix = false
28+
#[derive(Debug, PartialEq, SerializeAttribute)]
29+
#[xattribute(
30+
name = "testattr",
31+
namespace = "http://example.com/test",
32+
preferred_prefix = "pref"
33+
)]
34+
pub struct TestAttributeNoEnforce(String);
35+
36+
/// Test struct for attribute serialization with enforce_prefix = true
37+
#[derive(Debug, PartialEq, SerializeAttribute)]
38+
#[xattribute(
39+
name = "testattr",
40+
namespace = "http://example.com/test",
41+
preferred_prefix = "pref",
42+
enforce_prefix = true
43+
)]
44+
pub struct TestAttributeEnforcePrefix(String);
45+
46+
#[derive(Debug, PartialEq, Serialize)]
47+
#[xelement(
48+
name = "wrapper",
49+
namespace = "http://example.com/test",
50+
preferred_prefix = "wrapper-ns"
51+
)]
52+
struct AttrWrapper<TAttr: SerializeAttribute> {
53+
#[xattribute(deferred)]
54+
attr: TAttr,
55+
}
56+
#[derive(Debug, PartialEq, Serialize)]
57+
#[xelement(
58+
name = "wrapper",
59+
namespace = "http://example.com/irrelevant",
60+
preferred_prefix = "wrapper-ns"
61+
)]
62+
struct AttrIrrelevantWrapper<TAttr: SerializeAttribute> {
63+
#[xattribute(deferred)]
64+
attr: TAttr,
65+
}
66+
67+
#[derive(Debug, PartialEq, Serialize)]
68+
#[xelement(
69+
name = "wrapper",
70+
namespace = "http://example.com/test",
71+
preferred_prefix = "wrapper-ns"
72+
)]
73+
struct ValueWrapper<T: Serialize> {
74+
attr: T,
75+
}
76+
77+
define_serialize_test!(
78+
test_element_no_enforce,
79+
[
80+
(
81+
TestElementNoEnforce {
82+
value: "test_value".to_string()
83+
},
84+
r#"<pref:test xmlns:pref="http://example.com/test">test_value</pref:test>"#
85+
),
86+
(
87+
TestElementEnforcePrefix {
88+
value: "test_value".to_string()
89+
},
90+
r#"<pref:test xmlns:pref="http://example.com/test">test_value</pref:test>"#
91+
),
92+
(
93+
AttrIrrelevantWrapper {
94+
attr: TestAttributeNoEnforce("attribute_value".to_string())
95+
},
96+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/irrelevant" xmlns:pref="http://example.com/test" pref:testattr="attribute_value"/>"#
97+
),
98+
(
99+
AttrIrrelevantWrapper {
100+
attr: TestAttributeEnforcePrefix("attribute_value".to_string())
101+
},
102+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/irrelevant" xmlns:pref="http://example.com/test" pref:testattr="attribute_value"/>"#
103+
),
104+
(
105+
ValueWrapper {
106+
attr: TestElementNoEnforce {
107+
value: "test_value".to_string()
108+
}
109+
},
110+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/test"><wrapper-ns:test>test_value</wrapper-ns:test></wrapper-ns:wrapper>"#
111+
),
112+
(
113+
ValueWrapper {
114+
attr: TestElementEnforcePrefix {
115+
value: "test_value".to_string()
116+
}
117+
},
118+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/test"><pref:test xmlns:pref="http://example.com/test">test_value</pref:test></wrapper-ns:wrapper>"#
119+
),
120+
(
121+
AttrWrapper {
122+
attr: TestAttributeNoEnforce("attribute_value".to_string())
123+
},
124+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/test" wrapper-ns:testattr="attribute_value"/>"#
125+
),
126+
(
127+
AttrWrapper {
128+
attr: TestAttributeEnforcePrefix("attribute_value".to_string())
129+
},
130+
r#"<wrapper-ns:wrapper xmlns:wrapper-ns="http://example.com/test" xmlns:pref="http://example.com/test" pref:testattr="attribute_value"/>"#
131+
)
132+
]
133+
);

xmlity-quick-xml/tests/elements/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod attribute;
44
pub mod attribute_namespace;
55
pub mod basic;
66
pub mod default;
7+
pub mod enforce_prefix;
78
pub mod extendable;
89
pub mod generics;
910
pub mod group_element_equivalent;

0 commit comments

Comments
 (0)