{"id":13439371,"url":"https://github.com/tafia/quick-xml","last_synced_at":"2025-05-11T03:43:32.108Z","repository":{"id":37924178,"uuid":"50503287","full_name":"tafia/quick-xml","owner":"tafia","description":"Rust high performance xml reader and writer","archived":false,"fork":false,"pushed_at":"2025-05-09T08:26:54.000Z","size":3494,"stargazers_count":1320,"open_issues_count":102,"forks_count":250,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-11T03:43:25.501Z","etag":null,"topics":["deserialization","html","performance-xml","pull-parser","serialization","writer","xml","xml-parser"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tafia.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE-MIT.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-01-27T11:37:44.000Z","updated_at":"2025-05-10T21:44:48.000Z","dependencies_parsed_at":"2024-03-31T17:27:17.687Z","dependency_job_id":"3f67497f-7557-485b-9406-26b5c9133ac0","html_url":"https://github.com/tafia/quick-xml","commit_stats":{"total_commits":1280,"total_committers":115,"mean_commits":"11.130434782608695","dds":0.64140625,"last_synced_commit":"0793d6a8d006cb5dabf66bf2a25ddbf198305b46"},"previous_names":[],"tags_count":64,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tafia%2Fquick-xml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tafia%2Fquick-xml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tafia%2Fquick-xml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tafia%2Fquick-xml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tafia","download_url":"https://codeload.github.com/tafia/quick-xml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253514552,"owners_count":21920334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deserialization","html","performance-xml","pull-parser","serialization","writer","xml","xml-parser"],"created_at":"2024-07-31T03:01:13.365Z","updated_at":"2025-05-11T03:43:32.085Z","avatar_url":"https://github.com/tafia.png","language":"Rust","readme":"# quick-xml\n\n![status](https://github.com/tafia/quick-xml/actions/workflows/rust.yml/badge.svg)\n[![Crate](https://img.shields.io/crates/v/quick-xml.svg)](https://crates.io/crates/quick-xml)\n[![docs.rs](https://docs.rs/quick-xml/badge.svg)](https://docs.rs/quick-xml)\n[![codecov](https://img.shields.io/codecov/c/github/tafia/quick-xml)](https://codecov.io/gh/tafia/quick-xml)\n[![MSRV](https://img.shields.io/badge/rustc-1.56.0+-ab6000.svg)](https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html)\n\nHigh performance xml pull reader/writer.\n\nThe reader:\n- is almost zero-copy (use of `Cow` whenever possible)\n- is easy on memory allocation (the API provides a way to reuse buffers)\n- support various encoding (with `encoding` feature), namespaces resolution, special characters.\n\nSyntax is inspired by [xml-rs](https://github.com/netvl/xml-rs).\n\n## Example\n\n### Reader\n\n```rust\nuse quick_xml::events::Event;\nuse quick_xml::reader::Reader;\n\nlet xml = r#\"\u003ctag1 att1 = \"test\"\u003e\n                \u003ctag2\u003e\u003c!--Test comment--\u003eTest\u003c/tag2\u003e\n                \u003ctag2\u003eTest 2\u003c/tag2\u003e\n             \u003c/tag1\u003e\"#;\nlet mut reader = Reader::from_str(xml);\nreader.config_mut().trim_text(true);\n\nlet mut count = 0;\nlet mut txt = Vec::new();\nlet mut buf = Vec::new();\n\n// The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)\nloop {\n    // NOTE: this is the generic case when we don't know about the input BufRead.\n    // when the input is a \u0026str or a \u0026[u8], we don't actually need to use another\n    // buffer, we could directly call `reader.read_event()`\n    match reader.read_event_into(\u0026mut buf) {\n        Err(e) =\u003e panic!(\"Error at position {}: {:?}\", reader.error_position(), e),\n        // exits the loop when reaching end of file\n        Ok(Event::Eof) =\u003e break,\n\n        Ok(Event::Start(e)) =\u003e {\n            match e.name().as_ref() {\n                b\"tag1\" =\u003e println!(\"attributes values: {:?}\",\n                                    e.attributes().map(|a| a.unwrap().value)\n                                    .collect::\u003cVec\u003c_\u003e\u003e()),\n                b\"tag2\" =\u003e count += 1,\n                _ =\u003e (),\n            }\n        }\n        Ok(Event::Text(e)) =\u003e txt.push(e.unescape().unwrap().into_owned()),\n\n        // There are several other `Event`s we do not consider here\n        _ =\u003e (),\n    }\n    // if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low\n    buf.clear();\n}\n```\n\n### Writer\n\n```rust\nuse quick_xml::events::{Event, BytesEnd, BytesStart};\nuse quick_xml::reader::Reader;\nuse quick_xml::writer::Writer;\nuse std::io::Cursor;\n\nlet xml = r#\"\u003cthis_tag k1=\"v1\" k2=\"v2\"\u003e\u003cchild\u003etext\u003c/child\u003e\u003c/this_tag\u003e\"#;\nlet mut reader = Reader::from_str(xml);\nreader.config_mut().trim_text(true);\nlet mut writer = Writer::new(Cursor::new(Vec::new()));\nloop {\n    match reader.read_event() {\n        Ok(Event::Start(e)) if e.name().as_ref() == b\"this_tag\" =\u003e {\n\n            // crates a new element ... alternatively we could reuse `e` by calling\n            // `e.into_owned()`\n            let mut elem = BytesStart::new(\"my_elem\");\n\n            // collect existing attributes\n            elem.extend_attributes(e.attributes().map(|attr| attr.unwrap()));\n\n            // copy existing attributes, adds a new my-key=\"some value\" attribute\n            elem.push_attribute((\"my-key\", \"some value\"));\n\n            // writes the event to the writer\n            assert!(writer.write_event(Event::Start(elem)).is_ok());\n        },\n        Ok(Event::End(e)) if e.name().as_ref() == b\"this_tag\" =\u003e {\n            assert!(writer.write_event(Event::End(BytesEnd::new(\"my_elem\"))).is_ok());\n        },\n        Ok(Event::Eof) =\u003e break,\n        // we can either move or borrow the event to write, depending on your use-case\n        Ok(e) =\u003e assert!(writer.write_event(e).is_ok()),\n        Err(e) =\u003e panic!(\"Error at position {}: {:?}\", reader.error_position(), e),\n    }\n}\n\nlet result = writer.into_inner().into_inner();\nlet expected = r#\"\u003cmy_elem k1=\"v1\" k2=\"v2\" my-key=\"some value\"\u003e\u003cchild\u003etext\u003c/child\u003e\u003c/my_elem\u003e\"#;\nassert_eq!(result, expected.as_bytes());\n```\n\n## Serde\n\nWhen using the `serialize` feature, quick-xml can be used with serde's `Serialize`/`Deserialize` traits.\nThe mapping between XML and Rust types, and in particular the syntax that allows you to specify the\ndistinction between *elements* and *attributes*, is described in detail in the documentation\nfor [deserialization](https://docs.rs/quick-xml/latest/quick_xml/de/).\n\n### Credits\n\nThis has largely been inspired by [serde-xml-rs](https://github.com/RReverser/serde-xml-rs).\nquick-xml follows its convention for deserialization, including the\n[`$value`](https://github.com/RReverser/serde-xml-rs#parsing-the-value-of-a-tag) special name.\n\n### Parsing the \"value\" of a tag\n\nIf you have an input of the form `\u003cfoo abc=\"xyz\"\u003ebar\u003c/foo\u003e`, and you want to get at the `bar`,\nyou can use either the special name `$text`, or the special name `$value`:\n\n```rust,ignore\nstruct Foo {\n    #[serde(rename = \"@abc\")]\n    pub abc: String,\n    #[serde(rename = \"$text\")]\n    pub body: String,\n}\n```\n\nRead about the difference in the [documentation](https://docs.rs/quick-xml/latest/quick_xml/de/index.html#difference-between-text-and-value-special-names).\n\n### Performance\n\nNote that despite not focusing on performance (there are several unnecessary copies), it remains about 10x faster than serde-xml-rs.\n\n# Features\n\n- `encoding`: support non utf8 xmls\n- `serialize`: support serde `Serialize`/`Deserialize`\n\n## Performance\n\nBenchmarking is hard and the results depend on your input file and your machine.\n\nHere on my particular file, quick-xml is around **50 times faster** than [xml-rs](https://crates.io/crates/xml-rs) crate.\n\n```\n// quick-xml benches\ntest bench_quick_xml            ... bench:     198,866 ns/iter (+/- 9,663)\ntest bench_quick_xml_escaped    ... bench:     282,740 ns/iter (+/- 61,625)\ntest bench_quick_xml_namespaced ... bench:     389,977 ns/iter (+/- 32,045)\n\n// same bench with xml-rs\ntest bench_xml_rs               ... bench:  14,468,930 ns/iter (+/- 321,171)\n\n// serde-xml-rs vs serialize feature\ntest bench_serde_quick_xml      ... bench:   1,181,198 ns/iter (+/- 138,290)\ntest bench_serde_xml_rs         ... bench:  15,039,564 ns/iter (+/- 783,485)\n```\n\nFor a feature and performance comparison, you can also have a look at RazrFalcon's [parser comparison table](https://github.com/RazrFalcon/roxmltree#parsing).\n\n## Contribute\n\nAny PR is welcomed!\n\n## License\n\nMIT\n","funding_links":[],"categories":["Libraries","Rust","库 Libraries","库"],"sub_categories":["Encoding","编码 Encoding","编码(Encoding)","加密 Encoding"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftafia%2Fquick-xml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftafia%2Fquick-xml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftafia%2Fquick-xml/lists"}