Working with XML in Rust: Parsing, Creation, and Data Serialization

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Working with XML in Rust: Libraries and Tools



XML (eXtensible Markup Language) remains one of the key formats for data exchange, configuration files, and document workflows. The Rust ecosystem offers several mature solutions for working with XML — from high-performance streaming parsing to convenient serialization via serde. In this article, we will cover three of the most popular tools: quick-xml, roxmltree, and serde-xml-rs.



Why Rust for Working with XML?



Rust combines the speed of C/C++ with memory safety. When processing large XML files (e.g., medical records or geodata), this is critical. XML libraries in Rust are written from scratch in Rust (without C bindings), ensuring thread safety and predictable performance.



Libraries for Working with XML in Rust



  • quick-xml — a high-performance streaming parser (SAX-style) and writer. Minimal memory consumption, ideal for large files.
  • roxmltree — a DOM parser that builds a document tree. Convenient for navigation and modification.
  • serde-xml-rs — serialization/deserialization of Rust structures to/from XML via the serde crate. Maximum integration with the type system.


Installation



Add dependencies to Cargo.toml:



[dependencies]quick-xml = "0.36"        # streaming parserroxmltree = "0.20"        # DOM parserserde-xml-rs = "0.6"      # serialization (paired with serde)serde = { version = "1.0", features = ["derive"] }


Parsing XML with quick-xml



quick-xml works in Reader mode — it sequentially reads tokens (opening tag, text, closing tag). This saves memory: you process the document in parts without loading it entirely.



Example: Reading an RSS Feed



use quick_xml::Reader;use quick_xml::events::Event;

fn main() -> Result<(), Box<dyn std::error::Error>> { let xml = r#" <rss version="2.0"> <channel> <title>Rust News</title> <item> <title>Rust 1.78 Released</title> <link>https://example.com/rust-1.78</link> </item> </channel> </rss>"#;

let mut reader = Reader::from_str(xml); reader.trim_text(true);

let mut buf = Vec::new(); let mut in_item = false;

loop { match reader.read_event_into(&mut buf) { Ok(Event::Start(ref e)) => { if e.name().as_ref() == b"item" { in_item = true; } } Ok(Event::Text(ref e)) => { if in_item { let text = e.unescape()?; println!("{}", text); } } Ok(Event::End(ref e)) => { if e.name().as_ref() == b"item" { in_item = false; } } Ok(Event::Eof) => break, Err(e) => eprintln!("Error: {}", e), _ => () } buf.clear(); } Ok(())}


Output: titles of all <item> elements.



DOM Parsing with roxmltree



roxmltree loads the entire XML into a tree. This is convenient when you need to repeatedly access different nodes or modify the structure.



Example: Extracting Attributes and Text



use roxmltree::Document;

fn main() { let data = r#" <config version="1.0"> <database> <host>localhost</host> <port>5432</port> </database> </config>"#;\

Recommendations