Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ The MSRV has been raised to 1.86.
as `
`, `
`, and `	` respectively, preventing silent data loss from
XML attribute-value normalization on round-trip. Likewise `Attribute::from`
performs the same transformation.
- [#953]: The serde `Deserializer` now correctly handles namespaces. Previously
the namespace bindings might be applied or removed before the event actually
was consumed which lead to a couple of bugs.
- [#989]: `Attributes::new` and `Attributes::html` now return empty iterators when
their starting position is past the end of the input instead of panicking.
- [#977]: `NamespaceResolver::push` (and hence every `NsReader` `Start`/`Empty`
Expand Down Expand Up @@ -99,9 +102,17 @@ The MSRV has been raised to 1.86.
`decoded_and_normalized_value_with()`, `decode_and_unescape_value()`, and
`decode_and_unescape_value_with()`. Use `normalized_value()` and
`normalized_value_with()` instead.
- [#1002]: Added `NamespaceResolver::with` that allows temporary applying namespace
bindings from the start tag for the scope of a provided closure F, without making any
persistent change to the resolver. It is useful to check a peeked event which is
not yet consumed in custom implementations of peekable reader.
- [#1002]: Added `Deserializer::resolver` and `Deserializer::resolver_mut` methods
to get a namespace resolver used by this deserializer, because it no longer uses
an `NsReader` internally.

[#670]: https://github.com/tafia/quick-xml/issues/670
[#859]: https://github.com/tafia/quick-xml/issues/859
[#953]: https://github.com/tafia/quick-xml/issues/953
[#963]: https://github.com/tafia/quick-xml/pull/963
[#977]: https://github.com/tafia/quick-xml/issues/977
[#978]: https://github.com/tafia/quick-xml/issues/978
Expand All @@ -110,6 +121,7 @@ The MSRV has been raised to 1.86.
[#989]: https://github.com/tafia/quick-xml/issues/989
[#990]: https://github.com/tafia/quick-xml/issues/990
[#1000]: https://github.com/tafia/quick-xml/pull/1000
[#1002]: https://github.com/tafia/quick-xml/pull/1002


## 0.41.0 -- 2026-06-29
Expand Down
34 changes: 10 additions & 24 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,21 +221,6 @@ where
})
}

/// Determines if subtree started with the specified event should be skipped.
///
/// Used to map elements with `xsi:nil` attribute set to true to `None` in optional contexts.
///
/// We need to handle two attributes:
/// - on parent element: `<map xsi:nil="true"><foo/></map>`
/// - on this element: `<map><foo xsi:nil="true"/></map>`
///
/// We check parent element too because `xsi:nil` affects only nested elements of the
/// tag where it is defined. We can map structure with fields mapped to attributes to
/// the `<map>` element and set to `None` all its optional elements.
fn should_skip_subtree(&self, start: &BytesStart) -> bool {
self.de.reader.reader.has_nil_attr(&self.start) || self.de.reader.reader.has_nil_attr(start)
}

/// Skips whitespaces when they are not preserved
#[inline]
fn skip_whitespaces(&mut self) -> Result<(), DeError> {
Expand Down Expand Up @@ -577,15 +562,16 @@ where
where
V: Visitor<'de>,
{
// We cannot use result of `peek()` directly because of borrow checker
let _ = self.map.de.peek()?;
match self.map.de.last_peeked() {
DeEvent::Text(t) if t.is_empty() => visitor.visit_none(),
DeEvent::Start(start) if self.map.should_skip_subtree(start) => {
self.map.de.skip_next_tree()?;
visitor.visit_none()
}
_ => visitor.visit_some(self),
// `self.map.start` already was taken from the reader, so its namespace bindings were already processed.
let has_nil = self
.map
.start
.attributes()
.has_nil(&self.map.de.ns_resolver);
if self.map.de.deserialize_opt(Some(has_nil))? {
visitor.visit_some(self)
} else {
visitor.visit_none()
}
}

Expand Down
Loading
Loading