#xml #serialization #serde #deserialize #deserializing #struct #spreadsheet

xmlserde

用于序列化和反序列化xml的有用工具

17个版本 (6个重大更新)

0.9.1 2024年6月18日
0.8.1 2024年4月6日
0.8.0 2024年3月16日
0.5.5 2023年9月26日
0.3.0 2022年6月2日

#294 in 编码

Download history 18/week @ 2024-05-02 21/week @ 2024-05-09 17/week @ 2024-05-16 27/week @ 2024-05-23 29/week @ 2024-05-30 26/week @ 2024-06-06 280/week @ 2024-06-13 82/week @ 2024-06-20 48/week @ 2024-06-27 80/week @ 2024-07-04 25/week @ 2024-07-11 37/week @ 2024-07-18 203/week @ 2024-07-25 108/week @ 2024-08-01 53/week @ 2024-08-08 89/week @ 2024-08-15

每月457次 下载
用于 8 个crate(2个直接使用)

MIT 协议

23KB
273

xmlserde

MIT/Apache 2.0

xmlserde 是一个用于序列化和反序列化xml结构的工具。它专为 LogiSheets 设计,这是一个基于浏览器的电子表格应用程序。

您可以在 workbook 目录或 此处 查看使用细节。

如何使用 xmlserde

xmlserde 提供了一系列宏,足以满足大多数用例。要使用它们,您需要将以下crate包含在您的 Cargo.toml 文件中

xmlserde = 0.9
xmlserde_derives = 0.9

反序列化

从反序列化开始将更容易了解 xmlserde

给定以下xml结构

<person age ="16">Tom</person>

我们可以使用以下代码进行反序列化

use xmlserde_derives: XmlDerserialize
#[derive(XmlDeserialize)]
#[xmlserde(root = b"person")]
pub struct Person {
    #[xmlserde(name=b"age", ty="attr")]
    pub age: u8,
    #[xmlserde(ty ="text")]
    pub name: String,
}

fn deserialize_person() {
    use xmlserde::xml_deserialize_from_str;

    let s = r#"<person age ="16">Tom</person>"#;
    let p = xml_deserialize_from_str(s).unwrap();
    assert_eq!(p.age, 16);
    assert_eq!(p.name, "Tom");
}

您应该在反序列化器查找值的地方声明。

常见的类型有 attrtextchild。在上面的例子中,我们指示程序进入名为 person 的标签(使用 xml_deserialize_from_str),并搜索具有键 age 的属性。此外,它还指定文本元素的内容表示字段的值 name

您可以使用类似 #[xmlserde(root = b"person")] 的注释来指定xmlserde的序列化/反序列化输入元素,从而告诉程序 person 元素是serde操作的根。

以下是一个演示如何反序列化嵌套XML元素的示例

#[derive(XmlDeserialize)]
#[xmlserde(root = b"person")]
pub struct Person {
    #[xmlserde(name=b"age", ty="attr")]
    pub age: u8,
    #[xmlserde(name = b"lefty", ty ="attr", default = "default_lefty")]
    pub lefty: bool,
    #[xmlserde(name = b"name", ty ="child")]
    pub name: Name,
}

#[derive(XmlDeserialize)]
pub struct Name {
    #[xmlserde(name = b"zh", ty ="attr")]
    pub zh: String,
    #[xmlserde(name = b"en", ty ="attr")]
    pub en: String,
}

fn deserialize_person() {
    use xmlserde::xml_deserialize_from_str;

    let s = r#"<person age ="16"><name zh="汤姆", en="Tom"/></person>"#;
    let p = xml_deserialize_from_str(s).unwrap();
    assert_eq!(p.age, 16);
    assert_eq!(p.name.en, "Tom");
    assert_eq!(p.lefty, false);
}

fn default_lefty() -> bool { false }

在给定示例中,我们指定从标记为 <name> 的子元素中提取 name 字段的值。因此,程序将进入 <name> 元素并进行递归反序列化。

此外,我们指定如果反序列化器没有找到 lefty 的值,则应将 lefty 的默认值设置为 false。

Vec

我们支持反序列化类型为 std::Vec<T: XmlDeserialize> 的字段。

#[derive(XmlDeserialize)]
pub struct Pet {
    // Fields
}

#[derive(XmlDeserialize)]
#[xmlserde(root = b"person")]
pub struct Person {
    #[xmlserde(name = b"petCount", ty = "attr")]
    pub pet_count: u8,
    #[xmlserde(name = b"pet", ty = "child")]
    pub pets: Vec<Pet>
}

当反序列化器找到 pet 元素时,它将知道这是一个 pets 的元素。您甚至可以使用以下方式分配 Vec 的容量

#[xmlserde(name = b"pet", ty="child", vec_size=3)]

如果容量来自 attr,则可以

#[xmlserde(name = b"pet", ty="child", vec_size="pet_count")]

Enum

我们提供了两种反序列化 Enum 的模式。

#[derive(XmlSerialize, XmlDeserialize)]
enum TestEnum {
    #[xmlserde(name = b"testA")]
    TestA(TestA),
    #[xmlserde(name = b"testB")]
    TestB(TestB),
}

#[derive(XmlSerialize, XmlDeserialize)]
#[xmlserde(root = b"personA")]
pub struct PersonA {
    #[xmlserde(name = b"e", ty = "child")]
    pub e: TestEnum
    // Other fields
}

#[derive(XmlSerialize, XmlDeserialize)]
#[xmlserde(root = b"personB")]
pub struct PersonB {
    #[xmlserde(ty = "untag")]
    pub dummy: TestEnum
    // Other fields
}

PersonA 可以用于反序列化如下 XML 结构

<personA><e><testA/></e></personA>

<personA><e><testB/></e></personA>

PersonB 可以用于反序列化如下 XML

<personB><testA/></personB>

<personB><testB/></personB>

您可以使用 untagOption<T>Vec<T>(其中 T 是一个 Enum)转换为字符串类型。

这意味着以下示例是合法的

#[derive(XmlSerialize, XmlDeserialize)]
#[xmlserde(root = b"personB")]
pub struct PersonB {
    #[xmlserde(ty = "untag")]
    pub dummy1: Enum1,
    #[xmlserde(ty = "untag")]
    pub dummy2: Option<Enum2>,
    #[xmlserde(ty = "untag")]
    pub dummy3: Vec<Enum3>,
    // Other fields
}

未解析

在某些情况下,当某些 XML 元素不是立即相关的,但您希望为了将来的序列化而保留它们时,我们提供了 Unparsed 结构来实现这一目的。

use xmlserde::Unparsed;

#[derive(XmlDeserialize)]
pub struct Person {
    #[xmlserde(name = b"educationHistory", ty = "child")]
    pub education_history: Unparsed,
}

序列化

序列化在很大程度上与反序列化相似。但是,有几个关键特性需要考虑。

  • 默认值将跳过序列化。如果它是一个 struct,则应该实现 Eq 特性。

  • 如果一个结构没有 childtext,则序列化的结果将如下所示

    <tag attr1="value1"/>
    

自定义 xmlserde

xmlserde 提供了 XmlSerializeXmlDeserialize 特性,允许您通过实现这些特性来指定结构的序列化和反序列化行为。目前,仅允许使用内置类型作为属性。要启用自定义类型用于属性,可以在这些类型上实现 XmlValue 特性。

字符串类型的 Enum

xmlserde 还提供了一个名为 xml_serde_enum 的宏,用于将字符串类型的 enum 序列化。

xml_serde_enum 定义了一个 enum 并指定了序列化和反序列化的行为。

use xmlserde::xml_serde_enum;

xml_serde_enum!{
    #[derive(Debug)]
    Gender {
        Male => "male",
        Female => "female",
    }
}

依赖项

~1.5MB
~29K SLoC