#xml #serde #serialization #derive-deserialize #roxml-tree

serde-roxmltree

Convert roxmltree documents into Serde-compatible types

20 releases

new 0.8.4 Jan 5, 2025
0.8.3 Jul 20, 2024
0.8.1 May 26, 2024
0.7.0 Feb 10, 2024
0.4.0 Nov 21, 2022

#446 in Encoding

Download history 120/week @ 2024-09-18 133/week @ 2024-09-25 108/week @ 2024-10-02 89/week @ 2024-10-09 65/week @ 2024-10-16 107/week @ 2024-10-23 78/week @ 2024-10-30 140/week @ 2024-11-06 121/week @ 2024-11-13 113/week @ 2024-11-20 109/week @ 2024-11-27 112/week @ 2024-12-04 57/week @ 2024-12-11 19/week @ 2024-12-18 6/week @ 2024-12-25 144/week @ 2025-01-01

237 downloads per month
Used in 3 crates (2 directly)

MIT/Apache

45KB
1K SLoC

serde-roxmltree

crates.io docs.rs github.com

Convert roxmltree documents into Serde-compatible types

License

Licensed under

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


lib.rs:

Convert roxmltree documents into serde-compatible types

Owned types can be deserialized directly from XML text using from_str:

use serde::Deserialize;
use serde_roxmltree::from_str;

#[derive(Deserialize)]
struct Record {
    field: String,
}

let record = from_str::<Record>("<record><field>foobar</field></record>")?;
assert_eq!(record.field, "foobar");
#

Borrowing types must be deserialized from a Document using from_doc:

use roxmltree::Document;
use serde::Deserialize;
use serde_roxmltree::from_doc;

#[derive(Deserialize)]
struct Record<'a> {
    field: &'a str,
}

let document = Document::parse("<document><field>foobar</field></document>")?;

let record = from_doc::<Record>(&document)?;
assert_eq!(record.field, "foobar");
#

Subtrees can be captured from the source by enabling the raw-node feature and using the RawNode type.

Fields of structures map to child elements and attributes:

use serde::Deserialize;
use serde_roxmltree::from_str;

#[derive(Deserialize)]
struct Record {
    child: String,
    attribute: i32,
}

let record = from_str::<Record>(r#"<record attribute="42"><child>foobar</child></record>"#)?;
assert_eq!(record.child, "foobar");
assert_eq!(record.attribute, 42);
#

Sequences collect repeated child elements:

use serde::Deserialize;
use serde_roxmltree::from_str;

#[derive(Deserialize)]
struct Record {
    field: Vec<String>,
}

let record = from_str::<Record>("<record><field>foo</field><field>bar</field></record>")?;
assert_eq!(record.field, ["foo", "bar"]);
#

Enum variants describe alternatives:

use serde::Deserialize;
use serde_roxmltree::from_str;

#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "lowercase")]
enum Record {
    Float(f32),
    Integer(i32),
}

let record = from_str::<Record>("<record><float>42.0</float></record>")?;
assert_eq!(record, Record::Float(42.0));

let record = from_str::<Record>("<record><integer>23</integer></record>")?;
assert_eq!(record, Record::Integer(23));
#

The reserved name $text is used to directly refer to the text within an element:

use serde::Deserialize;
use serde_roxmltree::from_str;

#[derive(Deserialize)]
struct Record {
    child: Child,
}

#[derive(Deserialize)]
struct Child {
    #[serde(rename = "$text")]
    text: String,
    attribute: i32,
}

let record = from_str::<Record>(r#"<record><child attribute="42">foobar</child></record>"#)?;
assert_eq!(record.child.text, "foobar");
assert_eq!(record.child.attribute, 42);
#

Optionally, attribute names can be prefixed by @ to distinguish them from tag names:

use serde::Deserialize;
use serde_roxmltree::{defaults, from_str, Options};

#[derive(Deserialize)]
struct Record {
    child: String,
    #[serde(rename = "@attribute")]
    attribute: i32,
}

let record = defaults().prefix_attr().from_str::<Record>(r#"<record attribute="42"><child>foobar</child></record>"#)?;
assert_eq!(record.child, "foobar");
assert_eq!(record.attribute, 42);
#

Support for namespaces can be enabled via the namespaces option:

use serde::Deserialize;
use serde_roxmltree::{defaults, from_str, Options};

let text = r#"<record xmlns:foo="http://foo" xmlns:bar="http://bar">
    <foo:qux>23</foo:qux>
    <bar:qux>42</bar:qux>
</record>"#;

#[derive(Deserialize)]
struct SomeRecord {
    qux: Vec<i32>,
}

let record = from_str::<SomeRecord>(text)?;
assert_eq!(record.qux, [23, 42]);

#[derive(Deserialize)]
struct AnotherRecord {
    #[serde(rename = "{http://foo}qux")]
    some_qux: i32,
    #[serde(rename = "{http://bar}qux")]
    another_qux: i32,
}

let record = defaults().namespaces().from_str::<AnotherRecord>(text)?;
assert_eq!(record.some_qux, 23);
assert_eq!(record.another_qux, 42);
#

Dependencies

~415–640KB
~14K SLoC