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