1//! Provides an `Element` type, which represents DOM nodes, and a builder to create them with.
2
3use std::io::prelude::*;
4use std::io::Cursor;
5use std::collections::BTreeMap;
6use std::iter::FromIterator;
7
8use std::fmt;
9
10use error::Error;
11
12use xml::reader::{XmlEvent as ReaderEvent, EventReader};
13use xml::writer::{XmlEvent as WriterEvent, EventWriter, EmitterConfig};
14use xml::name::Name;
15use xml::namespace::NS_NO_PREFIX;
16
17use std::str::FromStr;
18
19use std::slice;
20
21use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
22
23#[derive(Clone, PartialEq, Eq)]
24/// A struct representing a DOM Element.
25pub struct Element {
26 name: String,
27 namespace: Option<String>,
28 attributes: BTreeMap<String, String>,
29 children: Vec<Node>,
30}
31
32
33impl<'a> From<&'a Element> for String {
34 fn from(elem: &'a Element) -> String {
35 let mut out = Vec::new();
36 let config = EmitterConfig::new()
37 .write_document_declaration(false);
38 elem.write_to(&mut EventWriter::new_with_config(&mut out, config)).unwrap();
39 String::from_utf8(out).unwrap()
40 }
41}
42
43impl fmt::Debug for Element {
44 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
45 write!(fmt, "{}", String::from(self))?;
46 Ok(())
47 }
48}
49
50impl FromStr for Element {
51 type Err = Error;
52
53 fn from_str(s: &str) -> Result<Element, Error> {
54 let mut reader = EventReader::new(Cursor::new(s));
55 Element::from_reader(&mut reader)
56 }
57}
58
59/// A node in an element tree.
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub enum Node {
62 /// An `Element`.
63 Element(Element),
64 /// A text node.
65 Text(String),
66}
67
68impl Element {
69 fn new(name: String, namespace: Option<String>, attributes: BTreeMap<String, String>, children: Vec<Node>) -> Element {
70 Element {
71 name: name,
72 namespace: namespace,
73 attributes: attributes,
74 children: children,
75 }
76 }
77
78 /// Return a builder for an `Element` with the given `name`.
79 ///
80 /// # Examples
81 ///
82 /// ```
83 /// use minidom::Element;
84 ///
85 /// let elem = Element::builder("name")
86 /// .ns("namespace")
87 /// .attr("name", "value")
88 /// .append("inner")
89 /// .build();
90 ///
91 /// assert_eq!(elem.name(), "name");
92 /// assert_eq!(elem.ns(), Some("namespace"));
93 /// assert_eq!(elem.attr("name"), Some("value"));
94 /// assert_eq!(elem.attr("inexistent"), None);
95 /// assert_eq!(elem.text(), "inner");
96 /// ```
97 pub fn builder<S: Into<String>>(name: S) -> ElementBuilder {
98 ElementBuilder {
99 root: Element::new(name.into(), None, BTreeMap::new(), Vec::new()),
100 }
101 }
102
103 /// Returns a bare minimum `Element` with this name.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use minidom::Element;
109 ///
110 /// let bare = Element::bare("name");
111 ///
112 /// assert_eq!(bare.name(), "name");
113 /// assert_eq!(bare.ns(), None);
114 /// assert_eq!(bare.attr("name"), None);
115 /// assert_eq!(bare.text(), "");
116 /// ```
117 pub fn bare<S: Into<String>>(name: S) -> Element {
118 Element {
119 name: name.into(),
120 namespace: None,
121 attributes: BTreeMap::new(),
122 children: Vec::new(),
123 }
124 }
125
126 /// Returns a reference to the name of this element.
127 pub fn name(&self) -> &str {
128 &self.name
129 }
130
131 /// Returns a reference to the namespace of this element, if it has one, else `None`.
132 pub fn ns(&self) -> Option<&str> {
133 self.namespace.as_ref()
134 .map(String::as_ref)
135 }
136
137 /// Returns a reference to the value of the given attribute, if it exists, else `None`.
138 pub fn attr(&self, name: &str) -> Option<&str> {
139 if let Some(value) = self.attributes.get(name) {
140 return Some(&value)
141 }
142 None
143 }
144
145 /// Modifies the value of an attribute.
146 pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
147 let name = name.into();
148 let val = val.into_attribute_value();
149
150 if let Some(value) = self.attributes.get_mut(&name) {
151 *value = val.expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
152 return;
153 }
154
155 if let Some(val) = val {
156 self.attributes.insert(name, val);
157 }
158 }
159
160 /// Returns whether the element has the given name and namespace.
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use minidom::Element;
166 ///
167 /// let elem = Element::builder("name").ns("namespace").build();
168 ///
169 /// assert_eq!(elem.is("name", "namespace"), true);
170 /// assert_eq!(elem.is("name", "wrong"), false);
171 /// assert_eq!(elem.is("wrong", "namespace"), false);
172 /// assert_eq!(elem.is("wrong", "wrong"), false);
173 /// ```
174 pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
175 let ns = self.namespace.as_ref().map(String::as_ref);
176 self.name == name.as_ref() && ns == Some(namespace.as_ref())
177 }
178
179 /// Parse a document from an `EventReader`.
180 pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element, Error> {
181 loop {
182 let e = reader.next()?;
183 match e {
184 ReaderEvent::StartElement { name, attributes, namespace } => {
185 let attributes = attributes.into_iter()
186 .map(|o| {
187 (match o.name.prefix {
188 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
189 None => o.name.local_name
190 },
191 o.value)
192 })
193 .collect();
194 let ns = if let Some(ref prefix) = name.prefix {
195 namespace.get(prefix)
196 }
197 else {
198 namespace.get(NS_NO_PREFIX)
199 }.map(|s| s.to_owned());
200
201 let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
202 root.from_reader_inner(reader)?;
203 return Ok(root);
204 },
205 ReaderEvent::EndDocument => {
206 return Err(Error::EndOfDocument);
207 },
208 _ => () // TODO: may need more errors
209 }
210 }
211 }
212
213 fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
214 loop {
215 let e = reader.next()?;
216 match e {
217 ReaderEvent::StartElement { name, attributes, namespace } => {
218 let attributes = attributes.into_iter()
219 .map(|o| {
220 (match o.name.prefix {
221 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
222 None => o.name.local_name
223 },
224 o.value)
225 })
226 .collect();
227 let ns = if let Some(ref prefix) = name.prefix {
228 namespace.get(prefix)
229 }
230 else {
231 namespace.get(NS_NO_PREFIX)
232 }.map(|s| s.to_owned());
233 let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
234 let elem_ref = self.append_child(elem);
235 elem_ref.from_reader_inner(reader)?;
236 },
237 ReaderEvent::EndElement { .. } => {
238 // TODO: may want to check whether we're closing the correct element
239 return Ok(());
240 },
241 ReaderEvent::Characters(s) => {
242 self.append_text_node(s);
243 },
244 ReaderEvent::CData(s) => {
245 self.append_text_node(s);
246 },
247 ReaderEvent::EndDocument => {
248 return Err(Error::EndOfDocument);
249 },
250 _ => (), // TODO: may need to implement more
251 }
252 }
253 }
254
255 /// Output a document to an `EventWriter`.
256 pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
257 let name = if let Some(ref ns) = self.namespace {
258 Name::qualified(&self.name, &ns, None)
259 }
260 else {
261 Name::local(&self.name)
262 };
263 let mut start = WriterEvent::start_element(name);
264 if let Some(ref ns) = self.namespace {
265 start = start.default_ns(ns.clone());
266 }
267 for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
268 start = start.attr(Name::local(&attr.0), &attr.1);
269 }
270 writer.write(start)?;
271 for child in &self.children {
272 match *child {
273 Node::Element(ref e) => {
274 e.write_to(writer)?;
275 },
276 Node::Text(ref s) => {
277 writer.write(WriterEvent::characters(s))?;
278 },
279 }
280 }
281 writer.write(WriterEvent::end_element())?;
282 Ok(())
283 }
284
285 /// Returns an iterator over references to the children of this element.
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use minidom::Element;
291 ///
292 /// let elem: Element = "<root><child1 /><child2 /><child3 /></root>".parse().unwrap();
293 ///
294 /// let mut iter = elem.children();
295 /// assert_eq!(iter.next().unwrap().name(), "child1");
296 /// assert_eq!(iter.next().unwrap().name(), "child2");
297 /// assert_eq!(iter.next().unwrap().name(), "child3");
298 /// assert_eq!(iter.next(), None);
299 /// ```
300 pub fn children<'a>(&'a self) -> Children<'a> {
301 Children {
302 iter: self.children.iter(),
303 }
304 }
305
306 /// Returns an iterator over mutable references to the children of this element.
307 pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
308 ChildrenMut {
309 iter: self.children.iter_mut(),
310 }
311 }
312
313 fn propagate_namespaces(&mut self) {
314 let ns = self.namespace.clone();
315 for child in self.children_mut() {
316 if child.namespace.is_none() {
317 child.namespace = ns.clone();
318 child.propagate_namespaces();
319 }
320 }
321 }
322
323 /// Appends a child node to the `Element`, returning the appended node.
324 ///
325 /// # Examples
326 ///
327 /// ```
328 /// use minidom::Element;
329 ///
330 /// let mut elem = Element::bare("root");
331 ///
332 /// assert_eq!(elem.children().count(), 0);
333 ///
334 /// elem.append_child(Element::bare("child"));
335 ///
336 /// {
337 /// let mut iter = elem.children();
338 /// assert_eq!(iter.next().unwrap().name(), "child");
339 /// assert_eq!(iter.next(), None);
340 /// }
341 ///
342 /// let child = elem.append_child(Element::bare("new"));
343 ///
344 /// assert_eq!(child.name(), "new");
345 /// ```
346 pub fn append_child(&mut self, mut child: Element) -> &mut Element {
347 if child.namespace.is_none() && self.namespace.is_some() {
348 child.namespace = self.namespace.clone();
349 child.propagate_namespaces();
350 }
351 self.children.push(Node::Element(child));
352 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
353 cld
354 }
355 else {
356 unreachable!()
357 }
358 }
359
360 /// Appends a text node to an `Element`.
361 ///
362 /// # Examples
363 ///
364 /// ```
365 /// use minidom::Element;
366 ///
367 /// let mut elem = Element::bare("node");
368 ///
369 /// assert_eq!(elem.text(), "");
370 ///
371 /// elem.append_text_node("text");
372 ///
373 /// assert_eq!(elem.text(), "text");
374 /// ```
375 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
376 self.children.push(Node::Text(child.into()));
377 }
378
379 /// Appends a node to an `Element`.
380 ///
381 /// # Examples
382 ///
383 /// ```
384 /// use minidom::{Element, Node};
385 ///
386 /// let mut elem = Element::bare("node");
387 ///
388 /// elem.append_node(Node::Text("hello".to_owned()));
389 ///
390 /// assert_eq!(elem.text(), "hello");
391 /// ```
392 pub fn append_node(&mut self, node: Node) {
393 self.children.push(node);
394 }
395
396 /// Returns the concatenation of all text nodes in the `Element`.
397 ///
398 /// # Examples
399 ///
400 /// ```
401 /// use minidom::Element;
402 ///
403 /// let elem: Element = "<node>hello, world!</node>".parse().unwrap();
404 ///
405 /// assert_eq!(elem.text(), "hello, world!");
406 /// ```
407 pub fn text(&self) -> String {
408 let mut ret = String::new();
409 for fork in &self.children {
410 if let Node::Text(ref s) = *fork {
411 ret += s;
412 }
413 }
414 ret
415 }
416
417 /// Returns a reference to the first child element with the specific name and namespace, if it
418 /// exists in the direct descendants of this `Element`, else returns `None`.
419 ///
420 /// # Examples
421 ///
422 /// ```
423 /// use minidom::Element;
424 ///
425 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
426 ///
427 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
428 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
429 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
430 /// assert_eq!(elem.get_child("c", "ns"), None);
431 /// assert_eq!(elem.get_child("b", "other_ns"), None);
432 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
433 /// ```
434 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
435 for fork in &self.children {
436 if let Node::Element(ref e) = *fork {
437 if e.is(name.as_ref(), namespace.as_ref()) {
438 return Some(e);
439 }
440 }
441 }
442 None
443 }
444
445 /// Returns a mutable reference to the first child element with the specific name and namespace,
446 /// if it exists in the direct descendants of this `Element`, else returns `None`.
447 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
448 for fork in &mut self.children {
449 if let Node::Element(ref mut e) = *fork {
450 if e.is(name.as_ref(), namespace.as_ref()) {
451 return Some(e);
452 }
453 }
454 }
455 None
456 }
457
458 /// Returns whether a specific child with this name and namespace exists in the direct
459 /// descendants of the `Element`.
460 ///
461 /// # Examples
462 ///
463 /// ```
464 /// use minidom::Element;
465 ///
466 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
467 ///
468 /// assert_eq!(elem.has_child("a", "other_ns"), true);
469 /// assert_eq!(elem.has_child("a", "ns"), true);
470 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
471 /// assert_eq!(elem.has_child("b", "ns"), true);
472 /// assert_eq!(elem.has_child("b", "other_ns"), false);
473 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
474 /// ```
475 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
476 self.get_child(name, namespace).is_some()
477 }
478}
479
480/// An iterator over references to children of an `Element`.
481pub struct Children<'a> {
482 iter: slice::Iter<'a, Node>,
483}
484
485impl<'a> Iterator for Children<'a> {
486 type Item = &'a Element;
487
488 fn next(&mut self) -> Option<&'a Element> {
489 while let Some(item) = self.iter.next() {
490 if let Node::Element(ref child) = *item {
491 return Some(child);
492 }
493 }
494 None
495 }
496}
497
498/// An iterator over mutable references to children of an `Element`.
499pub struct ChildrenMut<'a> {
500 iter: slice::IterMut<'a, Node>,
501}
502
503impl<'a> Iterator for ChildrenMut<'a> {
504 type Item = &'a mut Element;
505
506 fn next(&mut self) -> Option<&'a mut Element> {
507 while let Some(item) = self.iter.next() {
508 if let Node::Element(ref mut child) = *item {
509 return Some(child);
510 }
511 }
512 None
513 }
514}
515
516/// A builder for `Element`s.
517pub struct ElementBuilder {
518 root: Element,
519}
520
521impl ElementBuilder {
522 /// Sets the namespace.
523 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
524 self.root.namespace = Some(namespace.into());
525 self
526 }
527
528 /// Sets an attribute.
529 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
530 self.root.set_attr(name, value);
531 self
532 }
533
534 /// Appends anything implementing `IntoElements` into the tree.
535 pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
536 {
537 let mut emitter = ElementEmitter::new(&mut self.root);
538 into.into_elements(&mut emitter);
539 }
540 self
541 }
542
543 /// Builds the `Element`.
544 pub fn build(self) -> Element {
545 self.root
546 }
547}
548
549#[test]
550fn test_element_new() {
551 let elem = Element::new( "name".to_owned()
552 , Some("namespace".to_owned())
553 , BTreeMap::from_iter(vec![ ("name".to_string(), "value".to_string()) ].into_iter() )
554 , Vec::new() );
555
556 assert_eq!(elem.name(), "name");
557 assert_eq!(elem.ns(), Some("namespace"));
558 assert_eq!(elem.attr("name"), Some("value"));
559 assert_eq!(elem.attr("inexistent"), None);
560}