node.rs

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