Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options to expand empty tags and to skip line breaks #14

Merged
merged 2 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ pub struct XMLBuilder {
///
/// Defaults to `false`.
sort_attributes: bool,

/// Whether we want to break lines or not.
///
/// Defaults to `true`.
break_lines: bool,

/// Whether we want to expand empty tags or not.
///
/// Defaults to `false`.
expand_empty_tags: bool,
}

impl Default for XMLBuilder {
Expand All @@ -38,6 +48,8 @@ impl Default for XMLBuilder {
standalone: None,
indent: true,
sort_attributes: false,
break_lines: true,
expand_empty_tags: false,
}
}
}
Expand Down Expand Up @@ -91,6 +103,20 @@ impl XMLBuilder {
self
}

/// Sets whether to break lines.
pub fn break_lines(mut self, break_lines: bool) -> Self {
self.break_lines = break_lines;

self
}

/// Sets whether to expand empty tags.
pub fn expand_empty_tags(mut self, expand_empty_tags: bool) -> Self {
self.expand_empty_tags = expand_empty_tags;

self
}

/// Builds a new XML structure by consuming self.
pub fn build(self) -> XML {
XML::new(
Expand All @@ -99,6 +125,8 @@ impl XMLBuilder {
self.standalone,
self.indent,
self.sort_attributes,
self.break_lines,
self.expand_empty_tags,
)
}
}
32 changes: 28 additions & 4 deletions src/xml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ pub struct XML {
/// Defaults to `true`.
indent: bool,

/// Whether we want to break lines or not.
///
/// Defaults to `true`.
break_lines: bool,

/// Whether we want to expand empty tags or not.
///
/// Defaults to `false`.
expand_empty_tags: bool,

/// The root XML element.
root: Option<XMLElement>,
}
Expand All @@ -43,13 +53,17 @@ impl XML {
standalone: Option<bool>,
indent: bool,
sort_attributes: bool,
break_lines: bool,
expand_empty_tags: bool,
) -> Self {
Self {
version,
encoding,
standalone,
indent,
sort_attributes,
break_lines,
expand_empty_tags,
root: None,
}
}
Expand All @@ -71,16 +85,26 @@ impl XML {
Some(_) => r#" standalone="yes""#.to_string(),
None => String::default(),
};
let suffix = match self.break_lines {
true => "\n",
false => "",
};

writeln!(
write!(
writer,
r#"<?xml version="{}" encoding="{}"{}?>"#,
self.version, self.encoding, standalone_attribute
r#"<?xml version="{}" encoding="{}"{}?>{}"#,
self.version, self.encoding, standalone_attribute, suffix
)?;

// And then XML elements if present...
if let Some(elem) = &self.root {
elem.render(&mut writer, self.sort_attributes, self.indent)?;
elem.render(
&mut writer,
self.sort_attributes,
self.indent,
self.break_lines,
self.expand_empty_tags,
)?;
}

Ok(())
Expand Down
55 changes: 45 additions & 10 deletions src/xmlelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,17 @@ impl XMLElement {
writer: &mut W,
should_sort: bool,
should_indent: bool,
should_break_lines: bool,
should_expand_empty_tags: bool,
) -> Result<()> {
self.render_level(writer, 0, should_sort, should_indent)
self.render_level(
writer,
0,
should_sort,
should_indent,
should_break_lines,
should_expand_empty_tags,
)
}

/// Internal method rendering and indenting a XMLELement object
Expand All @@ -156,30 +165,56 @@ impl XMLElement {
level: usize,
should_sort: bool,
should_indent: bool,
should_break_lines: bool,
should_expand_empty_tags: bool,
) -> Result<()> {
let indent = match should_indent {
true => "\t".repeat(level),
false => "".into(),
};
let suffix = match should_break_lines {
true => "\n",
false => "",
};

let attributes = self.attributes_as_string(should_sort);

match &self.content {
XMLElementContent::Empty => {
writeln!(writer, "{}<{}{} />", indent, self.name, attributes)?;
}
XMLElementContent::Empty => match should_expand_empty_tags {
true => {
write!(
writer,
"{}<{}{}></{}>{}",
indent, self.name, attributes, self.name, suffix
)?;
}
false => {
write!(
writer,
"{}<{}{} />{}",
indent, self.name, attributes, suffix
)?;
}
},
XMLElementContent::Elements(elements) => {
writeln!(writer, "{}<{}{}>", indent, self.name, attributes)?;
write!(writer, "{}<{}{}>{}", indent, self.name, attributes, suffix)?;
for elem in elements {
elem.render_level(writer, level + 1, should_sort, should_indent)?;
elem.render_level(
writer,
level + 1,
should_sort,
should_indent,
should_break_lines,
should_expand_empty_tags,
)?;
}
writeln!(writer, "{}</{}>", indent, self.name)?;
write!(writer, "{}</{}>{}", indent, self.name, suffix)?;
}
XMLElementContent::Text(text) => {
writeln!(
write!(
writer,
"{}<{}{}>{}</{}>",
indent, self.name, attributes, text, self.name
"{}<{}{}>{}</{}>{}",
indent, self.name, attributes, text, self.name, suffix
)?;
}
};
Expand Down
40 changes: 40 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,46 @@ fn test_indent() {
assert_eq!(res, expected, "Both values does not match...");
}

#[test]
fn test_line_breaks() {
let mut xml = XMLBuilder::new().break_lines(false).build();

let mut root = XMLElement::new("root");
let element = XMLElement::new("element");

root.add_child(element).unwrap();
xml.set_root_element(root);

let mut writer: Vec<u8> = Vec::new();
xml.generate(&mut writer).unwrap();

let expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\t<element /></root>";
let res = std::str::from_utf8(&writer).unwrap();

assert_eq!(res, expected, "Both values does not match...");
}

#[test]
fn test_expand_empty_tags() {
let mut xml = XMLBuilder::new().expand_empty_tags(true).build();

let mut root = XMLElement::new("root");
let element = XMLElement::new("element");

root.add_child(element).unwrap();

xml.set_root_element(root);

let mut writer: Vec<u8> = Vec::new();
xml.generate(&mut writer).unwrap();

let expected =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n\t<element></element>\n</root>\n";
let res = std::str::from_utf8(&writer).unwrap();

assert_eq!(res, expected, "Both values does not match...");
}

#[test]
fn test_xml_version_1_0() {
let xml = XMLBuilder::new().version(XMLVersion::XML1_0).build();
Expand Down
Loading