Skip to main content

excelize_rs/xml/
core.rs

1//! Core document properties (`docProps/core.xml`).
2//!
3//! Ported from Go `xmlCore.go`.
4
5use serde::{Deserialize, Serialize};
6
7/// Directly maps the document core properties.
8#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct DocProperties {
10    #[serde(default)]
11    pub category: String,
12    #[serde(rename = "ContentStatus", default)]
13    pub content_status: String,
14    #[serde(default)]
15    pub created: String,
16    #[serde(default)]
17    pub creator: String,
18    #[serde(default)]
19    pub description: String,
20    #[serde(default)]
21    pub identifier: String,
22    #[serde(default)]
23    pub keywords: String,
24    #[serde(rename = "LastModifiedBy", default)]
25    pub last_modified_by: String,
26    #[serde(default)]
27    pub modified: String,
28    #[serde(default)]
29    pub revision: String,
30    #[serde(default)]
31    pub subject: String,
32    #[serde(default)]
33    pub title: String,
34    #[serde(default)]
35    pub language: String,
36    #[serde(default)]
37    pub version: String,
38}
39
40/// DCMI metadata terms for the coreProperties.
41#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub struct DecodeDcTerms {
43    #[serde(rename = "$value", default)]
44    pub text: String,
45    #[serde(rename = "@xsi:type", default)]
46    pub r#type: Option<String>,
47}
48
49/// Deserialization-only representation of `coreProperties`.
50#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
51#[serde(rename = "coreProperties", rename_all = "PascalCase")]
52pub struct DecodeCoreProperties {
53    #[serde(rename = "title", default)]
54    pub title: Option<String>,
55    #[serde(rename = "subject", default)]
56    pub subject: Option<String>,
57    #[serde(rename = "creator", default)]
58    pub creator: Option<String>,
59    #[serde(default)]
60    pub keywords: Option<String>,
61    #[serde(rename = "description", default)]
62    pub description: Option<String>,
63    #[serde(rename = "lastModifiedBy", default)]
64    pub last_modified_by: Option<String>,
65    #[serde(rename = "language", default)]
66    pub language: Option<String>,
67    #[serde(rename = "identifier", default)]
68    pub identifier: Option<String>,
69    #[serde(default)]
70    pub revision: Option<String>,
71    #[serde(rename = "created", default)]
72    pub created: Option<DecodeDcTerms>,
73    #[serde(rename = "modified", default)]
74    pub modified: Option<DecodeDcTerms>,
75    #[serde(rename = "contentStatus", default)]
76    pub content_status: Option<String>,
77    #[serde(default)]
78    pub category: Option<String>,
79    #[serde(default)]
80    pub version: Option<String>,
81}
82
83/// DCMI metadata terms for the coreProperties.
84#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
85pub struct XlsxDcTerms {
86    #[serde(rename = "$value", default)]
87    pub text: String,
88    #[serde(rename = "@xsi:type", default, skip_serializing_if = "Option::is_none")]
89    pub r#type: Option<String>,
90}
91
92/// Serialization representation of `coreProperties`.
93#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename = "coreProperties", rename_all = "PascalCase")]
95pub struct XlsxCoreProperties {
96    #[serde(rename = "@xmlns:dc", default, skip_serializing_if = "Option::is_none")]
97    pub dc: Option<String>,
98    #[serde(
99        rename = "@xmlns:dcterms",
100        default,
101        skip_serializing_if = "Option::is_none"
102    )]
103    pub dcterms: Option<String>,
104    #[serde(
105        rename = "@xmlns:dcmitype",
106        default,
107        skip_serializing_if = "Option::is_none"
108    )]
109    pub dcmitype: Option<String>,
110    #[serde(
111        rename = "@xmlns:xsi",
112        default,
113        skip_serializing_if = "Option::is_none"
114    )]
115    pub xsi: Option<String>,
116    #[serde(rename = "dc:title", default, skip_serializing_if = "Option::is_none")]
117    pub title: Option<String>,
118    #[serde(
119        rename = "dc:subject",
120        default,
121        skip_serializing_if = "Option::is_none"
122    )]
123    pub subject: Option<String>,
124    #[serde(
125        rename = "dc:creator",
126        default,
127        skip_serializing_if = "Option::is_none"
128    )]
129    pub creator: Option<String>,
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub keywords: Option<String>,
132    #[serde(
133        rename = "dc:description",
134        default,
135        skip_serializing_if = "Option::is_none"
136    )]
137    pub description: Option<String>,
138    #[serde(
139        rename = "lastModifiedBy",
140        default,
141        skip_serializing_if = "Option::is_none"
142    )]
143    pub last_modified_by: Option<String>,
144    #[serde(
145        rename = "dc:language",
146        default,
147        skip_serializing_if = "Option::is_none"
148    )]
149    pub language: Option<String>,
150    #[serde(
151        rename = "dc:identifier",
152        default,
153        skip_serializing_if = "Option::is_none"
154    )]
155    pub identifier: Option<String>,
156    #[serde(default, skip_serializing_if = "Option::is_none")]
157    pub revision: Option<String>,
158    #[serde(
159        rename = "dcterms:created",
160        default,
161        skip_serializing_if = "Option::is_none"
162    )]
163    pub created: Option<XlsxDcTerms>,
164    #[serde(
165        rename = "dcterms:modified",
166        default,
167        skip_serializing_if = "Option::is_none"
168    )]
169    pub modified: Option<XlsxDcTerms>,
170    #[serde(
171        rename = "contentStatus",
172        default,
173        skip_serializing_if = "Option::is_none"
174    )]
175    pub content_status: Option<String>,
176    #[serde(default, skip_serializing_if = "Option::is_none")]
177    pub category: Option<String>,
178    #[serde(default, skip_serializing_if = "Option::is_none")]
179    pub version: Option<String>,
180}
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185    use quick_xml::de::from_str;
186
187    #[test]
188    fn deserialize_created() {
189        let s = r#"<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dcterms:created xsi:type="dcterms:W3CDTF">2019-06-04T22:00:10Z</dcterms:created></cp:coreProperties>"#;
190        let core: DecodeCoreProperties = from_str(s).unwrap();
191        assert_eq!(core.created.as_ref().unwrap().text, "2019-06-04T22:00:10Z");
192    }
193
194    #[test]
195    fn deserialize_created_simple() {
196        let s = r#"<coreProperties xmlns:dcterms="http://purl.org/dc/terms/"><dcterms:created>2019-06-04T22:00:10Z</dcterms:created></coreProperties>"#;
197        let core: DecodeCoreProperties = from_str(s).unwrap();
198        assert_eq!(core.created.as_ref().unwrap().text, "2019-06-04T22:00:10Z");
199    }
200}