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