feat: Add rels
parent
7925fc4e24
commit
3e154d6904
|
@ -1,3 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||||
|
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
|
||||||
|
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
|
||||||
|
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
|
||||||
</Relationships>
|
</Relationships>
|
|
@ -1,4 +1,4 @@
|
||||||
use super::xml_builder::*;
|
use crate::xml_builder::*;
|
||||||
|
|
||||||
pub struct ContentTypes {}
|
pub struct ContentTypes {}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ impl ContentTypes {
|
||||||
|
|
||||||
pub fn build(&self) -> Vec<u8> {
|
pub fn build(&self) -> Vec<u8> {
|
||||||
let b = XMLBuilder::new();
|
let b = XMLBuilder::new();
|
||||||
b.add_declaration()
|
b.declaration()
|
||||||
.open_types("http://schemas.openxmlformats.org/package/2006/content-types")
|
.open_types("http://schemas.openxmlformats.org/package/2006/content-types")
|
||||||
.add_override(
|
.add_override(
|
||||||
"/_rels/.rels",
|
"/_rels/.rels",
|
||||||
|
@ -60,7 +60,7 @@ mod tests {
|
||||||
let b = c.build();
|
let b = c.build();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
str::from_utf8(&b).unwrap(),
|
str::from_utf8(&b).unwrap(),
|
||||||
r#"<?xml version="1.0" encoding="UTF-8" />
|
r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
||||||
<Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
|
<Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
|
||||||
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
|
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
pub mod content_types;
|
mod content_types;
|
||||||
mod xml_builder;
|
mod rels;
|
||||||
mod xml_document;
|
mod xml_document;
|
||||||
|
|
||||||
use content_types::*;
|
use content_types::*;
|
||||||
|
use rels::*;
|
||||||
|
|
||||||
pub(crate) struct Document {
|
pub(crate) struct Document {
|
||||||
content_type: ContentTypes,
|
content_type: ContentTypes,
|
||||||
|
rels: Rels,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
pub fn new() -> Document {
|
pub fn new() -> Document {
|
||||||
let content_type = ContentTypes::new();
|
let content_type = ContentTypes::new();
|
||||||
Document { content_type }
|
let rels = Rels::new();
|
||||||
|
Document { content_type, rels }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
use crate::xml_builder::*;
|
||||||
|
|
||||||
|
pub struct Rels {}
|
||||||
|
|
||||||
|
impl Rels {
|
||||||
|
pub fn new() -> Rels {
|
||||||
|
Rels {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(&self) -> Vec<u8> {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
b.declaration()
|
||||||
|
.open_relationships("http://schemas.openxmlformats.org/package/2006/relationships")
|
||||||
|
.relationship(
|
||||||
|
"rId1",
|
||||||
|
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
|
||||||
|
"docProps/core.xml"
|
||||||
|
)
|
||||||
|
.relationship(
|
||||||
|
"rId2",
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
|
||||||
|
"docProps/app.xml"
|
||||||
|
)
|
||||||
|
.relationship(
|
||||||
|
"rId3",
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
||||||
|
"word/document.xml"
|
||||||
|
)
|
||||||
|
.close()
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_build() {
|
||||||
|
let c = Rels::new();
|
||||||
|
let b = c.build();
|
||||||
|
assert_eq!(
|
||||||
|
str::from_utf8(&b).unwrap(),
|
||||||
|
r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||||
|
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml" />
|
||||||
|
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml" />
|
||||||
|
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml" />
|
||||||
|
</Relationships>"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,15 @@ use super::Document;
|
||||||
|
|
||||||
pub(crate) struct XMLDocument {
|
pub(crate) struct XMLDocument {
|
||||||
content_type: Vec<u8>,
|
content_type: Vec<u8>,
|
||||||
|
rels: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Document> for XMLDocument {
|
impl From<Document> for XMLDocument {
|
||||||
fn from(doc: Document) -> XMLDocument {
|
fn from(doc: Document) -> XMLDocument {
|
||||||
let content_type = doc.content_type.build();
|
let content_type = doc.content_type.build();
|
||||||
XMLDocument { content_type }
|
XMLDocument {
|
||||||
|
content_type,
|
||||||
|
rels: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
mod documents;
|
mod documents;
|
||||||
|
mod xml_builder;
|
||||||
|
|
||||||
use documents::*;
|
use documents::*;
|
||||||
|
use xml_builder::*;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
use super::XMLBuilder;
|
||||||
|
|
||||||
|
impl XMLBuilder {
|
||||||
|
// Build XML declaration
|
||||||
|
// i.e. <?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
pub(crate) fn declaration(mut self) -> Self {
|
||||||
|
self.writer
|
||||||
|
.write(super::XmlEvent::StartDocument {
|
||||||
|
version: super::XmlVersion::Version10,
|
||||||
|
encoding: Some("UTF-8"),
|
||||||
|
standalone: None,
|
||||||
|
})
|
||||||
|
.expect("should write to buf");
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_declaration() {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
let r = b.declaration().build();
|
||||||
|
assert_eq!(
|
||||||
|
str::from_utf8(&r).unwrap(),
|
||||||
|
r#"<?xml version="1.0" encoding="UTF-8"?>"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
macro_rules! opened_el {
|
||||||
|
($name: ident, $el_name: expr, $attr0: expr) => {
|
||||||
|
pub(crate) fn $name(mut self, arg0: &str) -> Self {
|
||||||
|
self.writer
|
||||||
|
.write(super::XmlEvent::start_element($el_name).attr($attr0, arg0))
|
||||||
|
.expect("should write to buf");
|
||||||
|
self
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! closed_el {
|
||||||
|
($name: ident, $el_name: expr, $attr0: expr) => {
|
||||||
|
pub(crate) fn $name(mut self, arg0: &str) -> Self {
|
||||||
|
self.writer
|
||||||
|
.write(super::XmlEvent::start_element($el_name).attr($attr0, arg0))
|
||||||
|
.expect("should write to buf");
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($name: ident, $el_name: expr, $attr0: expr, $attr1: expr) => {
|
||||||
|
pub(crate) fn $name(mut self, arg0: &str, arg1: &str) -> Self {
|
||||||
|
self.writer
|
||||||
|
.write(super::XmlEvent::start_element($el_name).attr($attr0, arg0).attr($attr1, arg1))
|
||||||
|
.expect("should write to buf");
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($name: ident, $el_name: expr, $attr0: expr, $attr1: expr, $attr2: expr) => {
|
||||||
|
pub(crate) fn $name(mut self, arg0: &str, arg1: &str, arg2: &str) -> Self {
|
||||||
|
self.writer
|
||||||
|
.write(super::XmlEvent::start_element($el_name).attr($attr0, arg0).attr($attr1, arg1).attr($attr2, arg2))
|
||||||
|
.expect("should write to buf");
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,3 +1,9 @@
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
mod declaration;
|
||||||
|
mod relationship;
|
||||||
|
|
||||||
|
use xml::common::XmlVersion;
|
||||||
use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
|
use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
|
||||||
|
|
||||||
pub struct XMLBuilder {
|
pub struct XMLBuilder {
|
||||||
|
@ -14,17 +20,8 @@ impl XMLBuilder {
|
||||||
XMLBuilder { writer }
|
XMLBuilder { writer }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_declaration(mut self) -> Self {
|
// Build types element
|
||||||
self.writer
|
// i.e. <Types xmlns="http://...">
|
||||||
.write(
|
|
||||||
XmlEvent::start_element("?xml")
|
|
||||||
.attr("version", "1.0")
|
|
||||||
.attr("encoding", "UTF-8"),
|
|
||||||
)
|
|
||||||
.expect("should write to buf");
|
|
||||||
self.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn open_types(mut self, uri: &str) -> Self {
|
pub(crate) fn open_types(mut self, uri: &str) -> Self {
|
||||||
self.writer
|
self.writer
|
||||||
.write(XmlEvent::start_element("Types").attr("xmlns", uri))
|
.write(XmlEvent::start_element("Types").attr("xmlns", uri))
|
||||||
|
@ -32,6 +29,8 @@ impl XMLBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build Override element
|
||||||
|
// i.e. <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
||||||
pub(crate) fn add_override(mut self, name: &str, content_type: &str) -> Self {
|
pub(crate) fn add_override(mut self, name: &str, content_type: &str) -> Self {
|
||||||
self.writer
|
self.writer
|
||||||
.write(
|
.write(
|
||||||
|
@ -43,6 +42,7 @@ impl XMLBuilder {
|
||||||
self.close()
|
self.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close tag
|
||||||
pub(crate) fn close(mut self) -> Self {
|
pub(crate) fn close(mut self) -> Self {
|
||||||
self.writer
|
self.writer
|
||||||
.write(XmlEvent::end_element())
|
.write(XmlEvent::end_element())
|
||||||
|
@ -50,7 +50,30 @@ impl XMLBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write plain text
|
||||||
|
pub(crate) fn text(mut self, t: &str) -> Self {
|
||||||
|
self.writer.write(t).unwrap();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn build(self) -> Vec<u8> {
|
pub(crate) fn build(self) -> Vec<u8> {
|
||||||
self.writer.into_inner()
|
self.writer.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_open_types() {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
let r = b.open_types("http://example").text("child").close().build();
|
||||||
|
assert_eq!(
|
||||||
|
str::from_utf8(&r).unwrap(),
|
||||||
|
r#"<Types xmlns="http://example">child</Types>"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
use super::XMLBuilder;
|
||||||
|
|
||||||
|
impl XMLBuilder {
|
||||||
|
// Build RelationShips element
|
||||||
|
// i.e. <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||||
|
opened_el!(open_relationships, "Relationships", "xmlns");
|
||||||
|
|
||||||
|
// Build Relationship
|
||||||
|
closed_el!(relationship, "Relationship", "Id", "Type", "Target");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::XMLBuilder;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_open_relationships() {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
let r = b
|
||||||
|
.open_relationships("http://example")
|
||||||
|
.text("child")
|
||||||
|
.close()
|
||||||
|
.build();
|
||||||
|
assert_eq!(
|
||||||
|
str::from_utf8(&r).unwrap(),
|
||||||
|
r#"<Relationships xmlns="http://example">child</Relationships>"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_relationship() {
|
||||||
|
let b = XMLBuilder::new();
|
||||||
|
let r = b.relationship("rId1", "http://example", "core.xml").build();
|
||||||
|
assert_eq!(
|
||||||
|
str::from_utf8(&r).unwrap(),
|
||||||
|
r#"<Relationship Id="rId1" Type="http://example" Target="core.xml" />"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue