2019-11-05 11:03:23 +02:00
|
|
|
#[macro_use]
|
|
|
|
mod macros;
|
2019-11-06 12:17:49 +02:00
|
|
|
|
2019-12-04 10:39:59 +02:00
|
|
|
mod comments;
|
2019-11-06 05:29:17 +02:00
|
|
|
mod core_properties;
|
2019-11-05 11:03:23 +02:00
|
|
|
mod declaration;
|
2019-11-07 09:08:59 +02:00
|
|
|
mod document;
|
2019-11-06 07:55:14 +02:00
|
|
|
mod elements;
|
2019-11-14 12:21:45 +02:00
|
|
|
mod fonts;
|
2019-11-05 12:20:40 +02:00
|
|
|
mod properties;
|
2019-11-05 11:03:23 +02:00
|
|
|
mod relationship;
|
2019-11-14 08:54:39 +02:00
|
|
|
mod settings;
|
2019-11-07 06:57:58 +02:00
|
|
|
mod styles;
|
2019-11-05 11:03:23 +02:00
|
|
|
|
2019-11-07 06:57:58 +02:00
|
|
|
use crate::BuildXML;
|
2019-11-07 09:08:59 +02:00
|
|
|
|
2019-11-06 07:55:14 +02:00
|
|
|
use std::str;
|
2019-11-05 11:03:23 +02:00
|
|
|
use xml::common::XmlVersion;
|
2019-11-05 08:10:48 +02:00
|
|
|
use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
|
|
|
|
|
2019-11-06 12:17:49 +02:00
|
|
|
pub use elements::*;
|
2019-11-06 07:55:14 +02:00
|
|
|
|
2019-11-05 08:10:48 +02:00
|
|
|
pub struct XMLBuilder {
|
|
|
|
writer: EventWriter<Vec<u8>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl XMLBuilder {
|
|
|
|
pub(crate) fn new() -> XMLBuilder {
|
|
|
|
let buf = Vec::new();
|
2019-11-06 07:55:14 +02:00
|
|
|
let mut config = EmitterConfig::new()
|
2019-11-05 08:10:48 +02:00
|
|
|
.write_document_declaration(false)
|
2019-11-06 07:55:14 +02:00
|
|
|
.perform_indent(true);
|
|
|
|
config.perform_escaping = false;
|
|
|
|
let writer = config.create_writer(buf);
|
2019-11-05 08:10:48 +02:00
|
|
|
XMLBuilder { writer }
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:03:23 +02:00
|
|
|
// Build types element
|
|
|
|
// i.e. <Types xmlns="http://...">
|
2019-11-05 08:10:48 +02:00
|
|
|
pub(crate) fn open_types(mut self, uri: &str) -> Self {
|
|
|
|
self.writer
|
|
|
|
.write(XmlEvent::start_element("Types").attr("xmlns", uri))
|
|
|
|
.expect("should write to buf");
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:03:23 +02:00
|
|
|
// Build Override element
|
|
|
|
// i.e. <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
2019-11-05 08:10:48 +02:00
|
|
|
pub(crate) fn add_override(mut self, name: &str, content_type: &str) -> Self {
|
|
|
|
self.writer
|
|
|
|
.write(
|
|
|
|
XmlEvent::start_element("Override")
|
|
|
|
.attr("PartName", &name)
|
|
|
|
.attr("ContentType", &content_type),
|
|
|
|
)
|
|
|
|
.expect("should write to buf");
|
|
|
|
self.close()
|
|
|
|
}
|
|
|
|
|
2019-11-07 06:57:58 +02:00
|
|
|
pub(crate) fn add_child<T>(mut self, child: &T) -> Self
|
|
|
|
where
|
|
|
|
T: BuildXML,
|
|
|
|
{
|
|
|
|
let buf = child.build();
|
|
|
|
let text = str::from_utf8(&buf).unwrap();
|
2019-11-06 07:55:14 +02:00
|
|
|
self.writer.write(text).expect("should write to buf");
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-07 06:57:58 +02:00
|
|
|
pub(crate) fn add_optional_child<T>(mut self, child: &Option<T>) -> Self
|
|
|
|
where
|
|
|
|
T: BuildXML,
|
|
|
|
{
|
|
|
|
if let Some(c) = child {
|
|
|
|
self = self.add_child(c)
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn add_children<T>(mut self, children: &[T]) -> Self
|
|
|
|
where
|
|
|
|
T: BuildXML,
|
|
|
|
{
|
|
|
|
for c in children {
|
|
|
|
self = self.add_child(c);
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:03:23 +02:00
|
|
|
// Close tag
|
2019-11-05 08:10:48 +02:00
|
|
|
pub(crate) fn close(mut self) -> Self {
|
|
|
|
self.writer
|
|
|
|
.write(XmlEvent::end_element())
|
|
|
|
.expect("should end");
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-05 11:03:23 +02:00
|
|
|
// Write plain text
|
2019-11-11 11:34:55 +02:00
|
|
|
#[allow(dead_code)]
|
2019-11-07 09:08:59 +02:00
|
|
|
pub(crate) fn plain_text(mut self, t: &str) -> Self {
|
2019-11-05 11:03:23 +02:00
|
|
|
self.writer.write(t).unwrap();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-05 08:10:48 +02:00
|
|
|
pub(crate) fn build(self) -> Vec<u8> {
|
|
|
|
self.writer.into_inner()
|
|
|
|
}
|
|
|
|
}
|
2019-11-05 11:03:23 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_open_types() {
|
|
|
|
let b = XMLBuilder::new();
|
2019-11-07 09:08:59 +02:00
|
|
|
let r = b
|
|
|
|
.open_types("http://example")
|
|
|
|
.plain_text("child")
|
|
|
|
.close()
|
|
|
|
.build();
|
2019-11-05 11:03:23 +02:00
|
|
|
assert_eq!(
|
|
|
|
str::from_utf8(&r).unwrap(),
|
|
|
|
r#"<Types xmlns="http://example">child</Types>"#
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|