use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, BytesText, Event};
use quick_xml::Writer;
use std::io::Write;
pub type Result<T> = std::io::Result<T>;
pub struct XmlWriter<W: Write> {
inner: Writer<W>,
}
impl<W: Write> XmlWriter<W> {
pub fn new(writer: W) -> Self {
Self {
inner: Writer::new_with_indent(writer, b' ', 2),
}
}
pub fn into_inner(self) -> W {
self.inner.into_inner()
}
pub fn writer(&mut self) -> &mut Writer<W> {
&mut self.inner
}
pub fn write_xml_declaration(&mut self) -> Result<()> {
self.inner
.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), Some("yes"))))
}
pub fn write_start_element<I, K, V>(&mut self, name: &str, attrs: I) -> Result<()>
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<str>,
V: AsRef<str>,
{
let mut element = BytesStart::new(name);
for (key, value) in attrs {
element.push_attribute((key.as_ref(), value.as_ref()));
}
self.inner.write_event(Event::Start(element))
}
pub fn write_empty_element<I, K, V>(&mut self, name: &str, attrs: I) -> Result<()>
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<str>,
V: AsRef<str>,
{
let mut element = BytesStart::new(name);
for (key, value) in attrs {
element.push_attribute((key.as_ref(), value.as_ref()));
}
self.inner.write_event(Event::Empty(element))
}
pub fn write_start_element_with_ns<I, N, K1, V1, K2, V2>(
&mut self,
name: &str,
namespaces: N,
attrs: I,
) -> Result<()>
where
I: IntoIterator<Item = (K1, V1)>,
N: IntoIterator<Item = (K2, V2)>,
K1: AsRef<str>,
V1: AsRef<str>,
K2: AsRef<str>,
V2: AsRef<str>,
{
let mut element = BytesStart::new(name);
for (prefix, uri) in namespaces {
if prefix.as_ref().is_empty() {
element.push_attribute(("xmlns", uri.as_ref()));
} else {
let key = format!("xmlns:{}", prefix.as_ref());
element.push_attribute((key.as_str(), uri.as_ref()));
}
}
for (key, value) in attrs {
element.push_attribute((key.as_ref(), value.as_ref()));
}
self.inner.write_event(Event::Start(element))
}
pub fn write_end_element(&mut self, name: &str) -> Result<()> {
self.inner.write_event(Event::End(BytesEnd::new(name)))
}
pub fn write_text(&mut self, text: &str) -> Result<()> {
self.inner.write_event(Event::Text(BytesText::new(text)))
}
pub fn write_text_element<I, K, V>(&mut self, name: &str, attrs: I, text: &str) -> Result<()>
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<str>,
V: AsRef<str>,
{
self.write_start_element(name, attrs)?;
self.write_text(text)?;
self.write_end_element(name)
}
}