Track xml:lang throughout parsing

This commit is contained in:
Jonas Schäfer 2025-04-18 17:20:06 +02:00
commit d9a21dd8c9
21 changed files with 446 additions and 88 deletions

View file

@ -229,6 +229,7 @@ impl ::xso::FromXml for Iq {
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
_ctx: &::xso::Context<'_>,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.0 != crate::ns::DEFAULT_NS || qname.1 != "iq" {
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });

View file

@ -203,6 +203,7 @@ impl ::xso::FromXml for Description {
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
_ctx: &::xso::Context<'_>,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.1 != "description" {
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });
@ -263,6 +264,7 @@ impl ::xso::FromXml for Transport {
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
_ctx: &::xso::Context<'_>,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.1 != "transport" {
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });

View file

@ -290,6 +290,7 @@ impl ::xso::FromXml for Transport {
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
_ctx: &::xso::Context<'_>,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.0 != crate::ns::JINGLE_S5B || qname.1 != "transport" {
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });

View file

@ -2489,3 +2489,65 @@ fn text_vs_attribute_ordering_compile_bug_roundtrip_with_parent() {
"<thread xmlns='urn:example:ns1' parent='bar'>foo</thread>",
);
}
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = NS1, name = "elem")]
struct Language {
#[xml(child(default))]
child: core::option::Option<Box<Language>>,
#[xml(lang)]
lang: core::option::Option<String>,
}
#[test]
fn language_roundtrip_absent() {
#[allow(unused_imports)]
use core::{
option::Option::{None, Some},
result::Result::{Err, Ok},
};
roundtrip_full::<Language>("<elem xmlns='urn:example:ns1'/>");
}
#[test]
fn language_roundtrip_present() {
#[allow(unused_imports)]
use core::{
option::Option::{None, Some},
result::Result::{Err, Ok},
};
roundtrip_full::<Language>("<elem xmlns='urn:example:ns1' xml:lang='foo'/>");
}
#[test]
fn language_roundtrip_nested_parse() {
// cannot write a round-trip test for this, because on emission,
// `#[xml(language)]` fields with a non-None value will always emit
// the `xml:lang` attribute to ensure semantic correctness.
#[allow(unused_imports)]
use core::{
option::Option::{None, Some},
result::Result::{Err, Ok},
};
match parse_str::<Language>(
"<elem xmlns='urn:example:ns1' xml:lang='foo'><elem><elem xml:lang='bar'/></elem></elem>",
) {
Ok(Language { child, lang }) => {
assert_eq!(lang.as_deref(), Some("foo"));
let Some(Language { child, lang }) = child.map(|x| *x) else {
panic!("missing child");
};
assert_eq!(lang.as_deref(), Some("foo"));
let Some(Language { child, lang }) = child.map(|x| *x) else {
panic!("missing grand child");
};
assert_eq!(lang.as_deref(), Some("bar"));
assert!(child.is_none());
}
other => panic!("unexpected parse result: {:?}", other),
}
}

View file

@ -262,6 +262,7 @@ macro_rules! generate_attribute_enum {
fn from_events(
qname: ::xso::exports::rxml::QName,
attrs: ::xso::exports::rxml::AttrMap,
_ctx: &::xso::Context<'_>,
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
if qname.0 != crate::ns::$ns || qname.1 != $name {
return Err(::xso::error::FromEventsError::Mismatch {