1// Copyright (c) 2020 lumi <lumi@pew.im>
2// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
3// Copyright (c) 2020 Bastien Orivel <eijebong+minidom@bananium.fr>
4// Copyright (c) 2020 Maxime “pep” Buquet <pep@bouah.net>
5// Copyright (c) 2020 Yue Liu <amznyue@amazon.com>
6// Copyright (c) 2020 Matt Bilker <me@mbilker.us>
7// Copyright (c) 2020 Xidorn Quan <me@upsuper.org>
8//
9// This Source Code Form is subject to the terms of the Mozilla Public
10// License, v. 2.0. If a copy of the MPL was not distributed with this
11// file, You can obtain one at http://mozilla.org/MPL/2.0/.
12
13//! Provides an `Element` type, which represents DOM nodes, and a builder to create them with.
14
15use crate::convert::IntoAttributeValue;
16use crate::error::{Error, Result};
17use crate::namespaces::NSChoice;
18use crate::node::Node;
19use crate::prefixes::{Namespace, Prefix, Prefixes};
20use crate::tree_builder::TreeBuilder;
21
22use std::collections::{btree_map, BTreeMap};
23use std::convert::{TryFrom, TryInto};
24use std::io::{BufRead, Write};
25use std::sync::Arc;
26
27use std::borrow::Cow;
28use std::str;
29
30use rxml::writer::{Encoder, Item, TrackNamespace};
31use rxml::{EventRead, Lexer, PullDriver, RawParser, XmlVersion};
32
33use std::str::FromStr;
34
35use std::slice;
36
37fn encode_and_write<W: Write, T: rxml::writer::TrackNamespace>(
38 item: Item<'_>,
39 enc: &mut Encoder<T>,
40 mut w: W,
41) -> rxml::Result<()> {
42 let mut buf = rxml::bytes::BytesMut::new();
43 enc.encode_into_bytes(item, &mut buf)
44 .expect("encoder driven incorrectly");
45 w.write_all(&buf[..])?;
46 Ok(())
47}
48
49/// Wrapper around a [`std::io::Write`] and an [`rxml::writer::Encoder`], to
50/// provide a simple function to write an rxml Item to a writer.
51pub struct CustomItemWriter<W, T> {
52 writer: W,
53 encoder: Encoder<T>,
54}
55
56impl<W: Write> CustomItemWriter<W, rxml::writer::SimpleNamespaces> {
57 pub(crate) fn new(writer: W) -> Self {
58 Self {
59 writer,
60 encoder: Encoder::new(),
61 }
62 }
63}
64
65impl<W: Write, T: rxml::writer::TrackNamespace> CustomItemWriter<W, T> {
66 pub(crate) fn write(&mut self, item: Item<'_>) -> rxml::Result<()> {
67 encode_and_write(item, &mut self.encoder, &mut self.writer)
68 }
69}
70
71/// Type alias to simplify the use for the default namespace tracking
72/// implementation.
73pub type ItemWriter<W> = CustomItemWriter<W, rxml::writer::SimpleNamespaces>;
74
75/// helper function to escape a `&[u8]` and replace all
76/// xml special characters (<, >, &, ', ") with their corresponding
77/// xml escaped value.
78pub fn escape(raw: &[u8]) -> Cow<[u8]> {
79 let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
80 let mut bytes = raw.iter();
81 fn to_escape(b: u8) -> bool {
82 matches!(b, b'<' | b'>' | b'\'' | b'&' | b'"')
83 }
84
85 let mut loc = 0;
86 while let Some(i) = bytes.position(|&b| to_escape(b)) {
87 loc += i;
88 match raw[loc] {
89 b'<' => escapes.push((loc, b"<")),
90 b'>' => escapes.push((loc, b">")),
91 b'\'' => escapes.push((loc, b"'")),
92 b'&' => escapes.push((loc, b"&")),
93 b'"' => escapes.push((loc, b""")),
94 _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
95 }
96 loc += 1;
97 }
98
99 if escapes.is_empty() {
100 Cow::Borrowed(raw)
101 } else {
102 let len = raw.len();
103 let mut v = Vec::with_capacity(len);
104 let mut start = 0;
105 for (i, r) in escapes {
106 v.extend_from_slice(&raw[start..i]);
107 v.extend_from_slice(r);
108 start = i + 1;
109 }
110
111 if start < len {
112 v.extend_from_slice(&raw[start..]);
113 }
114 Cow::Owned(v)
115 }
116}
117
118#[derive(Clone, Eq, Debug)]
119/// A struct representing a DOM Element.
120pub struct Element {
121 name: String,
122 namespace: String,
123 /// Namespace declarations
124 pub prefixes: Prefixes,
125 attributes: BTreeMap<String, String>,
126 children: Vec<Node>,
127}
128
129impl<'a> From<&'a Element> for String {
130 fn from(elem: &'a Element) -> String {
131 let mut writer = Vec::new();
132 elem.write_to(&mut writer).unwrap();
133 String::from_utf8(writer).unwrap()
134 }
135}
136
137impl FromStr for Element {
138 type Err = Error;
139
140 fn from_str(s: &str) -> Result<Element> {
141 Element::from_reader(s.as_bytes())
142 }
143}
144
145impl PartialEq for Element {
146 fn eq(&self, other: &Self) -> bool {
147 if self.name() == other.name() && self.ns() == other.ns() && self.attrs().eq(other.attrs())
148 {
149 self.nodes()
150 .zip(other.nodes())
151 .all(|(node1, node2)| node1 == node2)
152 } else {
153 false
154 }
155 }
156}
157
158impl Element {
159 pub(crate) fn new<P: Into<Prefixes>>(
160 name: String,
161 namespace: String,
162 prefixes: P,
163 attributes: BTreeMap<String, String>,
164 children: Vec<Node>,
165 ) -> Element {
166 Element {
167 name,
168 namespace,
169 prefixes: prefixes.into(),
170 attributes,
171 children,
172 }
173 }
174
175 /// Return a builder for an `Element` with the given `name`.
176 ///
177 /// # Examples
178 ///
179 /// ```rust
180 /// use minidom::Element;
181 ///
182 /// let elem = Element::builder("name", "namespace")
183 /// .attr("name", "value")
184 /// .append("inner")
185 /// .build();
186 ///
187 /// assert_eq!(elem.name(), "name");
188 /// assert_eq!(elem.ns(), "namespace".to_owned());
189 /// assert_eq!(elem.attr("name"), Some("value"));
190 /// assert_eq!(elem.attr("inexistent"), None);
191 /// assert_eq!(elem.text(), "inner");
192 /// ```
193 pub fn builder<S: AsRef<str>, NS: Into<String>>(name: S, namespace: NS) -> ElementBuilder {
194 ElementBuilder {
195 root: Element::new(
196 name.as_ref().to_string(),
197 namespace.into(),
198 None,
199 BTreeMap::new(),
200 Vec::new(),
201 ),
202 }
203 }
204
205 /// Returns a bare minimum `Element` with this name.
206 ///
207 /// # Examples
208 ///
209 /// ```rust
210 /// use minidom::Element;
211 ///
212 /// let bare = Element::bare("name", "namespace");
213 ///
214 /// assert_eq!(bare.name(), "name");
215 /// assert_eq!(bare.ns(), "namespace");
216 /// assert_eq!(bare.attr("name"), None);
217 /// assert_eq!(bare.text(), "");
218 /// ```
219 pub fn bare<S: Into<String>, NS: Into<String>>(name: S, namespace: NS) -> Element {
220 Element::new(
221 name.into(),
222 namespace.into(),
223 None,
224 BTreeMap::new(),
225 Vec::new(),
226 )
227 }
228
229 /// Returns a reference to the local name of this element (that is, without a possible prefix).
230 pub fn name(&self) -> &str {
231 &self.name
232 }
233
234 /// Returns a reference to the namespace of this element.
235 pub fn ns(&self) -> String {
236 self.namespace.clone()
237 }
238
239 /// Returns a reference to the value of the given attribute, if it exists, else `None`.
240 pub fn attr(&self, name: &str) -> Option<&str> {
241 if let Some(value) = self.attributes.get(name) {
242 return Some(value);
243 }
244 None
245 }
246
247 /// Returns an iterator over the attributes of this element.
248 ///
249 /// # Example
250 ///
251 /// ```rust
252 /// use minidom::Element;
253 ///
254 /// let elm: Element = "<elem xmlns=\"ns1\" a=\"b\" />".parse().unwrap();
255 ///
256 /// let mut iter = elm.attrs();
257 ///
258 /// assert_eq!(iter.next().unwrap(), ("a", "b"));
259 /// assert_eq!(iter.next(), None);
260 /// ```
261 pub fn attrs(&self) -> Attrs {
262 Attrs {
263 iter: self.attributes.iter(),
264 }
265 }
266
267 /// Returns an iterator over the attributes of this element, with the value being a mutable
268 /// reference.
269 pub fn attrs_mut(&mut self) -> AttrsMut {
270 AttrsMut {
271 iter: self.attributes.iter_mut(),
272 }
273 }
274
275 /// Modifies the value of an attribute.
276 pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
277 let name = name.into();
278 let val = val.into_attribute_value();
279
280 if let Some(value) = self.attributes.get_mut(&name) {
281 *value = val
282 .expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
283 return;
284 }
285
286 if let Some(val) = val {
287 self.attributes.insert(name, val);
288 }
289 }
290
291 /// Returns whether the element has the given name and namespace.
292 ///
293 /// # Examples
294 ///
295 /// ```rust
296 /// use minidom::{Element, NSChoice};
297 ///
298 /// let elem = Element::builder("name", "namespace").build();
299 ///
300 /// assert_eq!(elem.is("name", "namespace"), true);
301 /// assert_eq!(elem.is("name", "wrong"), false);
302 /// assert_eq!(elem.is("wrong", "namespace"), false);
303 /// assert_eq!(elem.is("wrong", "wrong"), false);
304 ///
305 /// assert_eq!(elem.is("name", NSChoice::OneOf("namespace")), true);
306 /// assert_eq!(elem.is("name", NSChoice::OneOf("foo")), false);
307 /// assert_eq!(elem.is("name", NSChoice::AnyOf(&["foo", "namespace"])), true);
308 /// assert_eq!(elem.is("name", NSChoice::Any), true);
309 /// ```
310 pub fn is<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(&self, name: N, namespace: NS) -> bool {
311 self.name == name.as_ref() && namespace.into().compare(self.namespace.as_ref())
312 }
313
314 /// Returns whether the element has the given namespace.
315 ///
316 /// # Examples
317 ///
318 /// ```rust
319 /// use minidom::{Element, NSChoice};
320 ///
321 /// let elem = Element::builder("name", "namespace").build();
322 ///
323 /// assert_eq!(elem.has_ns("namespace"), true);
324 /// assert_eq!(elem.has_ns("wrong"), false);
325 ///
326 /// assert_eq!(elem.has_ns(NSChoice::OneOf("namespace")), true);
327 /// assert_eq!(elem.has_ns(NSChoice::OneOf("foo")), false);
328 /// assert_eq!(elem.has_ns(NSChoice::AnyOf(&["foo", "namespace"])), true);
329 /// assert_eq!(elem.has_ns(NSChoice::Any), true);
330 /// ```
331 pub fn has_ns<'a, NS: Into<NSChoice<'a>>>(&self, namespace: NS) -> bool {
332 namespace.into().compare(self.namespace.as_ref())
333 }
334
335 /// Parse a document from a `BufRead`.
336 pub fn from_reader<R: BufRead>(reader: R) -> Result<Element> {
337 let mut tree_builder = TreeBuilder::new();
338 let mut driver = PullDriver::wrap(reader, Lexer::new(), RawParser::new());
339 while let Some(event) = driver.read()? {
340 tree_builder.process_event(event)?;
341
342 if let Some(root) = tree_builder.root.take() {
343 return Ok(root);
344 }
345 }
346 Err(Error::EndOfDocument)
347 }
348
349 /// Output a document to a `Writer`.
350 pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
351 self.to_writer(&mut ItemWriter::new(writer))
352 }
353
354 /// Output a document to a `Writer`.
355 pub fn write_to_decl<W: Write>(&self, writer: &mut W) -> Result<()> {
356 self.to_writer_decl(&mut ItemWriter::new(writer))
357 }
358
359 /// Output the document to quick-xml `Writer`
360 pub fn to_writer<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
361 self.write_to_inner(writer)
362 }
363
364 /// Output the document to quick-xml `Writer`
365 pub fn to_writer_decl<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
366 writer
367 .write(Item::XmlDeclaration(XmlVersion::V1_0))
368 .unwrap(); // TODO: error return
369 self.write_to_inner(writer)
370 }
371
372 /// Like `write_to()` but without the `<?xml?>` prelude
373 pub fn write_to_inner<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
374 for (prefix, namespace) in self.prefixes.declared_prefixes() {
375 assert!(writer.encoder.inner_mut().declare_fixed(
376 prefix.as_ref().map(|x| (&**x).try_into()).transpose()?,
377 Some(Arc::new(namespace.clone().try_into()?))
378 ));
379 }
380
381 let namespace = if self.namespace.len() == 0 {
382 None
383 } else {
384 Some(Arc::new(self.namespace.clone().try_into()?))
385 };
386 writer.write(Item::ElementHeadStart(namespace, (*self.name).try_into()?))?;
387
388 for (key, value) in self.attributes.iter() {
389 let (prefix, name) = <&rxml::NameStr>::try_from(&**key)
390 .unwrap()
391 .split_name()
392 .unwrap();
393 let namespace = match prefix {
394 Some(prefix) => match writer.encoder.inner().lookup_prefix(Some(prefix)) {
395 Ok(v) => Some(v),
396 Err(rxml::writer::PrefixError::Undeclared) => return Err(Error::InvalidPrefix),
397 },
398 None => None,
399 };
400 writer.write(Item::Attribute(namespace, name, (&**value).try_into()?))?;
401 }
402
403 if !self.children.is_empty() {
404 writer.write(Item::ElementHeadEnd)?;
405 for child in self.children.iter() {
406 child.write_to_inner(writer)?;
407 }
408 }
409 writer.write(Item::ElementFoot)?;
410
411 Ok(())
412 }
413
414 /// Returns an iterator over references to every child node of this element.
415 ///
416 /// # Examples
417 ///
418 /// ```rust
419 /// use minidom::Element;
420 ///
421 /// let elem: Element = "<root xmlns=\"ns1\">a<c1 />b<c2 />c</root>".parse().unwrap();
422 ///
423 /// let mut iter = elem.nodes();
424 ///
425 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
426 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
427 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
428 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
429 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
430 /// assert_eq!(iter.next(), None);
431 /// ```
432 #[inline]
433 pub fn nodes(&self) -> Nodes {
434 self.children.iter()
435 }
436
437 /// Returns an iterator over mutable references to every child node of this element.
438 #[inline]
439 pub fn nodes_mut(&mut self) -> NodesMut {
440 self.children.iter_mut()
441 }
442
443 /// Returns an iterator over references to every child element of this element.
444 ///
445 /// # Examples
446 ///
447 /// ```rust
448 /// use minidom::Element;
449 ///
450 /// let elem: Element = "<root xmlns=\"ns1\">hello<child1 xmlns=\"ns1\"/>this<child2 xmlns=\"ns1\"/>is<child3 xmlns=\"ns1\"/>ignored</root>".parse().unwrap();
451 ///
452 /// let mut iter = elem.children();
453 /// assert_eq!(iter.next().unwrap().name(), "child1");
454 /// assert_eq!(iter.next().unwrap().name(), "child2");
455 /// assert_eq!(iter.next().unwrap().name(), "child3");
456 /// assert_eq!(iter.next(), None);
457 /// ```
458 #[inline]
459 pub fn children(&self) -> Children {
460 Children {
461 iter: self.children.iter(),
462 }
463 }
464
465 /// Returns an iterator over mutable references to every child element of this element.
466 #[inline]
467 pub fn children_mut(&mut self) -> ChildrenMut {
468 ChildrenMut {
469 iter: self.children.iter_mut(),
470 }
471 }
472
473 /// Returns an iterator over references to every text node of this element.
474 ///
475 /// # Examples
476 ///
477 /// ```rust
478 /// use minidom::Element;
479 ///
480 /// let elem: Element = "<root xmlns=\"ns1\">hello<c /> world!</root>".parse().unwrap();
481 ///
482 /// let mut iter = elem.texts();
483 /// assert_eq!(iter.next().unwrap(), "hello");
484 /// assert_eq!(iter.next().unwrap(), " world!");
485 /// assert_eq!(iter.next(), None);
486 /// ```
487 #[inline]
488 pub fn texts(&self) -> Texts {
489 Texts {
490 iter: self.children.iter(),
491 }
492 }
493
494 /// Returns an iterator over mutable references to every text node of this element.
495 #[inline]
496 pub fn texts_mut(&mut self) -> TextsMut {
497 TextsMut {
498 iter: self.children.iter_mut(),
499 }
500 }
501
502 /// Appends a child node to the `Element`, returning the appended node.
503 ///
504 /// # Examples
505 ///
506 /// ```rust
507 /// use minidom::Element;
508 ///
509 /// let mut elem = Element::bare("root", "ns1");
510 ///
511 /// assert_eq!(elem.children().count(), 0);
512 ///
513 /// elem.append_child(Element::bare("child", "ns1"));
514 ///
515 /// {
516 /// let mut iter = elem.children();
517 /// assert_eq!(iter.next().unwrap().name(), "child");
518 /// assert_eq!(iter.next(), None);
519 /// }
520 ///
521 /// let child = elem.append_child(Element::bare("new", "ns1"));
522 ///
523 /// assert_eq!(child.name(), "new");
524 /// ```
525 pub fn append_child(&mut self, child: Element) -> &mut Element {
526 self.children.push(Node::Element(child));
527 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
528 cld
529 } else {
530 unreachable!()
531 }
532 }
533
534 /// Appends a text node to an `Element`.
535 ///
536 /// # Examples
537 ///
538 /// ```rust
539 /// use minidom::Element;
540 ///
541 /// let mut elem = Element::bare("node", "ns1");
542 ///
543 /// assert_eq!(elem.text(), "");
544 ///
545 /// elem.append_text_node("text");
546 ///
547 /// assert_eq!(elem.text(), "text");
548 /// ```
549 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
550 self.children.push(Node::Text(child.into()));
551 }
552
553 /// Appends a node to an `Element`.
554 ///
555 /// # Examples
556 ///
557 /// ```rust
558 /// use minidom::{Element, Node};
559 ///
560 /// let mut elem = Element::bare("node", "ns1");
561 ///
562 /// elem.append_node(Node::Text("hello".to_owned()));
563 ///
564 /// assert_eq!(elem.text(), "hello");
565 /// ```
566 pub fn append_node(&mut self, node: Node) {
567 self.children.push(node);
568 }
569
570 /// Returns the concatenation of all text nodes in the `Element`.
571 ///
572 /// # Examples
573 ///
574 /// ```rust
575 /// use minidom::Element;
576 ///
577 /// let elem: Element = "<node xmlns=\"ns1\">hello,<split /> world!</node>".parse().unwrap();
578 ///
579 /// assert_eq!(elem.text(), "hello, world!");
580 /// ```
581 pub fn text(&self) -> String {
582 self.texts().fold(String::new(), |ret, new| ret + new)
583 }
584
585 /// Returns a reference to the first child element with the specific name and namespace, if it
586 /// exists in the direct descendants of this `Element`, else returns `None`.
587 ///
588 /// # Examples
589 ///
590 /// ```rust
591 /// use minidom::{Element, NSChoice};
592 ///
593 /// let elem: Element = r#"<node xmlns="ns"><a/><a xmlns="other_ns" /><b/></node>"#.parse().unwrap();
594 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
595 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
596 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
597 /// assert_eq!(elem.get_child("c", "ns"), None);
598 /// assert_eq!(elem.get_child("b", "other_ns"), None);
599 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
600 /// ```
601 pub fn get_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
602 &self,
603 name: N,
604 namespace: NS,
605 ) -> Option<&Element> {
606 let namespace = namespace.into();
607 for fork in &self.children {
608 if let Node::Element(ref e) = *fork {
609 if e.is(name.as_ref(), namespace) {
610 return Some(e);
611 }
612 }
613 }
614 None
615 }
616
617 /// Returns a mutable reference to the first child element with the specific name and namespace,
618 /// if it exists in the direct descendants of this `Element`, else returns `None`.
619 pub fn get_child_mut<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
620 &mut self,
621 name: N,
622 namespace: NS,
623 ) -> Option<&mut Element> {
624 let namespace = namespace.into();
625 for fork in &mut self.children {
626 if let Node::Element(ref mut e) = *fork {
627 if e.is(name.as_ref(), namespace) {
628 return Some(e);
629 }
630 }
631 }
632 None
633 }
634
635 /// Returns whether a specific child with this name and namespace exists in the direct
636 /// descendants of the `Element`.
637 ///
638 /// # Examples
639 ///
640 /// ```rust
641 /// use minidom::{Element, NSChoice};
642 ///
643 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
644 /// assert_eq!(elem.has_child("a", "other_ns"), true);
645 /// assert_eq!(elem.has_child("a", "ns"), true);
646 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
647 /// assert_eq!(elem.has_child("b", "ns"), true);
648 /// assert_eq!(elem.has_child("b", "other_ns"), false);
649 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
650 /// ```
651 pub fn has_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
652 &self,
653 name: N,
654 namespace: NS,
655 ) -> bool {
656 self.get_child(name, namespace).is_some()
657 }
658
659 /// Removes the first child with this name and namespace, if it exists, and returns an
660 /// `Option<Element>` containing this child if it succeeds.
661 /// Returns `None` if no child matches this name and namespace.
662 ///
663 /// # Examples
664 ///
665 /// ```rust
666 /// use minidom::{Element, NSChoice};
667 ///
668 /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
669 /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
670 /// assert!(elem.remove_child("a", "ns").is_none());
671 /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
672 /// ```
673 pub fn remove_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
674 &mut self,
675 name: N,
676 namespace: NS,
677 ) -> Option<Element> {
678 let name = name.as_ref();
679 let namespace = namespace.into();
680 let idx = self.children.iter().position(|x| {
681 if let Node::Element(ref elm) = x {
682 elm.is(name, namespace)
683 } else {
684 false
685 }
686 })?;
687 self.children.remove(idx).into_element()
688 }
689
690 /// Remove the leading nodes up to the first child element and
691 /// return it
692 pub fn unshift_child(&mut self) -> Option<Element> {
693 while self.children.len() > 0 {
694 if let Some(el) = self.children.remove(0).into_element() {
695 return Some(el);
696 }
697 }
698
699 None
700 }
701}
702
703/// An iterator over references to child elements of an `Element`.
704pub struct Children<'a> {
705 iter: slice::Iter<'a, Node>,
706}
707
708impl<'a> Iterator for Children<'a> {
709 type Item = &'a Element;
710
711 fn next(&mut self) -> Option<&'a Element> {
712 for item in &mut self.iter {
713 if let Node::Element(ref child) = *item {
714 return Some(child);
715 }
716 }
717 None
718 }
719}
720
721/// An iterator over mutable references to child elements of an `Element`.
722pub struct ChildrenMut<'a> {
723 iter: slice::IterMut<'a, Node>,
724}
725
726impl<'a> Iterator for ChildrenMut<'a> {
727 type Item = &'a mut Element;
728
729 fn next(&mut self) -> Option<&'a mut Element> {
730 for item in &mut self.iter {
731 if let Node::Element(ref mut child) = *item {
732 return Some(child);
733 }
734 }
735 None
736 }
737}
738
739/// An iterator over references to child text nodes of an `Element`.
740pub struct Texts<'a> {
741 iter: slice::Iter<'a, Node>,
742}
743
744impl<'a> Iterator for Texts<'a> {
745 type Item = &'a str;
746
747 fn next(&mut self) -> Option<&'a str> {
748 for item in &mut self.iter {
749 if let Node::Text(ref child) = *item {
750 return Some(child);
751 }
752 }
753 None
754 }
755}
756
757/// An iterator over mutable references to child text nodes of an `Element`.
758pub struct TextsMut<'a> {
759 iter: slice::IterMut<'a, Node>,
760}
761
762impl<'a> Iterator for TextsMut<'a> {
763 type Item = &'a mut String;
764
765 fn next(&mut self) -> Option<&'a mut String> {
766 for item in &mut self.iter {
767 if let Node::Text(ref mut child) = *item {
768 return Some(child);
769 }
770 }
771 None
772 }
773}
774
775/// An iterator over references to all child nodes of an `Element`.
776pub type Nodes<'a> = slice::Iter<'a, Node>;
777
778/// An iterator over mutable references to all child nodes of an `Element`.
779pub type NodesMut<'a> = slice::IterMut<'a, Node>;
780
781/// An iterator over the attributes of an `Element`.
782pub struct Attrs<'a> {
783 iter: btree_map::Iter<'a, String, String>,
784}
785
786impl<'a> Iterator for Attrs<'a> {
787 type Item = (&'a str, &'a str);
788
789 fn next(&mut self) -> Option<Self::Item> {
790 self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
791 }
792}
793
794/// An iterator over the attributes of an `Element`, with the values mutable.
795pub struct AttrsMut<'a> {
796 iter: btree_map::IterMut<'a, String, String>,
797}
798
799impl<'a> Iterator for AttrsMut<'a> {
800 type Item = (&'a str, &'a mut String);
801
802 fn next(&mut self) -> Option<Self::Item> {
803 self.iter.next().map(|(x, y)| (x.as_ref(), y))
804 }
805}
806
807/// A builder for `Element`s.
808pub struct ElementBuilder {
809 root: Element,
810}
811
812impl ElementBuilder {
813 /// Sets a custom prefix. It is not possible to set the same prefix twice.
814 pub fn prefix<S: Into<Namespace>>(
815 mut self,
816 prefix: Prefix,
817 namespace: S,
818 ) -> Result<ElementBuilder> {
819 if self.root.prefixes.get(&prefix).is_some() {
820 return Err(Error::DuplicatePrefix);
821 }
822 self.root.prefixes.insert(prefix, namespace.into());
823 Ok(self)
824 }
825
826 /// Sets an attribute.
827 pub fn attr<S: Into<String>, V: IntoAttributeValue>(
828 mut self,
829 name: S,
830 value: V,
831 ) -> ElementBuilder {
832 self.root.set_attr(name, value);
833 self
834 }
835
836 /// Appends anything implementing `Into<Node>` into the tree.
837 pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
838 self.root.append_node(node.into());
839 self
840 }
841
842 /// Appends an iterator of things implementing `Into<Node>` into the tree.
843 pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(
844 mut self,
845 iter: I,
846 ) -> ElementBuilder {
847 for node in iter {
848 self.root.append_node(node.into());
849 }
850 self
851 }
852
853 /// Builds the `Element`.
854 pub fn build(self) -> Element {
855 self.root
856 }
857}
858
859#[cfg(test)]
860mod tests {
861 use super::*;
862
863 #[test]
864 fn test_element_new() {
865 use std::iter::FromIterator;
866
867 let elem = Element::new(
868 "name".to_owned(),
869 "namespace".to_owned(),
870 (None, "namespace".to_owned()),
871 BTreeMap::from_iter(vec![("name".to_string(), "value".to_string())].into_iter()),
872 Vec::new(),
873 );
874
875 assert_eq!(elem.name(), "name");
876 assert_eq!(elem.ns(), "namespace".to_owned());
877 assert_eq!(elem.attr("name"), Some("value"));
878 assert_eq!(elem.attr("inexistent"), None);
879 }
880
881 #[test]
882 fn test_from_reader_simple() {
883 let xml = b"<foo xmlns='ns1'></foo>";
884 let elem = Element::from_reader(&xml[..]);
885
886 let elem2 = Element::builder("foo", "ns1").build();
887
888 assert_eq!(elem.unwrap(), elem2);
889 }
890
891 #[test]
892 fn test_from_reader_nested() {
893 let xml = b"<foo xmlns='ns1'><bar xmlns='ns1' baz='qxx' /></foo>";
894 let elem = Element::from_reader(&xml[..]);
895
896 let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
897 let elem2 = Element::builder("foo", "ns1").append(nested).build();
898
899 assert_eq!(elem.unwrap(), elem2);
900 }
901
902 #[test]
903 fn test_from_reader_with_prefix() {
904 let xml = b"<foo xmlns='ns1'><prefix:bar xmlns:prefix='ns1' baz='qxx' /></foo>";
905 let elem = Element::from_reader(&xml[..]);
906
907 let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
908 let elem2 = Element::builder("foo", "ns1").append(nested).build();
909
910 assert_eq!(elem.unwrap(), elem2);
911 }
912
913 #[test]
914 fn test_from_reader_split_prefix() {
915 let xml = b"<foo:bar xmlns:foo='ns1'/>";
916 let elem = Element::from_reader(&xml[..]).unwrap();
917
918 assert_eq!(elem.name(), String::from("bar"));
919 assert_eq!(elem.ns(), String::from("ns1"));
920 // Ensure the prefix is properly added to the store
921 assert_eq!(
922 elem.prefixes.get(&Some(String::from("foo"))),
923 Some(&String::from("ns1"))
924 );
925 }
926
927 #[test]
928 fn parses_spectest_xml() {
929 // From: https://gitlab.com/lumi/minidom-rs/issues/8
930 let xml = br#"<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
931 <rng:name xmlns:rng="http://relaxng.org/ns/structure/1.0"></rng:name>
932 </rng:grammar>
933 "#;
934 let _ = Element::from_reader(&xml[..]).unwrap();
935 }
936
937 #[test]
938 fn does_not_unescape_cdata() {
939 let xml = b"<test xmlns='test'><![CDATA['>blah<blah>]]></test>";
940 let elem = Element::from_reader(&xml[..]).unwrap();
941 assert_eq!(elem.text(), "'>blah<blah>");
942 }
943
944 #[test]
945 fn test_compare_all_ns() {
946 let xml = b"<foo xmlns='foo' xmlns:bar='baz'><bar:meh xmlns:bar='baz' /></foo>";
947 let elem = Element::from_reader(&xml[..]).unwrap();
948
949 let elem2 = elem.clone();
950
951 let xml3 = b"<foo xmlns='foo'><bar:meh xmlns:bar='baz'/></foo>";
952 let elem3 = Element::from_reader(&xml3[..]).unwrap();
953
954 let xml4 = b"<prefix:foo xmlns:prefix='foo'><bar:meh xmlns:bar='baz'/></prefix:foo>";
955 let elem4 = Element::from_reader(&xml4[..]).unwrap();
956
957 assert_eq!(elem, elem2);
958 assert_eq!(elem, elem3);
959 assert_eq!(elem, elem4);
960 }
961}