Работа с XML в Rust: обзор библиотек и практические примеры
Rust — современный системный язык программирования, который всё чаще используется для создания высоконагруженных веб-сервисов, инструментов командной строки и встроенных систем. При работе с данными нередко возникает необходимость обрабатывать XML-документы. В отличие от Python, где стандартная библиотека xml.etree.ElementTree покрывает большинство задач, в Rust экосистема предлагает несколько специализированных крейтов (crates) с разными подходами. В этой статье мы рассмотрим три наиболее популярных инструмента для работы с XML в Rust: roxmltree, quick-xml и serde-xml-rs.
1. roxmltree — быстрый и безопасный парсер только для чтения
roxmltree — это крейт, предназначенный исключительно для чтения XML. Он не поддерживает мутацию или создание документов, но зато предоставляет очень быстрый и надёжный парсер с полной поддержкой пространств имён (namespaces). Главное преимущество — работа с заимствованными данными (zero-copy), что минимизирует выделение памяти.
// cargo add roxmltree
use roxmltree::Document;
fn main() -> Result<(), roxmltree::Error> {
let xml = r#"
<root>
<item id="1">Первый элемент</item>
<item id="2">Второй элемент</item>
</root>"#;
let doc = Document::parse(xml)?;
// Получаем корневой элемент
let root = doc.root_element();
println!("Корневой элемент: {}", root.tag_name().name());
// Ищем все дочерние элементы <item>
for item in root.children().filter(|n| n.has_tag_name("item")) {
let id = item.attribute("id").unwrap_or("unknown");
let text = item.text().unwrap_or("");
println!("ID: {}, Текст: {}", id, text);
}
Ok(())
}
Когда использовать: если вам нужно только читать XML-файлы (конфигурации, ответы API, RSS-ленты) и важна максимальная производительность. roxmltree идеален для однократного парсинга.
2. quick-xml — универсальный парсер с поддержкой чтения и записи
quick-xml — самый популярный крейт для работы с XML в Rust. Он поддерживает как парсинг (событийный и DOM-подобный), так и сериализацию (запись) XML. Работает как с потоками (Reader), так и с целыми строками. Поддерживает атрибуты, CDATA, комментарии и escape-последовательности.
// cargo add quick-xml
use quick_xml::Reader;
use quick_xml::events::Event;
fn main() -> Result<(), quick_xml::Error> {
let xml = r#"<library>
<book genre="rust">Программирование на Rust</book>
<book genre="python">Python для начинающих</book>
</library>"#;
let mut reader = Reader::from_str(xml);
reader.trim_text(true);
let mut txt = String::new();
let mut current_genre = String::new();
loop {
match reader.read_event_into(&mut txt) {
Ok(Event::Start(ref e)) => {
if e.name().as_ref() == b"book" {
// Получаем атрибут genre
if let Some(attr) = e.attributes().flatten().find(|a| a.key.as_ref() == b"genre") {
current_genre = String::from_utf8_lossy(&attr.value).to_string();
}
}
}
Ok(Event::Text(ref e)) => {
let text = e.unescape()?;
println!("Жанр: {}, Название: {}", current_genre, text);
}
Ok(Event::Eof) => break,
Err(e) => panic!("Ошибка: {:?}", e),
_ => {}
}
txt.clear();
}
Ok(())
}
Когда использовать: если нужна гибкость — читать большие файлы потоково, создавать новые XML-документы или модифицировать существующие. quick-xml — выбор по умолчанию для большинства задач.
3. serde-xml-rs — сериализация через Serde (как в Python с marshmallow)
serde-xml-rs — это адаптер, который позволяет использовать мощную систему сериализации Serde для работы с XML. Если вы знакомы с Python-библиотеками marshmallow или pydantic, принцип будет похож: вы определяете структуры данных (struct), а библиотека автоматически преобразует их в XML и обратно.
// cargo add serde serde-xml-rs
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Partial Также в библиотеке
JSON обработка в Rust: serde_json, simd-json, json5 и другие библиотеки
Tokio для Rust: полное руководство с примерами
PDF генерация в Java: обзор библиотек iText, Apache PDFBox, OpenPDF
Mongoose Paginate для JavaScript (Node.js): полное руководство с примерами
Работа с XML в PHP: полное руководство по парсингу и созданию XML-документов