nestxml/
lib.rs

1// Copyright (C) 2018 Stephane Raux. Distributed under the MIT license.
2
3//! Tools to nest XML or HTML elements. Relies on the xml-rs crate.
4//!
5//! # Example
6//!
7//! ```
8//! use xml::EmitterConfig;
9//!
10//! fn main() {
11//!     let out = Vec::new();
12//!     let mut out = EmitterConfig::new()
13//!         .write_document_declaration(false)
14//!         .create_writer(out);
15//!     nestxml::element(&mut out, "contacts").write(|out| {
16//!         nestxml::element(out, "first_name").text("John")?;
17//!         nestxml::element(out, "last_name").text("Doe")
18//!     }).unwrap();
19//!     let out = out.into_inner();
20//!     assert_eq!(&out[..], &b"<contacts><first_name>John</first_name>\
21//!         <last_name>Doe</last_name></contacts>"[..]);
22//! }
23//! ```
24
25#![deny(missing_docs)]
26#![deny(warnings)]
27
28#[macro_use]
29mod macros;
30pub mod html;
31
32use std::io::Write;
33use xml::EventWriter;
34use xml::writer::{Error, XmlEvent};
35
36/// XML element
37pub struct Element<'a, W: 'a> {
38    out: &'a mut EventWriter<W>,
39    name: String,
40    attributes: Vec<(String, String)>,
41}
42
43impl<'a, W: Write + 'a> Element<'a, W> {
44    /// Returns a XML element with the given `name` that will be written to
45    /// `out`.
46    pub fn new<S>(out: &'a mut EventWriter<W>, name: S) -> Self
47    where
48        S: Into<String>,
49    {
50        Element {out, name: name.into(), attributes: Vec::new()}
51    }
52
53    /// Adds an attribute to the element.
54    pub fn attr<N, V>(mut self, name: N, value: V) -> Self
55    where
56        N: Into<String>,
57        V: Into<String>,
58    {
59        self.attributes.push((name.into(), value.into()));
60        self
61    }
62
63    /// Writes this element and invokes `f` to fill in its children.
64    pub fn write<F>(self, f: F) -> Result<(), Error>
65    where
66        F: FnOnce(&mut EventWriter<W>) -> Result<(), Error>,
67    {
68        self.write_res(f)
69    }
70
71    /// Writes this element and invokes `f` to fill in its children.
72    pub fn write_res<F, T, E>(self, f: F) -> Result<T, E>
73    where
74        F: FnOnce(&mut EventWriter<W>) -> Result<T, E>,
75        E: From<Error>,
76    {
77        let mut elem_start = XmlEvent::start_element(self.name.as_str());
78        for (name, value) in &self.attributes {
79            elem_start = elem_start.attr(name.as_str(), value.as_str());
80        }
81        self.out.write(elem_start)?;
82        let res = f(self.out)?;
83        self.out.write(XmlEvent::end_element())?;
84        Ok(res)
85    }
86
87    /// Writes this element without children.
88    pub fn empty(self) -> Result<(), Error> {
89        self.write(|_| Ok(()))
90    }
91
92    /// Writes this element with the given text as its only child.
93    pub fn text(self, s: &str) -> Result<(), Error> {
94        self.write(|out| out.write(XmlEvent::characters(s)))
95    }
96}
97
98/// Returns an `Element`.
99pub fn element<'a, W, S>(out: &'a mut EventWriter<W>, name: S) -> Element<'a, W>
100where
101    W: Write + 'a,
102    S: Into<String>,
103{
104    Element::new(out, name)
105}