docx_rust/
core.rs

1//! Core File Properties part
2//!
3//! The corresponding ZIP item is `/docProps/core.xml`.
4
5use hard_xml::{XmlRead, XmlResult, XmlWrite, XmlWriter};
6use std::borrow::Cow;
7use std::io::Write;
8
9use crate::schema::{SCHEMA_CORE_2, SCHEMA_DC, SCHEMA_DCTERMS, SCHEMA_XML};
10
11#[derive(Debug, XmlRead, XmlWrite, Clone)]
12pub enum Core<'a> {
13    #[xml(tag = "cp:coreProperties")]
14    CoreNamespace(CoreNamespace<'a>),
15    #[xml(tag = "coreProperties")]
16    CoreNoNamespace(CoreNoNamespace<'a>),
17}
18
19#[derive(Debug, Default, XmlRead, Clone)]
20#[xml(tag = "cp:coreProperties")]
21pub struct CoreNamespace<'a> {
22    #[xml(flatten_text = "dc:title")]
23    pub title: Option<Cow<'a, str>>,
24    #[xml(flatten_text = "dc:subject")]
25    pub subject: Option<Cow<'a, str>>,
26    #[xml(flatten_text = "dc:creator")]
27    pub creator: Option<Cow<'a, str>>,
28    #[xml(flatten_text = "cp:keywords")]
29    pub keywords: Option<Cow<'a, str>>,
30    #[xml(flatten_text = "dc:description")]
31    pub description: Option<Cow<'a, str>>,
32    #[xml(flatten_text = "cp:lastModifiedBy")]
33    pub last_modified_by: Option<Cow<'a, str>>,
34    #[xml(flatten_text = "cp:revision")]
35    pub revision: Option<Cow<'a, str>>,
36    #[xml(flatten_text = "dcterms:created")]
37    pub created: Option<Cow<'a, str>>,
38    #[xml(flatten_text = "dcterms:modified")]
39    pub modified: Option<Cow<'a, str>>,
40    #[xml(flatten_text = "cp:contentStatus")]
41    pub content_status: Option<Cow<'a, str>>,
42    #[xml(flatten_text = "dc:language")]
43    pub language: Option<Cow<'a, str>>,
44    #[xml(flatten_text = "cp:category")]
45    pub category: Option<Cow<'a, str>>,
46}
47
48#[derive(Debug, Default, XmlRead, Clone)]
49#[xml(tag = "coreProperties")]
50pub struct CoreNoNamespace<'a> {
51    #[xml(flatten_text = "dc:title")]
52    pub title: Option<Cow<'a, str>>,
53    #[xml(flatten_text = "dc:subject")]
54    pub subject: Option<Cow<'a, str>>,
55    #[xml(flatten_text = "dc:creator")]
56    pub creator: Option<Cow<'a, str>>,
57    #[xml(flatten_text = "keywords")]
58    pub keywords: Option<Cow<'a, str>>,
59    #[xml(flatten_text = "dc:description")]
60    pub description: Option<Cow<'a, str>>,
61    #[xml(flatten_text = "lastModifiedBy")]
62    pub last_modified_by: Option<Cow<'a, str>>,
63    #[xml(flatten_text = "revision")]
64    pub revision: Option<Cow<'a, str>>,
65    #[xml(flatten_text = "created")]
66    pub created: Option<Cow<'a, str>>,
67    #[xml(flatten_text = "modified")]
68    pub modified: Option<Cow<'a, str>>,
69    #[xml(flatten_text = "contentStatus")]
70    pub content_status: Option<Cow<'a, str>>,
71    #[xml(flatten_text = "language")]
72    pub language: Option<Cow<'a, str>>,
73    #[xml(flatten_text = "category")]
74    pub category: Option<Cow<'a, str>>,
75}
76
77impl<'a> XmlWrite for CoreNamespace<'a> {
78    fn to_writer<W: Write>(&self, writer: &mut XmlWriter<W>) -> XmlResult<()> {
79        let CoreNamespace {
80            title,
81            subject,
82            creator,
83            keywords,
84            description,
85            last_modified_by,
86            revision,
87            created,
88            modified,
89            content_status,
90            language,
91            category,
92        } = self;
93
94        log::debug!("[Core] Started writing.");
95        let _ = write!(writer.inner, "{}", SCHEMA_XML);
96
97        writer.write_element_start("cp:coreProperties")?;
98
99        writer.write_attribute("xmlns:cp", SCHEMA_CORE_2)?;
100
101        writer.write_attribute("xmlns:dc", SCHEMA_DC)?;
102
103        writer.write_attribute("xmlns:dcterms", SCHEMA_DCTERMS)?;
104
105        if title.is_none()
106            && subject.is_none()
107            && creator.is_none()
108            && keywords.is_none()
109            && description.is_none()
110            && last_modified_by.is_none()
111            && revision.is_none()
112            && created.is_none()
113            && modified.is_none()
114            && content_status.is_none()
115            && language.is_none()
116            && category.is_none()
117        {
118            writer.write_element_end_empty()?;
119        } else {
120            writer.write_element_end_open()?;
121            if let Some(val) = title {
122                writer.write_flatten_text("dc:title", val, false)?;
123            }
124            if let Some(val) = subject {
125                writer.write_flatten_text("dc:subject", val, false)?;
126            }
127            if let Some(val) = creator {
128                writer.write_flatten_text("dc:creator", val, false)?;
129            }
130            if let Some(val) = keywords {
131                writer.write_flatten_text("cp:keywords", val, false)?;
132            }
133            if let Some(val) = description {
134                writer.write_flatten_text("dc:description", val, false)?;
135            }
136            if let Some(val) = last_modified_by {
137                writer.write_flatten_text("cp:lastModifiedBy", val, false)?;
138            }
139            if let Some(val) = revision {
140                writer.write_flatten_text("cp:revision", val, false)?;
141            }
142            if let Some(val) = revision {
143                writer.write_flatten_text("cp:revision", val, false)?;
144            }
145            if let Some(val) = created {
146                writer.write_flatten_text("dcterms:created", val, false)?;
147            }
148            if let Some(val) = modified {
149                writer.write_flatten_text("dcterms:modified", val, false)?;
150            }
151            if let Some(val) = content_status {
152                writer.write_flatten_text("cp:contentStatus", val, false)?;
153            }
154            if let Some(val) = language {
155                writer.write_flatten_text("dc:language", val, false)?;
156            }
157            if let Some(val) = category {
158                writer.write_flatten_text("cp:category", val, false)?;
159            }
160            writer.write_element_end_close("cp:coreProperties")?;
161        }
162
163        log::debug!("[Core] Finished writing.");
164
165        Ok(())
166    }
167}
168
169impl<'a> XmlWrite for CoreNoNamespace<'a> {
170    fn to_writer<W: Write>(&self, writer: &mut XmlWriter<W>) -> XmlResult<()> {
171        let CoreNoNamespace {
172            title,
173            subject,
174            creator,
175            keywords,
176            description,
177            last_modified_by,
178            revision,
179            created,
180            modified,
181            content_status,
182            language,
183            category,
184        } = self;
185
186        log::debug!("[Core] Started writing.");
187        let _ = write!(writer.inner, "{}", SCHEMA_XML);
188
189        writer.write_element_start("cp:coreProperties")?;
190
191        writer.write_attribute("xmlns:cp", SCHEMA_CORE_2)?;
192
193        writer.write_attribute("xmlns:dc", SCHEMA_DC)?;
194
195        if title.is_none()
196            && subject.is_none()
197            && creator.is_none()
198            && keywords.is_none()
199            && description.is_none()
200            && last_modified_by.is_none()
201            && revision.is_none()
202        {
203            writer.write_element_end_empty()?;
204        } else {
205            writer.write_element_end_open()?;
206            if let Some(val) = title {
207                writer.write_flatten_text("dc:title", val, false)?;
208            }
209            if let Some(val) = subject {
210                writer.write_flatten_text("dc:subject", val, false)?;
211            }
212            if let Some(val) = creator {
213                writer.write_flatten_text("dc:creator", val, false)?;
214            }
215            if let Some(val) = keywords {
216                writer.write_flatten_text("cp:keywords", val, false)?;
217            }
218            if let Some(val) = description {
219                writer.write_flatten_text("dc:description", val, false)?;
220            }
221            if let Some(val) = last_modified_by {
222                writer.write_flatten_text("cp:lastModifiedBy", val, false)?;
223            }
224            if let Some(val) = revision {
225                writer.write_flatten_text("cp:revision", val, false)?;
226            }
227            if let Some(val) = created {
228                writer.write_flatten_text("dcterms:created", val, false)?;
229            }
230            if let Some(val) = modified {
231                writer.write_flatten_text("dcterms:modified", val, false)?;
232            }
233            if let Some(val) = content_status {
234                writer.write_flatten_text("cp:contentStatus", val, false)?;
235            }
236            if let Some(val) = language {
237                writer.write_flatten_text("dc:language", val, false)?;
238            }
239            if let Some(val) = category {
240                writer.write_flatten_text("cp:category", val, false)?;
241            }
242            writer.write_element_end_close("cp:coreProperties")?;
243        }
244
245        log::debug!("[Core] Finished writing.");
246
247        Ok(())
248    }
249}