docx_reader/documents/
content_types.rsuse serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::io::Read;
use xml::reader::{EventReader, XmlEvent};
use crate::reader::{FromXML, ReaderError};
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct ContentTypes {
types: BTreeMap<String, String>,
web_extension_count: usize,
custom_xml_count: usize,
header_count: usize,
footer_count: usize,
}
impl ContentTypes {
pub fn new() -> ContentTypes {
Default::default()
}
pub fn add_content(mut self, path: impl Into<String>, namespace: impl Into<String>) -> Self {
self.types.insert(path.into(), namespace.into());
self
}
pub fn set_default(mut self) -> ContentTypes {
self.types.insert(
"/_rels/.rels".to_owned(),
"application/vnd.openxmlformats-package.relationships+xml".to_owned(),
);
self.types.insert(
"/docProps/app.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.extended-properties+xml".to_owned(),
);
self.types.insert(
"/docProps/core.xml".to_owned(),
"application/vnd.openxmlformats-package.core-properties+xml".to_owned(),
);
self.types.insert(
"/word/_rels/document.xml.rels".to_owned(),
"application/vnd.openxmlformats-package.relationships+xml".to_owned(),
);
self.types.insert(
"/word/settings.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"
.to_owned(),
);
self.types.insert(
"/word/fontTable.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"
.to_owned(),
);
self.types.insert(
"/word/document.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
.to_owned(),
);
self.types.insert(
"/word/styles.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml".to_owned(),
);
self.types.insert(
"/word/comments.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"
.to_owned(),
);
self.types.insert(
"/word/numbering.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"
.to_owned(),
);
self.types.insert(
"/word/commentsExtended.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml"
.to_owned(),
);
self.types.insert(
"/docProps/custom.xml".to_owned(),
"application/vnd.openxmlformats-officedocument.custom-properties+xml".to_owned(),
);
self
}
pub fn add_taskpanes(mut self) -> Self {
self.types.insert(
"/word/webextensions/taskpanes.xml".to_owned(),
"application/vnd.ms-office.webextensiontaskpanes+xml".to_owned(),
);
self
}
pub fn add_web_extensions(mut self) -> Self {
self.types.insert(
format!(
"/word/webextensions/webextension{}.xml",
self.web_extension_count
),
"application/vnd.ms-office.webextension+xml".to_owned(),
);
self.web_extension_count += 1;
self
}
pub fn add_custom_xml(mut self) -> Self {
self.types.insert(
format!("/customXml/itemProps{}.xml", self.web_extension_count),
"application/vnd.openxmlformats-officedocument.customXmlProperties+xml".to_owned(),
);
self.custom_xml_count += 1;
self
}
pub fn add_header(mut self) -> Self {
self.header_count += 1;
self.types.insert(
format!("/word/header{}.xml", self.header_count),
"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml".to_owned(),
);
self
}
pub fn add_footer(mut self) -> Self {
self.footer_count += 1;
self.types.insert(
format!("/word/footer{}.xml", self.footer_count),
"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml".to_owned(),
);
self
}
}
impl Default for ContentTypes {
fn default() -> Self {
ContentTypes {
types: BTreeMap::new(),
web_extension_count: 1,
custom_xml_count: 1,
header_count: 0,
footer_count: 0,
}
}
}
impl FromXML for ContentTypes {
fn from_xml<R: Read>(reader: R) -> Result<Self, ReaderError> {
let parser = EventReader::new(reader);
let mut s = Self::default();
let mut depth = 0;
for e in parser {
match e {
Ok(XmlEvent::StartElement { attributes, .. }) => {
if depth == 1 {
let namespace = attributes[0].value.clone();
let path = attributes[1].value.clone();
s = s.add_content(path, namespace);
}
depth += 1;
}
Ok(XmlEvent::EndElement { .. }) => {
depth -= 1;
}
Err(_) => {}
_ => {}
}
}
Ok(s)
}
}