viral32111_xml/
element.rs1use std::error::Error;
2
3use super::attributes::{self, Attributes};
4
5pub struct Element {
6 pub name: Option<String>,
7 pub value: Option<String>,
8 pub attributes: Option<Attributes>,
9 pub children: Option<Vec<Element>>,
10}
11
12impl Element {}
13
14pub fn parse(text: &str) -> Result<(Element, usize), Box<dyn Error>> {
16 if text.is_empty() {
18 return Err("Empty XML element".into());
19 }
20
21 if !text.starts_with("<") && !text.ends_with(">") {
23 return Ok((
24 Element {
25 name: None,
26 value: Some(text.to_string()),
27 attributes: None,
28 children: None,
29 },
30 text.len(),
31 ));
32 }
33
34 let mut opening_tag_end_position = text.find(">").expect("Tag not terminated");
36
37 let is_self_closing = text[opening_tag_end_position - 1..opening_tag_end_position].eq("/");
39 if is_self_closing {
40 opening_tag_end_position -= 1;
41 }
42
43 let opening_tag = &text[1..opening_tag_end_position];
44
45 let name_end_position = opening_tag.find(" ").unwrap_or(opening_tag.len());
47 let name = &opening_tag[..name_end_position];
48
49 let attributes = if opening_tag.contains(" ") {
51 Some(attributes::parse(&opening_tag[name_end_position..]))
52 } else {
53 None
54 };
55
56 if is_self_closing {
58 return Ok((
59 Element {
60 name: Some(name.to_string()),
61 value: None,
62 attributes,
63 children: None,
64 },
65 opening_tag_end_position + (if is_self_closing { 2 } else { 1 }),
66 ));
67 }
68
69 let closing_tag_position = text
71 .find(&format!("</{}>", name))
72 .expect("Element not terminated");
73
74 let inner_text = &text[opening_tag_end_position + 1..closing_tag_position];
76 let mut children = Vec::new();
77 let mut position = 0;
78 loop {
79 let (child, child_end_position) = parse(&inner_text[position..])?;
80 position += child_end_position;
81 children.push(child);
82
83 if position >= inner_text.len() {
84 break;
85 }
86 }
87
88 Ok((
89 Element {
90 name: Some(name.to_string()),
91 value: None,
92 attributes,
93 children: Some(children),
94 },
95 closing_tag_position + name.len() + 3, ))
97}