use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
#[cfg(feature = "parsing")]
use parser::parse_svg;
#[cfg(feature = "parsing")]
use {ParseOptions, Error};
use writer;
use {
Attributes,
ElementId,
NameRef,
TagName,
TagNameRef,
WriteBuffer,
WriteOptions,
WriteToString,
};
use super::iterators::{Children, Descendants};
use super::node::Node;
use super::node_data::{Link, NodeData};
use super::node_type::NodeType;
pub struct Document {
pub root: Node,
}
impl Document {
pub fn new() -> Document {
Document {
root: Document::new_node(None, NodeType::Root, None, String::new())
}
}
#[cfg(feature = "parsing")]
pub fn from_str(text: &str) -> Result<Document, Error> {
Document::from_str_with_opt(text, &ParseOptions::default())
}
#[cfg(feature = "parsing")]
pub fn from_str_with_opt(text: &str, opt: &ParseOptions) -> Result<Document, Error> {
parse_svg(text, opt)
}
pub fn create_element<'a, T>(&self, tag_name: T) -> Node
where TagNameRef<'a>: From<T>
{
let tn = TagNameRef::from(tag_name);
if let NameRef::Name(name) = tn {
if name.is_empty() {
panic!("supplied tag name is empty");
}
}
Document::new_node(Some(self.root.0.clone()), NodeType::Element, Some(tn), String::new())
}
pub fn create_node(&self, node_type: NodeType, text: &str) -> Node {
debug_assert!(node_type != NodeType::Element && node_type != NodeType::Root);
Document::new_node(Some(self.root.0.clone()), node_type, None, text.to_owned())
}
pub fn root(&self) -> Node {
self.root.clone()
}
pub fn first_child(&self) -> Option<Node> {
self.root().first_child()
}
pub fn svg_element(&self) -> Option<Node> {
for n in self.root.children().svg() {
if n.is_tag_name(ElementId::Svg) {
return Some(n.clone());
}
}
None
}
pub fn append(&self, new_child: &Node) -> Node {
self.root.append(new_child);
new_child.clone()
}
pub fn descendants(&self) -> Descendants {
self.root.descendants()
}
pub fn children(&self) -> Children {
self.root.children()
}
pub fn drain<P>(&self, f: P) -> usize
where P: Fn(&Node) -> bool
{
self.root().drain(f)
}
fn new_node(doc: Option<Link>, node_type: NodeType, tag_name: Option<TagNameRef>,
text: String)
-> Node {
Node(Rc::new(RefCell::new(NodeData {
doc: doc.map(|a| Rc::downgrade(&a)),
parent: None,
first_child: None,
last_child: None,
previous_sibling: None,
next_sibling: None,
node_type: node_type,
tag_name: tag_name.map(TagName::from),
id: String::new(),
attributes: Attributes::new(),
linked_nodes: Vec::new(),
text: text,
})))
}
}
impl Default for Document {
fn default() -> Self {
Self::new()
}
}
impl WriteBuffer for Document {
fn write_buf_opt(&self, opt: &WriteOptions, buf: &mut Vec<u8>) {
writer::write_dom(self, opt, buf);
}
}
impl_display!(Document);