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