use std::io::Write;
use xml::writer::{EventWriter, EmitterConfig, XmlEvent};
use crate::Error;
use crate::structs::{UrlEntry, Location, LastMod, ChangeFreq, Priority, SiteMapEntry};
const DEFAULT_NAMESPACE: &str = "http://www.sitemaps.org/schemas/sitemap/0.9";
pub struct SiteMapWriter<T: Write + Sized> {
writer: EventWriter<T>,
}
impl<T: Write + Sized> SiteMapWriter<T> {
pub fn new(out: T) -> SiteMapWriter<T> {
let writer = EmitterConfig::new().perform_indent(true).create_writer(out);
SiteMapWriter { writer: writer }
}
pub fn start_urlset(self) -> Result<UrlSetWriter<T>, Error> {
return self.start_urlset_ns(DEFAULT_NAMESPACE);
}
pub fn start_urlset_ns(mut self, namespace: &str) -> Result<UrlSetWriter<T>, Error> {
self.writer.write(XmlEvent::start_element("urlset").default_ns(namespace))?;
Ok(UrlSetWriter { sitemap: self })
}
pub fn start_urlset_without_ns(mut self) -> Result<UrlSetWriter<T>, Error> {
self.writer.write(XmlEvent::start_element("urlset"))?;
Ok(UrlSetWriter { sitemap: self })
}
pub fn start_sitemapindex(self) -> Result<SiteMapIndexWriter<T>, Error> {
return self.start_sitemapindex_ns(DEFAULT_NAMESPACE);
}
pub fn start_sitemapindex_ns(
mut self,
namespace: &str,
) -> Result<SiteMapIndexWriter<T>, Error> {
self.writer.write(XmlEvent::start_element("sitemapindex").default_ns(namespace))?;
Ok(SiteMapIndexWriter { sitemap: self })
}
pub fn start_sitemapindex_without_ns(mut self) -> Result<SiteMapIndexWriter<T>, Error> {
self.writer.write(XmlEvent::start_element("sitemapindex"))?;
Ok(SiteMapIndexWriter { sitemap: self })
}
fn write_content_element(&mut self, ele: &str, content: &str) -> Result<(), Error> {
self.writer.write(XmlEvent::start_element(ele))?;
self.writer.write(XmlEvent::characters(content))?;
self.writer.write(XmlEvent::end_element().name(ele))?;
Ok(())
}
}
pub struct UrlSetWriter<T: Write + Sized> {
sitemap: SiteMapWriter<T>,
}
impl<T: Write + Sized> UrlSetWriter<T> {
pub fn url<S: Into<UrlEntry>>(&mut self, url: S) -> Result<(), Error> {
let url = url.into();
self.sitemap.writer.write(XmlEvent::start_element("url"))?;
if let Location::Url(loc) = url.loc {
self.sitemap.write_content_element("loc", loc.as_str())?;
}
if let LastMod::DateTime(lastmod) = url.lastmod {
self.sitemap.write_content_element("lastmod", lastmod.to_rfc3339().as_str())?;
}
match url.changefreq {
ChangeFreq::ParseErr(_) => {}
ChangeFreq::None => {}
_ => {
self.sitemap.write_content_element("changefreq", url.changefreq.as_str())?;
}
}
if let Priority::Value(priority) = url.priority {
self.sitemap.write_content_element("priority", priority.to_string().as_str())?;
}
self.sitemap.writer.write(XmlEvent::end_element().name("url"))?;
Ok(())
}
pub fn end(mut self) -> Result<SiteMapWriter<T>, Error> {
self.sitemap.writer.write(XmlEvent::end_element().name("urlset"))?;
Ok(self.sitemap)
}
}
pub struct SiteMapIndexWriter<T: Write + Sized> {
sitemap: SiteMapWriter<T>,
}
impl<T: Write + Sized> SiteMapIndexWriter<T> {
pub fn sitemap<S: Into<SiteMapEntry>>(&mut self, sitemapentry: S) -> Result<(), Error> {
let sitemapentry = sitemapentry.into();
self.sitemap.writer.write(XmlEvent::start_element("sitemap"))?;
if let Location::Url(loc) = sitemapentry.loc {
self.sitemap.write_content_element("loc", loc.as_str())?;
}
if let LastMod::DateTime(lastmod) = sitemapentry.lastmod {
self.sitemap.write_content_element("lastmod", lastmod.to_rfc3339().as_str())?;
}
self.sitemap.writer.write(XmlEvent::end_element().name("sitemap"))?;
Ok(())
}
pub fn end(mut self) -> Result<SiteMapWriter<T>, Error> {
self.sitemap.writer.write(XmlEvent::end_element().name("sitemapindex"))?;
Ok(self.sitemap)
}
}