1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
//! Macro simplification for emitting XML.
#[allow(unused_imports)]
use xml::writer::XmlEvent;
/// Write [`XmlEvent`]s to the supplied writer.
///
/// The first argument to the macro is always the writer object.
/// When writing elements, the second argument is the tag name, followed by an
/// optional list of `attr: "value"` pairs, separated by commas.
///
/// If the content of the element is just text, the above will be followed by a `;`
/// and an expression giving the text.
///
/// If the content is more XML, the start definition will be followed by `=>` and
/// a block. The block contains further XML writing code must return a [`Result`];
///
/// If you want to just send text to the XML, the only thing following the writer
/// should be a `;` and and expression giving the text.
///
/// ## Examples
///
/// ```rust, no_run
/// # use std::fs::File;
/// use xml::writer::{EmitterConfig, XmlEvent};
/// use timelog::emit_xml;
/// use timelog::Result;
///
/// # fn main() -> Result<()> {
/// let mut file = File::create("output.html").expect("Can't open file");
/// let mut w = EmitterConfig::new()
/// .perform_indent(true)
/// .write_document_declaration(false)
/// .create_writer(&mut file);
///
/// emit_xml!(w, html => {
/// emit_xml!(w, head => {
/// emit_xml!(w, title; "This is the page")
/// })?;
/// emit_xml!(w, body => {
/// emit_xml!(w, div, class: "group" => {
/// emit_xml!(w, h1; &format!("Page for {}", "me"))?;
/// emit_xml!(w, p, class: "stuff"; "Useless text")?;
/// emit_xml!(w, br)
/// })?;
/// emit_xml!(w, p => {
/// emit_xml!(w; "This is some random text.")?;
/// emit_xml!(w, em; "That is part of more formatted text.")
/// })
/// })
/// })?;
///
/// # Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! emit_xml {
($target:expr; $text:expr) => {
{
$target.write(XmlEvent::from(XmlEvent::characters($text)))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident; $text:expr) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
$target.write(XmlEvent::from(XmlEvent::characters($text)))?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident, $($attr:ident: $val:expr),+; $text:expr) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
$(
.attr(stringify!($attr), $val)
)+
))?;
$target.write(XmlEvent::from(XmlEvent::characters($text)))?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident => $block:block) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
$block?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident, $($attr:ident: $val:expr),+ => $block:block) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
$(
.attr(stringify!($attr), $val)
)+
))?;
let result: crate::Result<()> = $block;
result?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
($target:expr, $tag:ident, $($attr:ident: $val:expr),+) => {
{
$target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
$(
.attr(stringify!($attr), $val)
)+
))?;
$target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
crate::Result::Ok(())
}
};
}