quick-xml returned back and active again. Please use it
fast-xml -- successor of quick-xml
High performance xml pull reader/writer.
The reader:
- is almost zero-copy (use of
Cow
whenever possible) - is easy on memory allocation (the API provides a way to reuse buffers)
- support various encoding (with
encoding
feature), namespaces resolution, special characters.
Syntax is inspired by xml-rs.
Migration from quick-xml
If you using quick-xml 0.22.0 or 0.23.0-alpha3, you can just replace quick-xml
in your Cargo.toml
with fast-xml
. Replace each occurrence of quick_xml
crate name to fast_xml
in your code base.
That two releases of fast-xml was specifically made for migration and contains the same code as original quick-xml, except updated cargo metadata and extern crate names in tests, benches and examples.
Example
Reader
use Reader;
use Event;
let xml = r#"<tag1 att1 = "test">
<tag2><!--Test comment-->Test</tag2>
<tag2>
Test 2
</tag2>
</tag1>"#;
let mut reader = from_str;
reader.trim_text;
let mut count = 0;
let mut txt = Vec new;
let mut buf = Vec new;
// The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
loop
Writer
use Writer;
use Reader;
use ;
use Cursor;
use iter;
let xml = r#"<this_tag k1="v1" k2="v2"><child>text</child></this_tag>"#;
let mut reader = from_str;
reader.trim_text;
let mut writer = new;
let mut buf = Vec new;
loop
let result = writer.into_inner.into_inner;
let expected = r#"<my_elem k1="v1" k2="v2" my-key="some value"><child>text</child></my_elem>"#;
assert_eq!;
Serde
When using the serialize
feature, fast-xml can be used with serde's Serialize
/Deserialize
traits.
Here is an example deserializing crates.io source:
// Cargo.toml
// [dependencies]
// serde = { version = "1.0", features = [ "derive" ] }
// fast-xml = { version = "0.22", features = [ "serialize" ] }
use Deserialize;
use ;
Credits
This has largely been inspired by serde-xml-rs.
fast-xml follows its convention for deserialization, including the
$value
special name.
Original quick-xml was developed by @tafia and abandoned around end of 2021.
Parsing the "value" of a tag
If you have an input of the form <foo abc="xyz">bar</foo>
, and you want to get at the bar
, you can use the special name $value
:
Unflattening structs into verbose XML
If your XML files look like <root><first>value</first><second>value</second></root>
, you can
(de)serialize them with the special name prefix $unflatten=
:
Serializing unit variants as primitives
The $primitive
prefix lets you serialize enum variants without associated values (internally referred to as unit variants) as primitive strings rather than self-closing tags. Consider the following definitions:
Serializing Root { foo: Foo::Bar }
will then yield <Root foo="Bar"/>
instead of <Root><Bar/></Root>
.
Performance
Note that despite not focusing on performance (there are several unnecessary copies), it remains about 10x faster than serde-xml-rs.
Features
encoding
: support non utf8 xmlsserialize
: support serdeSerialize
/Deserialize
Performance
Benchmarking is hard and the results depend on your input file and your machine.
Here on my particular file, fast-xml is around 50 times faster than xml-rs crate. (measurements was done while this crate named quick-xml)
// quick-xml benches
test bench_quick_xml ... bench: 198,866 ns/iter (+/- 9,663)
test bench_quick_xml_escaped ... bench: 282,740 ns/iter (+/- 61,625)
test bench_quick_xml_namespaced ... bench: 389,977 ns/iter (+/- 32,045)
// same bench with xml-rs
test bench_xml_rs ... bench: 14,468,930 ns/iter (+/- 321,171)
// serde-xml-rs vs serialize feature
test bench_serde_quick_xml ... bench: 1,181,198 ns/iter (+/- 138,290)
test bench_serde_xml_rs ... bench: 15,039,564 ns/iter (+/- 783,485)
For a feature and performance comparison, you can also have a look at RazrFalcon's parser comparison table.
Contribute
Any PR is welcomed!
License
MIT