What's Changed
0.42.0 -- 2026-08-22
This is a large release. The primary change is an ergonomic improvement across the entire API -
quick_xml now makes use of &str and String types where possible instead of
&[u8] and Vec<u8>. This requires significant refactoring of downstream code,
but should result in a net simplification as well as potential performance improvements,
and opens up additional opportunities in future releases.
The MSRV has been raised to 1.86. We now use Rust 2024 Edition.
Breaking Changes
- #963: Reader now validates that input is valid UTF-8 when constructing events.
Non-UTF-8 input passed toReader::from_reader()withoutDecodingReaderwill now
produceError::Encodinginstead of silently passing through invalid bytes.
UseDecodingReaderto transcode non-UTF-8 sources. - #963: Name types (
QName,LocalName,Prefix,Namespace,PrefixDeclaration)
now wrap&strinstead of&[u8].into_inner()returns&str, andAsRef<str>
is implemented (AsRef<[u8]>has been removed).ResolveResult::Unknownnow containsString
instead ofVec<u8>, andNamespaceErrorvariants containStringinstead ofVec<u8>. - #963: Removed the
decoder: Decoderfield from event types (BytesStart,BytesText,
BytesCData,BytesRef) andAttributes. Thedecoder()method is no longer available
on these types. Decode methods on events now always assume UTF-8 input.
Error::missed_end()no longer takes aDecoderparameter. - #963: Event types (
BytesStart,BytesEnd,BytesText,BytesCData,BytesPI,
BytesRef) now storeCow<str>internally instead ofCow<[u8]>.into_inner()on
BytesText,BytesCData,BytesPI, andBytesRefnow returnsCow<str>.
BytesStart::set_name()now takes&strinstead of&[u8]. - #963: All event types and the
Eventenum now implementDeref<Target = str>
instead ofDeref<Target = [u8]>. ExplicitAsRef<str>impls are provided to
avoid ambiguity. - #963: Removed
decode()methods fromBytesText,BytesCData, andBytesRef.
Content is already available as&strviaDeref. Thexml10_content(),
xml11_content(),xml_content(), andhtml_content()methods now return
Cow<str>directly instead ofResult<Cow<str>, EncodingError>. - #963:
Attribute::valueis nowCow<'a, str>instead ofCow<'a, [u8]>.
TheFrom<(&[u8], &[u8])>impl has been removed. - #963:
BytesDecl::version(),encoding(), andstandalone()now return
Cow<'_, str>instead ofCow<'_, [u8]>. - #963: Removed
Reader::decoder()method. UseReader::encoding()instead
(available with theencodingfeature). Removeddecoder()from theXmlRead
serde trait. Removed all methods fromDecoder(the struct is kept only for
backward compatibility with deprecatedAttributemethods). - #980:
NamespaceError::TooManyDeclarationshas been renamed toTooManyBindings,
andNamespaceResolver::set_max_declarations_per_elementhas been renamed to
NamespaceResolver::set_max_namespace_bindings, and the semantic behavior has
changed slightly. The default maximum has also been reduced from 256 to 128. - #1000:
DeError::UnexpectedStartrenamed toDeError::MixedContent. That error
is emitted when you try to deserialize boolean, number or stringfieldfrom
something like<field>text <tag/> another text</field>.
Bug Fixes
- #670: Serde serializer now escapes
\r,\n, and\tin attribute values
as , , and	respectively, preventing silent data loss from
XML attribute-value normalization on round-trip. LikewiseAttribute::from
performs the same transformation. - #953: The serde
Deserializernow 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::newandAttributes::htmlnow return empty iterators when
their starting position is past the end of the input instead of panicking. - #977:
NamespaceResolver::push(and hence everyNsReaderStart/Empty
event) now returns the newNamespaceError::TooDeeplyNestedwhen a document
nests elements deeper thanu16::MAX, instead of overflowing the internal
u16depth counter. Previously the unguardednesting_level += 1panicked
underoverflow-checksbuilds and silently wrapped in release, corrupting
namespace-scope bookkeeping on deeply nested untrusted input. - #980:
NamespaceResolvernow caps the total number of in-scope namespace
bindings (default 128, configurable viaset_max_namespace_bindings),
replacing the previous per-elementmax_declarations_per_elementlimit. - #978: The serde
Deserializernow enforces a configurable recursion-depth
limit (default 128, matchingserde_json). Deeply nested XML returns
DeError::TooDeeplyNestedinstead of overflowing the native call stack.
UseDeserializer::recursion_limit()to adjust. - #990:
\rin text content is now escaped as by the serde serializer,
BytesText::new(),escape(),partial_escape(), andminimal_escape(),
preventing silent conversion to\nfrom XML end-of-line normalization on
round-trip. Note that\rcannot be preserved through CDATA serialization
because character references are not permitted inside CDATA sections.
Misc Changes
- #269: Added getting-started examples (
getting_started,writer,
serde_roundtrip,reader_patterns,visitor) and anexamples/README.md
guide on choosing between the serde and pull-reader/writer APIs. - #331: Documentation about lifetimes of the events and attributes has been clarified.
- #859: Added an example showing how to pretty-print serialized XML.
- #983: Adopted an AI use and contribution policy for new upstream contributions.
- #963: MSRV bumped to 1.86 (April 2025)
- #963: Deprecated
Attributemethods that take aDecoderparameter, since
attribute values are now always valid UTF-8:decoded_and_normalized_value(),
decoded_and_normalized_value_with(),decode_and_unescape_value(), and
decode_and_unescape_value_with(). Usenormalized_value()and
normalized_value_with()instead. - #1002: Added
NamespaceResolver::withthat 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::resolverandDeserializer::resolver_mutmethods
to get a namespace resolver used by this deserializer, because it no longer uses
anNsReaderinternally. - #1005: Implement
Hash,PartialOrd, andOrdforBytesTextandBytesCDatatypes.
New Contributors
- @maxtaran2010 made their first contribution in #976
- @scadastrangelove made their first contribution in #979
- @lntutor made their first contribution in #992
Full Changelog: v0.41.0...v0.42.0