#[derive(Default, Debug, PartialEq, Eq, Hash)]
pub struct Attribute {
prefix: Option<String>,
name: String,
value: String,
}
impl Attribute {
pub fn new(prefix: Option<&str>, name: &str, value: &str) -> Attribute {
Self {
prefix: prefix.map(String::from),
name: name.to_owned(),
value: value.to_owned(),
}
}
#[inline(always)]
pub fn name(&self) -> &str {
&self.name
}
#[inline(always)]
pub fn value(&self) -> &str {
&self.value
}
}
impl std::fmt::Display for Attribute {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(prefix) = &self.prefix {
write!(f, "{}:{}=\"{}\"", prefix, self.name, self.value)
} else {
write!(f, "{}=\"{}\"", self.name, self.value)
}
}
}
#[derive(Debug, Default, PartialEq, Eq)]
pub struct Element {
name: String,
attributes: Vec<Attribute>,
childrens: Vec<Element>,
}
impl Element {
pub fn new(name: &str) -> Element {
Element {
name: name.to_owned(),
..Default::default()
}
}
pub fn with_capacity(name: &str, capacity: usize) -> Element {
Element {
name: name.to_owned(),
attributes: Vec::with_capacity(capacity),
..Default::default()
}
}
pub fn set_attribute(&mut self, name: &str, value: &str) {
if self.attributes.iter().any(|a| a.name() == name) {
return;
}
self.attributes.push(Attribute::new(None, name, value));
}
pub fn set_attribute_with_prefix(&mut self, prefix: Option<&str>, name: &str, value: &str) {
if self
.attributes
.iter()
.any(|a| a.name() == name && a.prefix.as_deref() == prefix)
{
return;
}
self.attributes.push(Attribute::new(prefix, name, value));
}
#[inline]
pub fn append_child(&mut self, child: Element) {
self.childrens.push(child);
}
#[inline]
pub fn childrens(&self) -> impl Iterator<Item = &Element> {
self.childrens.iter()
}
#[inline]
pub fn descendants(&self) -> Descendants<'_> {
Descendants::new(self)
}
#[inline]
pub fn attributes(&self) -> impl Iterator<Item = &Attribute> {
self.attributes.iter()
}
#[inline]
pub fn name(&self) -> &str {
&self.name
}
#[inline]
pub fn attr(&self, name: &str) -> Option<&str> {
self.attributes
.iter()
.find(|x| x.name() == name)
.map(|x| x.value())
}
pub(crate) fn fmt_with_indent(
&self,
f: &mut std::fmt::Formatter<'_>,
indent: usize,
) -> std::fmt::Result {
let indent_str = " ".repeat(indent);
write!(f, "{}<{}", indent_str, self.name)?;
if self.attributes.len() > 1 {
let indent_str = " ".repeat(indent + 1);
write!(f, "\n{}", indent_str)?;
for (idx, attr) in self.attributes.iter().enumerate() {
write!(f, "{}", attr)?;
if idx != self.attributes.len() - 1 {
write!(f, "\n{}", indent_str)?;
}
}
} else if self.attributes.len() == 1 {
write!(f, " {}", self.attributes().next().unwrap())?;
}
if self.childrens.is_empty() {
writeln!(f, "/>")?;
} else {
writeln!(f, ">")?;
for child in &self.childrens {
child.fmt_with_indent(f, indent + 1)?;
}
writeln!(f, "{}</{}>", indent_str, self.name)?;
}
Ok(())
}
}
impl std::fmt::Display for Element {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "<?xml version=\"1.0\" encoding=\"utf-8\"?>")?;
self.fmt_with_indent(f, 0)
}
}
pub struct Descendants<'a> {
stack: Vec<std::slice::Iter<'a, Element>>,
}
impl<'a> Descendants<'a> {
fn new(root: &'a Element) -> Descendants<'a> {
Descendants {
stack: vec![root.childrens.iter()],
}
}
}
impl<'a> Iterator for Descendants<'a> {
type Item = &'a Element;
fn next(&mut self) -> Option<Self::Item> {
while let Some(top_iter) = self.stack.last_mut() {
if let Some(next_elem) = top_iter.next() {
if !next_elem.childrens.is_empty() {
self.stack.push(next_elem.childrens.iter());
}
return Some(next_elem);
} else {
self.stack.pop();
}
}
None
}
}