1//! Provides the `Node` struct, which represents a node in the DOM.
2
3use crate::element::{Element, ElementBuilder};
4use crate::error::Result;
5
6use std::io::Write;
7
8use quick_xml::Writer as EventWriter;
9use quick_xml::events::{Event, BytesText};
10
11/// A node in an element tree.
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub enum Node {
14 /// An `Element`.
15 Element(Element),
16 /// A text node.
17 Text(String),
18 #[cfg(feature = "comments")]
19 /// A comment node.
20 Comment(String),
21}
22
23impl Node {
24 /// Turns this into a reference to an `Element` if this is an element node.
25 /// Else this returns `None`.
26 ///
27 /// # Examples
28 ///
29 /// ```rust
30 /// use minidom::Node;
31 ///
32 /// let elm = Node::Element("<meow />".parse().unwrap());
33 /// let txt = Node::Text("meow".to_owned());
34 ///
35 /// assert_eq!(elm.as_element().unwrap().name(), "meow");
36 /// assert_eq!(txt.as_element(), None);
37 /// ```
38 pub fn as_element(&self) -> Option<&Element> {
39 match *self {
40 Node::Element(ref e) => Some(e),
41 Node::Text(_) => None,
42 #[cfg(feature = "comments")]
43 Node::Comment(_) => None,
44 }
45 }
46
47 /// Turns this into a mutable reference of an `Element` if this is an element node.
48 /// Else this returns `None`.
49 ///
50 /// # Examples
51 ///
52 /// ```rust
53 /// use minidom::Node;
54 ///
55 /// let mut elm = Node::Element("<meow />".parse().unwrap());
56 /// let mut txt = Node::Text("meow".to_owned());
57 ///
58 /// assert_eq!(elm.as_element_mut().unwrap().name(), "meow");
59 /// assert_eq!(txt.as_element_mut(), None);
60 /// ```
61 pub fn as_element_mut(&mut self) -> Option<&mut Element> {
62 match *self {
63 Node::Element(ref mut e) => Some(e),
64 Node::Text(_) => None,
65 #[cfg(feature = "comments")]
66 Node::Comment(_) => None,
67 }
68 }
69
70 /// Turns this into an `Element`, consuming self, if this is an element node.
71 /// Else this returns `None`.
72 ///
73 /// # Examples
74 ///
75 /// ```rust
76 /// use minidom::Node;
77 ///
78 /// let elm = Node::Element("<meow />".parse().unwrap());
79 /// let txt = Node::Text("meow".to_owned());
80 ///
81 /// assert_eq!(elm.into_element().unwrap().name(), "meow");
82 /// assert_eq!(txt.into_element(), None);
83 /// ```
84 pub fn into_element(self) -> Option<Element> {
85 match self {
86 Node::Element(e) => Some(e),
87 Node::Text(_) => None,
88 #[cfg(feature = "comments")]
89 Node::Comment(_) => None,
90 }
91 }
92
93 /// Turns this into an `&str` if this is a text node.
94 /// Else this returns `None`.
95 ///
96 /// # Examples
97 ///
98 /// ```rust
99 /// use minidom::Node;
100 ///
101 /// let elm = Node::Element("<meow />".parse().unwrap());
102 /// let txt = Node::Text("meow".to_owned());
103 ///
104 /// assert_eq!(elm.as_text(), None);
105 /// assert_eq!(txt.as_text().unwrap(), "meow");
106 /// ```
107 pub fn as_text(&self) -> Option<&str> {
108 match *self {
109 Node::Element(_) => None,
110 Node::Text(ref s) => Some(s),
111 #[cfg(feature = "comments")]
112 Node::Comment(_) => None,
113 }
114 }
115
116 /// Turns this into an `&mut String` if this is a text node.
117 /// Else this returns `None`.
118 ///
119 /// # Examples
120 ///
121 /// ```rust
122 /// use minidom::Node;
123 ///
124 /// let mut elm = Node::Element("<meow />".parse().unwrap());
125 /// let mut txt = Node::Text("meow".to_owned());
126 ///
127 /// assert_eq!(elm.as_text_mut(), None);
128 /// {
129 /// let text_mut = txt.as_text_mut().unwrap();
130 /// assert_eq!(text_mut, "meow");
131 /// text_mut.push_str("zies");
132 /// assert_eq!(text_mut, "meowzies");
133 /// }
134 /// assert_eq!(txt.as_text().unwrap(), "meowzies");
135 /// ```
136 pub fn as_text_mut(&mut self) -> Option<&mut String> {
137 match *self {
138 Node::Element(_) => None,
139 Node::Text(ref mut s) => Some(s),
140 #[cfg(feature = "comments")]
141 Node::Comment(_) => None,
142 }
143 }
144
145 /// Turns this into an `String`, consuming self, if this is a text node.
146 /// Else this returns `None`.
147 ///
148 /// # Examples
149 ///
150 /// ```rust
151 /// use minidom::Node;
152 ///
153 /// let elm = Node::Element("<meow />".parse().unwrap());
154 /// let txt = Node::Text("meow".to_owned());
155 ///
156 /// assert_eq!(elm.into_text(), None);
157 /// assert_eq!(txt.into_text().unwrap(), "meow");
158 /// ```
159 pub fn into_text(self) -> Option<String> {
160 match self {
161 Node::Element(_) => None,
162 Node::Text(s) => Some(s),
163 #[cfg(feature = "comments")]
164 Node::Comment(_) => None,
165 }
166 }
167
168 #[doc(hidden)]
169 pub(crate) fn write_to_inner<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()>{
170 match *self {
171 Node::Element(ref elmt) => elmt.write_to_inner(writer)?,
172 Node::Text(ref s) => {
173 writer.write_event(Event::Text(BytesText::from_plain_str(s)))?;
174 },
175 #[cfg(feature = "comments")]
176 Node::Comment(ref s) => {
177 writer.write_event(Event::Comment(BytesText::from_plain_str(s)))?;
178 },
179 }
180
181 Ok(())
182 }
183}
184
185impl From<Element> for Node {
186 fn from(elm: Element) -> Node {
187 Node::Element(elm)
188 }
189}
190
191impl From<String> for Node {
192 fn from(s: String) -> Node {
193 Node::Text(s)
194 }
195}
196
197impl<'a> From<&'a str> for Node {
198 fn from(s: &'a str) -> Node {
199 Node::Text(s.to_owned())
200 }
201}
202
203impl From<ElementBuilder> for Node {
204 fn from(builder: ElementBuilder) -> Node {
205 Node::Element(builder.build())
206 }
207}