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