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