Skip to content

Commit 76ce809

Browse files
authored
Merge pull request #14 from dobo90/master
Add options to expand empty tags and to skip line breaks
2 parents da23656 + 20371e4 commit 76ce809

4 files changed

Lines changed: 141 additions & 14 deletions

File tree

src/builder.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ pub struct XMLBuilder {
2828
///
2929
/// Defaults to `false`.
3030
sort_attributes: bool,
31+
32+
/// Whether we want to break lines or not.
33+
///
34+
/// Defaults to `true`.
35+
break_lines: bool,
36+
37+
/// Whether we want to expand empty tags or not.
38+
///
39+
/// Defaults to `false`.
40+
expand_empty_tags: bool,
3141
}
3242

3343
impl Default for XMLBuilder {
@@ -38,6 +48,8 @@ impl Default for XMLBuilder {
3848
standalone: None,
3949
indent: true,
4050
sort_attributes: false,
51+
break_lines: true,
52+
expand_empty_tags: false,
4153
}
4254
}
4355
}
@@ -91,6 +103,20 @@ impl XMLBuilder {
91103
self
92104
}
93105

106+
/// Sets whether to break lines.
107+
pub fn break_lines(mut self, break_lines: bool) -> Self {
108+
self.break_lines = break_lines;
109+
110+
self
111+
}
112+
113+
/// Sets whether to expand empty tags.
114+
pub fn expand_empty_tags(mut self, expand_empty_tags: bool) -> Self {
115+
self.expand_empty_tags = expand_empty_tags;
116+
117+
self
118+
}
119+
94120
/// Builds a new XML structure by consuming self.
95121
pub fn build(self) -> XML {
96122
XML::new(
@@ -99,6 +125,8 @@ impl XMLBuilder {
99125
self.standalone,
100126
self.indent,
101127
self.sort_attributes,
128+
self.break_lines,
129+
self.expand_empty_tags,
102130
)
103131
}
104132
}

src/xml.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ pub struct XML {
3232
/// Defaults to `true`.
3333
indent: bool,
3434

35+
/// Whether we want to break lines or not.
36+
///
37+
/// Defaults to `true`.
38+
break_lines: bool,
39+
40+
/// Whether we want to expand empty tags or not.
41+
///
42+
/// Defaults to `false`.
43+
expand_empty_tags: bool,
44+
3545
/// The root XML element.
3646
root: Option<XMLElement>,
3747
}
@@ -43,13 +53,17 @@ impl XML {
4353
standalone: Option<bool>,
4454
indent: bool,
4555
sort_attributes: bool,
56+
break_lines: bool,
57+
expand_empty_tags: bool,
4658
) -> Self {
4759
Self {
4860
version,
4961
encoding,
5062
standalone,
5163
indent,
5264
sort_attributes,
65+
break_lines,
66+
expand_empty_tags,
5367
root: None,
5468
}
5569
}
@@ -71,16 +85,26 @@ impl XML {
7185
Some(_) => r#" standalone="yes""#.to_string(),
7286
None => String::default(),
7387
};
88+
let suffix = match self.break_lines {
89+
true => "\n",
90+
false => "",
91+
};
7492

75-
writeln!(
93+
write!(
7694
writer,
77-
r#"<?xml version="{}" encoding="{}"{}?>"#,
78-
self.version, self.encoding, standalone_attribute
95+
r#"<?xml version="{}" encoding="{}"{}?>{}"#,
96+
self.version, self.encoding, standalone_attribute, suffix
7997
)?;
8098

8199
// And then XML elements if present...
82100
if let Some(elem) = &self.root {
83-
elem.render(&mut writer, self.sort_attributes, self.indent)?;
101+
elem.render(
102+
&mut writer,
103+
self.sort_attributes,
104+
self.indent,
105+
self.break_lines,
106+
self.expand_empty_tags,
107+
)?;
84108
}
85109

86110
Ok(())

src/xmlelement.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,17 @@ impl XMLElement {
140140
writer: &mut W,
141141
should_sort: bool,
142142
should_indent: bool,
143+
should_break_lines: bool,
144+
should_expand_empty_tags: bool,
143145
) -> Result<()> {
144-
self.render_level(writer, 0, should_sort, should_indent)
146+
self.render_level(
147+
writer,
148+
0,
149+
should_sort,
150+
should_indent,
151+
should_break_lines,
152+
should_expand_empty_tags,
153+
)
145154
}
146155

147156
/// Internal method rendering and indenting a XMLELement object
@@ -156,30 +165,56 @@ impl XMLElement {
156165
level: usize,
157166
should_sort: bool,
158167
should_indent: bool,
168+
should_break_lines: bool,
169+
should_expand_empty_tags: bool,
159170
) -> Result<()> {
160171
let indent = match should_indent {
161172
true => "\t".repeat(level),
162173
false => "".into(),
163174
};
175+
let suffix = match should_break_lines {
176+
true => "\n",
177+
false => "",
178+
};
164179

165180
let attributes = self.attributes_as_string(should_sort);
166181

167182
match &self.content {
168-
XMLElementContent::Empty => {
169-
writeln!(writer, "{}<{}{} />", indent, self.name, attributes)?;
170-
}
183+
XMLElementContent::Empty => match should_expand_empty_tags {
184+
true => {
185+
write!(
186+
writer,
187+
"{}<{}{}></{}>{}",
188+
indent, self.name, attributes, self.name, suffix
189+
)?;
190+
}
191+
false => {
192+
write!(
193+
writer,
194+
"{}<{}{} />{}",
195+
indent, self.name, attributes, suffix
196+
)?;
197+
}
198+
},
171199
XMLElementContent::Elements(elements) => {
172-
writeln!(writer, "{}<{}{}>", indent, self.name, attributes)?;
200+
write!(writer, "{}<{}{}>{}", indent, self.name, attributes, suffix)?;
173201
for elem in elements {
174-
elem.render_level(writer, level + 1, should_sort, should_indent)?;
202+
elem.render_level(
203+
writer,
204+
level + 1,
205+
should_sort,
206+
should_indent,
207+
should_break_lines,
208+
should_expand_empty_tags,
209+
)?;
175210
}
176-
writeln!(writer, "{}</{}>", indent, self.name)?;
211+
write!(writer, "{}</{}>{}", indent, self.name, suffix)?;
177212
}
178213
XMLElementContent::Text(text) => {
179-
writeln!(
214+
write!(
180215
writer,
181-
"{}<{}{}>{}</{}>",
182-
indent, self.name, attributes, text, self.name
216+
"{}<{}{}>{}</{}>{}",
217+
indent, self.name, attributes, text, self.name, suffix
183218
)?;
184219
}
185220
};

tests/tests.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,46 @@ fn test_indent() {
6767
assert_eq!(res, expected, "Both values does not match...");
6868
}
6969

70+
#[test]
71+
fn test_line_breaks() {
72+
let mut xml = XMLBuilder::new().break_lines(false).build();
73+
74+
let mut root = XMLElement::new("root");
75+
let element = XMLElement::new("element");
76+
77+
root.add_child(element).unwrap();
78+
xml.set_root_element(root);
79+
80+
let mut writer: Vec<u8> = Vec::new();
81+
xml.generate(&mut writer).unwrap();
82+
83+
let expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\t<element /></root>";
84+
let res = std::str::from_utf8(&writer).unwrap();
85+
86+
assert_eq!(res, expected, "Both values does not match...");
87+
}
88+
89+
#[test]
90+
fn test_expand_empty_tags() {
91+
let mut xml = XMLBuilder::new().expand_empty_tags(true).build();
92+
93+
let mut root = XMLElement::new("root");
94+
let element = XMLElement::new("element");
95+
96+
root.add_child(element).unwrap();
97+
98+
xml.set_root_element(root);
99+
100+
let mut writer: Vec<u8> = Vec::new();
101+
xml.generate(&mut writer).unwrap();
102+
103+
let expected =
104+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n\t<element></element>\n</root>\n";
105+
let res = std::str::from_utf8(&writer).unwrap();
106+
107+
assert_eq!(res, expected, "Both values does not match...");
108+
}
109+
70110
#[test]
71111
fn test_xml_version_1_0() {
72112
let xml = XMLBuilder::new().version(XMLVersion::XML1_0).build();

0 commit comments

Comments
 (0)