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| Attribute::new(o.name.local_name, o.value))
215 .collect();
216 let ns = if let Some(ref prefix) = name.prefix {
217 namespace.get(prefix)
218 }
219 else {
220 namespace.get(NS_NO_PREFIX)
221 }.map(|s| s.to_owned());
222 let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
223 root.from_reader_inner(reader)?;
224 return Ok(root);
225 },
226 ReaderEvent::EndDocument => {
227 return Err(Error::EndOfDocument);
228 },
229 _ => () // TODO: may need more errors
230 }
231 }
232 }
233
234 fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
235 loop {
236 let e = reader.next()?;
237 match e {
238 ReaderEvent::StartElement { name, attributes, namespace } => {
239 let attributes = attributes.into_iter()
240 .map(|o| Attribute::new(o.name.local_name, o.value))
241 .collect();
242 let ns = if let Some(ref prefix) = name.prefix {
243 namespace.get(prefix)
244 }
245 else {
246 namespace.get(NS_NO_PREFIX)
247 }.map(|s| s.to_owned());
248 let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
249 let elem_ref = self.append_child(elem);
250 elem_ref.from_reader_inner(reader)?;
251 },
252 ReaderEvent::EndElement { .. } => {
253 // TODO: may want to check whether we're closing the correct element
254 return Ok(());
255 },
256 ReaderEvent::Characters(s) => {
257 self.append_text_node(s);
258 },
259 ReaderEvent::CData(s) => {
260 self.append_text_node(s);
261 },
262 ReaderEvent::EndDocument => {
263 return Err(Error::EndOfDocument);
264 },
265 _ => (), // TODO: may need to implement more
266 }
267 }
268 }
269
270 /// Output a document to an `EventWriter`.
271 pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
272 let name = if let Some(ref ns) = self.namespace {
273 Name::qualified(&self.name, &ns, None)
274 }
275 else {
276 Name::local(&self.name)
277 };
278 let mut start = WriterEvent::start_element(name);
279 if let Some(ref ns) = self.namespace {
280 start = start.default_ns(ns.as_ref());
281 }
282 for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
283 start = start.attr(Name::local(&attr.name), &attr.value);
284 }
285 writer.write(start)?;
286 for child in &self.children {
287 match *child {
288 Node::Element(ref e) => {
289 e.write_to(writer)?;
290 },
291 Node::Text(ref s) => {
292 writer.write(WriterEvent::characters(s))?;
293 },
294 }
295 }
296 writer.write(WriterEvent::end_element())?;
297 Ok(())
298 }
299
300 /// Returns an iterator over references to the children of this element.
301 ///
302 /// # Examples
303 ///
304 /// ```
305 /// use minidom::Element;
306 ///
307 /// let elem: Element = "<root><child1 /><child2 /><child3 /></root>".parse().unwrap();
308 ///
309 /// let mut iter = elem.children();
310 /// assert_eq!(iter.next().unwrap().name(), "child1");
311 /// assert_eq!(iter.next().unwrap().name(), "child2");
312 /// assert_eq!(iter.next().unwrap().name(), "child3");
313 /// assert_eq!(iter.next(), None);
314 /// ```
315 pub fn children<'a>(&'a self) -> Children<'a> {
316 Children {
317 iter: self.children.iter(),
318 }
319 }
320
321 /// Returns an iterator over mutable references to the children of this element.
322 pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
323 ChildrenMut {
324 iter: self.children.iter_mut(),
325 }
326 }
327
328 fn propagate_namespaces(&mut self) {
329 let ns = self.namespace.clone();
330 for child in self.children_mut() {
331 if child.namespace.is_none() {
332 child.namespace = ns.clone();
333 child.propagate_namespaces();
334 }
335 }
336 }
337
338 /// Appends a child node to the `Element`, returning the appended node.
339 ///
340 /// # Examples
341 ///
342 /// ```
343 /// use minidom::Element;
344 ///
345 /// let mut elem = Element::bare("root");
346 ///
347 /// assert_eq!(elem.children().count(), 0);
348 ///
349 /// elem.append_child(Element::bare("child"));
350 ///
351 /// {
352 /// let mut iter = elem.children();
353 /// assert_eq!(iter.next().unwrap().name(), "child");
354 /// assert_eq!(iter.next(), None);
355 /// }
356 ///
357 /// let child = elem.append_child(Element::bare("new"));
358 ///
359 /// assert_eq!(child.name(), "new");
360 /// ```
361 pub fn append_child(&mut self, mut child: Element) -> &mut Element {
362 if child.namespace.is_none() && self.namespace.is_some() {
363 child.namespace = self.namespace.clone();
364 child.propagate_namespaces();
365 }
366 self.children.push(Node::Element(child));
367 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
368 cld
369 }
370 else {
371 unreachable!()
372 }
373 }
374
375 /// Appends a text node to an `Element`.
376 ///
377 /// # Examples
378 ///
379 /// ```
380 /// use minidom::Element;
381 ///
382 /// let mut elem = Element::bare("node");
383 ///
384 /// assert_eq!(elem.text(), "");
385 ///
386 /// elem.append_text_node("text");
387 ///
388 /// assert_eq!(elem.text(), "text");
389 /// ```
390 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
391 self.children.push(Node::Text(child.into()));
392 }
393
394 /// Appends a node to an `Element`.
395 ///
396 /// # Examples
397 ///
398 /// ```
399 /// use minidom::{Element, Node};
400 ///
401 /// let mut elem = Element::bare("node");
402 ///
403 /// elem.append_node(Node::Text("hello".to_owned()));
404 ///
405 /// assert_eq!(elem.text(), "hello");
406 /// ```
407 pub fn append_node(&mut self, node: Node) {
408 self.children.push(node);
409 }
410
411 /// Returns the concatenation of all text nodes in the `Element`.
412 ///
413 /// # Examples
414 ///
415 /// ```
416 /// use minidom::Element;
417 ///
418 /// let elem: Element = "<node>hello, world!</node>".parse().unwrap();
419 ///
420 /// assert_eq!(elem.text(), "hello, world!");
421 /// ```
422 pub fn text(&self) -> String {
423 let mut ret = String::new();
424 for fork in &self.children {
425 if let Node::Text(ref s) = *fork {
426 ret += s;
427 }
428 }
429 ret
430 }
431
432 /// Returns a reference to the first child element with the specific name and namespace, if it
433 /// exists in the direct descendants of this `Element`, else returns `None`.
434 ///
435 /// # Examples
436 ///
437 /// ```
438 /// use minidom::Element;
439 ///
440 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
441 ///
442 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
443 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
444 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
445 /// assert_eq!(elem.get_child("c", "ns"), None);
446 /// assert_eq!(elem.get_child("b", "other_ns"), None);
447 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
448 /// ```
449 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
450 for fork in &self.children {
451 if let Node::Element(ref e) = *fork {
452 if e.is(name.as_ref(), namespace.as_ref()) {
453 return Some(e);
454 }
455 }
456 }
457 None
458 }
459
460 /// Returns a mutable reference to the first child element with the specific name and namespace,
461 /// if it exists in the direct descendants of this `Element`, else returns `None`.
462 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
463 for fork in &mut self.children {
464 if let Node::Element(ref mut e) = *fork {
465 if e.is(name.as_ref(), namespace.as_ref()) {
466 return Some(e);
467 }
468 }
469 }
470 None
471 }
472
473 /// Returns whether a specific child with this name and namespace exists in the direct
474 /// descendants of the `Element`.
475 ///
476 /// # Examples
477 ///
478 /// ```
479 /// use minidom::Element;
480 ///
481 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
482 ///
483 /// assert_eq!(elem.has_child("a", "other_ns"), true);
484 /// assert_eq!(elem.has_child("a", "ns"), true);
485 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
486 /// assert_eq!(elem.has_child("b", "ns"), true);
487 /// assert_eq!(elem.has_child("b", "other_ns"), false);
488 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
489 /// ```
490 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
491 self.get_child(name, namespace).is_some()
492 }
493}
494
495/// An iterator over references to children of an `Element`.
496pub struct Children<'a> {
497 iter: slice::Iter<'a, Node>,
498}
499
500impl<'a> Iterator for Children<'a> {
501 type Item = &'a Element;
502
503 fn next(&mut self) -> Option<&'a Element> {
504 while let Some(item) = self.iter.next() {
505 if let Node::Element(ref child) = *item {
506 return Some(child);
507 }
508 }
509 None
510 }
511}
512
513/// An iterator over mutable references to children of an `Element`.
514pub struct ChildrenMut<'a> {
515 iter: slice::IterMut<'a, Node>,
516}
517
518impl<'a> Iterator for ChildrenMut<'a> {
519 type Item = &'a mut Element;
520
521 fn next(&mut self) -> Option<&'a mut Element> {
522 while let Some(item) = self.iter.next() {
523 if let Node::Element(ref mut child) = *item {
524 return Some(child);
525 }
526 }
527 None
528 }
529}
530
531/// A builder for `Element`s.
532pub struct ElementBuilder {
533 root: Element,
534}
535
536impl ElementBuilder {
537 /// Sets the namespace.
538 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
539 self.root.namespace = Some(namespace.into());
540 self
541 }
542
543 /// Sets an attribute.
544 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
545 self.root.set_attr(name, value);
546 self
547 }
548
549 /// Appends anything implementing `IntoElements` into the tree.
550 pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
551 {
552 let mut emitter = ElementEmitter::new(&mut self.root);
553 into.into_elements(&mut emitter);
554 }
555 self
556 }
557
558 /// Builds the `Element`.
559 pub fn build(self) -> Element {
560 self.root
561 }
562}
563
564#[test]
565fn test_element_new() {
566 let elem = Element::new( "name".to_owned()
567 , Some("namespace".to_owned())
568 , vec![ Attribute::new("name", "value") ]
569 , Vec::new() );
570
571 assert_eq!(elem.name(), "name");
572 assert_eq!(elem.ns(), Some("namespace"));
573 assert_eq!(elem.attr("name"), Some("value"));
574 assert_eq!(elem.attr("inexistent"), None);
575}