diff --git a/parsers/src/util/macro_tests.rs b/parsers/src/util/macro_tests.rs index 70bbffb9..a477ed94 100644 --- a/parsers/src/util/macro_tests.rs +++ b/parsers/src/util/macro_tests.rs @@ -139,6 +139,23 @@ fn empty_unexpected_attribute() { } } +#[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] +fn empty_ignores_xml_lang() { + #[allow(unused_imports)] + use core::{ + option::Option::{None, Some}, + result::Result::{Err, Ok}, + }; + match parse_str::("") { + Ok(Empty) => (), + other => panic!("unexpected result: {:?}", other), + } +} + #[test] #[cfg_attr( feature = "disable-validation", diff --git a/xso-proc/src/compound.rs b/xso-proc/src/compound.rs index bf149119..d91fa8c3 100644 --- a/xso-proc/src/compound.rs +++ b/xso-proc/src/compound.rs @@ -396,7 +396,11 @@ impl Compound { } } - let mut discard_attr = TokenStream::default(); + // We always implicitly discard the `xml:lang` attribute. Its + // processing is handled using the `#[xml(language)]` meta. + let mut discard_attr = quote! { + let _ = #attrs.remove(::xso::exports::rxml::Namespace::xml(), "lang"); + }; for (xml_namespace, xml_name) in self.discard_attr.iter() { let xml_namespace = match xml_namespace { Some(v) => v.to_token_stream(), diff --git a/xso/ChangeLog b/xso/ChangeLog index f00527a6..002c8236 100644 --- a/xso/ChangeLog +++ b/xso/ChangeLog @@ -12,6 +12,11 @@ Version NEXT: This change overall allows for more flexibility in the implementation of text codecs. + - `xml:lang` attributes are now silently discarded during + deserialisation unless captured by `#[xml(attribute = "xml:lang")]` or + equivalent. This is because `xml:lang` is special as per + XML 1.0 § 2.12 and it is generally preferable to allow it to occur + anywhere in the document. * Added - Support for child elements in derive macros. Child elements may also be wrapped in Option or Box or in containers like Vec or HashSet.