node.rs

  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}