2018-12-23 14:59:13 +00:00
|
|
|
//! Provides the `Node` struct, which represents a node in the DOM.
|
|
|
|
|
2019-09-13 01:07:02 +00:00
|
|
|
use crate::element::{Element, ElementBuilder};
|
|
|
|
use crate::error::Result;
|
|
|
|
|
2018-12-23 14:59:13 +00:00
|
|
|
use std::io::Write;
|
|
|
|
|
2019-10-22 23:32:41 +00:00
|
|
|
use quick_xml::events::{BytesText, Event};
|
2018-12-23 14:59:13 +00:00
|
|
|
use quick_xml::Writer as EventWriter;
|
|
|
|
|
|
|
|
/// A node in an element tree.
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum Node {
|
|
|
|
/// An `Element`.
|
|
|
|
Element(Element),
|
|
|
|
/// A text node.
|
|
|
|
Text(String),
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
/// A comment node.
|
|
|
|
Comment(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Node {
|
|
|
|
/// Turns this into a reference to an `Element` if this is an element node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.as_element().unwrap().name(), "meow");
|
|
|
|
/// assert_eq!(txt.as_element(), None);
|
|
|
|
/// ```
|
|
|
|
pub fn as_element(&self) -> Option<&Element> {
|
|
|
|
match *self {
|
|
|
|
Node::Element(ref e) => Some(e),
|
|
|
|
Node::Text(_) => None,
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this into a mutable reference of an `Element` if this is an element node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let mut elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let mut txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.as_element_mut().unwrap().name(), "meow");
|
|
|
|
/// assert_eq!(txt.as_element_mut(), None);
|
|
|
|
/// ```
|
|
|
|
pub fn as_element_mut(&mut self) -> Option<&mut Element> {
|
|
|
|
match *self {
|
|
|
|
Node::Element(ref mut e) => Some(e),
|
|
|
|
Node::Text(_) => None,
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this into an `Element`, consuming self, if this is an element node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.into_element().unwrap().name(), "meow");
|
|
|
|
/// assert_eq!(txt.into_element(), None);
|
|
|
|
/// ```
|
|
|
|
pub fn into_element(self) -> Option<Element> {
|
|
|
|
match self {
|
|
|
|
Node::Element(e) => Some(e),
|
|
|
|
Node::Text(_) => None,
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this into an `&str` if this is a text node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.as_text(), None);
|
|
|
|
/// assert_eq!(txt.as_text().unwrap(), "meow");
|
|
|
|
/// ```
|
|
|
|
pub fn as_text(&self) -> Option<&str> {
|
|
|
|
match *self {
|
|
|
|
Node::Element(_) => None,
|
|
|
|
Node::Text(ref s) => Some(s),
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this into an `&mut String` if this is a text node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let mut elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let mut txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.as_text_mut(), None);
|
|
|
|
/// {
|
|
|
|
/// let text_mut = txt.as_text_mut().unwrap();
|
|
|
|
/// assert_eq!(text_mut, "meow");
|
|
|
|
/// text_mut.push_str("zies");
|
|
|
|
/// assert_eq!(text_mut, "meowzies");
|
|
|
|
/// }
|
|
|
|
/// assert_eq!(txt.as_text().unwrap(), "meowzies");
|
|
|
|
/// ```
|
|
|
|
pub fn as_text_mut(&mut self) -> Option<&mut String> {
|
|
|
|
match *self {
|
|
|
|
Node::Element(_) => None,
|
|
|
|
Node::Text(ref mut s) => Some(s),
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this into an `String`, consuming self, if this is a text node.
|
|
|
|
/// Else this returns `None`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use minidom::Node;
|
|
|
|
///
|
|
|
|
/// let elm = Node::Element("<meow />".parse().unwrap());
|
|
|
|
/// let txt = Node::Text("meow".to_owned());
|
|
|
|
///
|
|
|
|
/// assert_eq!(elm.into_text(), None);
|
|
|
|
/// assert_eq!(txt.into_text().unwrap(), "meow");
|
|
|
|
/// ```
|
|
|
|
pub fn into_text(self) -> Option<String> {
|
|
|
|
match self {
|
|
|
|
Node::Element(_) => None,
|
|
|
|
Node::Text(s) => Some(s),
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-10-22 23:32:41 +00:00
|
|
|
pub(crate) fn write_to_inner<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
|
2018-12-23 14:59:13 +00:00
|
|
|
match *self {
|
|
|
|
Node::Element(ref elmt) => elmt.write_to_inner(writer)?,
|
|
|
|
Node::Text(ref s) => {
|
|
|
|
writer.write_event(Event::Text(BytesText::from_plain_str(s)))?;
|
2019-10-22 23:32:41 +00:00
|
|
|
}
|
2019-08-22 16:04:47 +00:00
|
|
|
#[cfg(feature = "comments")]
|
2018-12-23 14:59:13 +00:00
|
|
|
Node::Comment(ref s) => {
|
|
|
|
writer.write_event(Event::Comment(BytesText::from_plain_str(s)))?;
|
2019-10-22 23:32:41 +00:00
|
|
|
}
|
2019-02-21 20:06:23 +00:00
|
|
|
}
|
2018-12-23 14:59:13 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-03 17:49:11 +00:00
|
|
|
impl<I> From<I> for Node
|
|
|
|
where I: Into<Element>
|
|
|
|
{
|
|
|
|
fn from(elm: I) -> Node {
|
|
|
|
Node::Element(elm.into())
|
2018-12-23 14:59:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<String> for Node {
|
|
|
|
fn from(s: String) -> Node {
|
|
|
|
Node::Text(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a str> for Node {
|
|
|
|
fn from(s: &'a str) -> Node {
|
|
|
|
Node::Text(s.to_owned())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ElementBuilder> for Node {
|
|
|
|
fn from(builder: ElementBuilder) -> Node {
|
|
|
|
Node::Element(builder.build())
|
|
|
|
}
|
|
|
|
}
|