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