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 /// 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 = PullDriver::wrap(reader, Lexer::new(), RawParser::new());
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.inner_mut().declare_fixed(
395 prefix.as_ref().map(|x| (&**x).try_into()).transpose()?,
396 Some(Arc::new(namespace.clone().try_into()?))
397 ));
398 }
399
400 let namespace = if self.namespace.len() == 0 {
401 None
402 } else {
403 Some(Arc::new(self.namespace.clone().try_into()?))
404 };
405 writer.write(Item::ElementHeadStart(namespace, (*self.name).try_into()?))?;
406
407 for (key, value) in self.attributes.iter() {
408 let (prefix, name) = <&rxml::NameStr>::try_from(&**key)
409 .unwrap()
410 .split_name()
411 .unwrap();
412 let namespace = match prefix {
413 Some(prefix) => match writer.encoder.inner().lookup_prefix(Some(prefix)) {
414 Ok(v) => Some(v),
415 Err(rxml::writer::PrefixError::Undeclared) => return Err(Error::InvalidPrefix),
416 },
417 None => None,
418 };
419 writer.write(Item::Attribute(namespace, name, (&**value).try_into()?))?;
420 }
421
422 if !self.children.is_empty() {
423 writer.write(Item::ElementHeadEnd)?;
424 for child in self.children.iter() {
425 child.write_to_inner(writer)?;
426 }
427 }
428 writer.write(Item::ElementFoot)?;
429
430 Ok(())
431 }
432
433 /// Returns an iterator over references to every child node of this element.
434 ///
435 /// # Examples
436 ///
437 /// ```rust
438 /// use minidom::Element;
439 ///
440 /// let elem: Element = "<root xmlns=\"ns1\">a<c1 />b<c2 />c</root>".parse().unwrap();
441 ///
442 /// let mut iter = elem.nodes();
443 ///
444 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
445 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
446 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
447 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
448 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
449 /// assert_eq!(iter.next(), None);
450 /// ```
451 #[inline]
452 pub fn nodes(&self) -> Nodes {
453 self.children.iter()
454 }
455
456 /// Returns an iterator over mutable references to every child node of this element.
457 #[inline]
458 pub fn nodes_mut(&mut self) -> NodesMut {
459 self.children.iter_mut()
460 }
461
462 /// Returns an iterator over references to every child element of this element.
463 ///
464 /// # Examples
465 ///
466 /// ```rust
467 /// use minidom::Element;
468 ///
469 /// let elem: Element = "<root xmlns=\"ns1\">hello<child1 xmlns=\"ns1\"/>this<child2 xmlns=\"ns1\"/>is<child3 xmlns=\"ns1\"/>ignored</root>".parse().unwrap();
470 ///
471 /// let mut iter = elem.children();
472 /// assert_eq!(iter.next().unwrap().name(), "child1");
473 /// assert_eq!(iter.next().unwrap().name(), "child2");
474 /// assert_eq!(iter.next().unwrap().name(), "child3");
475 /// assert_eq!(iter.next(), None);
476 /// ```
477 #[inline]
478 pub fn children(&self) -> Children {
479 Children {
480 iter: self.children.iter(),
481 }
482 }
483
484 /// Returns an iterator over mutable references to every child element of this element.
485 #[inline]
486 pub fn children_mut(&mut self) -> ChildrenMut {
487 ChildrenMut {
488 iter: self.children.iter_mut(),
489 }
490 }
491
492 /// Returns an iterator over references to every text node of this element.
493 ///
494 /// # Examples
495 ///
496 /// ```rust
497 /// use minidom::Element;
498 ///
499 /// let elem: Element = "<root xmlns=\"ns1\">hello<c /> world!</root>".parse().unwrap();
500 ///
501 /// let mut iter = elem.texts();
502 /// assert_eq!(iter.next().unwrap(), "hello");
503 /// assert_eq!(iter.next().unwrap(), " world!");
504 /// assert_eq!(iter.next(), None);
505 /// ```
506 #[inline]
507 pub fn texts(&self) -> Texts {
508 Texts {
509 iter: self.children.iter(),
510 }
511 }
512
513 /// Returns an iterator over mutable references to every text node of this element.
514 #[inline]
515 pub fn texts_mut(&mut self) -> TextsMut {
516 TextsMut {
517 iter: self.children.iter_mut(),
518 }
519 }
520
521 /// Appends a child node to the `Element`, returning the appended node.
522 ///
523 /// # Examples
524 ///
525 /// ```rust
526 /// use minidom::Element;
527 ///
528 /// let mut elem = Element::bare("root", "ns1");
529 ///
530 /// assert_eq!(elem.children().count(), 0);
531 ///
532 /// elem.append_child(Element::bare("child", "ns1"));
533 ///
534 /// {
535 /// let mut iter = elem.children();
536 /// assert_eq!(iter.next().unwrap().name(), "child");
537 /// assert_eq!(iter.next(), None);
538 /// }
539 ///
540 /// let child = elem.append_child(Element::bare("new", "ns1"));
541 ///
542 /// assert_eq!(child.name(), "new");
543 /// ```
544 pub fn append_child(&mut self, child: Element) -> &mut Element {
545 self.children.push(Node::Element(child));
546 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
547 cld
548 } else {
549 unreachable!()
550 }
551 }
552
553 /// Appends a text node to an `Element`.
554 ///
555 /// # Examples
556 ///
557 /// ```rust
558 /// use minidom::Element;
559 ///
560 /// let mut elem = Element::bare("node", "ns1");
561 ///
562 /// assert_eq!(elem.text(), "");
563 ///
564 /// elem.append_text_node("text");
565 ///
566 /// assert_eq!(elem.text(), "text");
567 /// ```
568 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
569 self.children.push(Node::Text(child.into()));
570 }
571
572 /// Appends a node to an `Element`.
573 ///
574 /// # Examples
575 ///
576 /// ```rust
577 /// use minidom::{Element, Node};
578 ///
579 /// let mut elem = Element::bare("node", "ns1");
580 ///
581 /// elem.append_node(Node::Text("hello".to_owned()));
582 ///
583 /// assert_eq!(elem.text(), "hello");
584 /// ```
585 pub fn append_node(&mut self, node: Node) {
586 self.children.push(node);
587 }
588
589 /// Returns the concatenation of all text nodes in the `Element`.
590 ///
591 /// # Examples
592 ///
593 /// ```rust
594 /// use minidom::Element;
595 ///
596 /// let elem: Element = "<node xmlns=\"ns1\">hello,<split /> world!</node>".parse().unwrap();
597 ///
598 /// assert_eq!(elem.text(), "hello, world!");
599 /// ```
600 pub fn text(&self) -> String {
601 self.texts().fold(String::new(), |ret, new| ret + new)
602 }
603
604 /// Returns a reference to the first child element with the specific name and namespace, if it
605 /// exists in the direct descendants of this `Element`, else returns `None`.
606 ///
607 /// # Examples
608 ///
609 /// ```rust
610 /// use minidom::{Element, NSChoice};
611 ///
612 /// let elem: Element = r#"<node xmlns="ns"><a/><a xmlns="other_ns" /><b/></node>"#.parse().unwrap();
613 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
614 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
615 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
616 /// assert_eq!(elem.get_child("c", "ns"), None);
617 /// assert_eq!(elem.get_child("b", "other_ns"), None);
618 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
619 /// ```
620 pub fn get_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
621 &self,
622 name: N,
623 namespace: NS,
624 ) -> Option<&Element> {
625 let namespace = namespace.into();
626 for fork in &self.children {
627 if let Node::Element(ref e) = *fork {
628 if e.is(name.as_ref(), namespace) {
629 return Some(e);
630 }
631 }
632 }
633 None
634 }
635
636 /// Returns a mutable reference to the first child element with the specific name and namespace,
637 /// if it exists in the direct descendants of this `Element`, else returns `None`.
638 pub fn get_child_mut<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
639 &mut self,
640 name: N,
641 namespace: NS,
642 ) -> Option<&mut Element> {
643 let namespace = namespace.into();
644 for fork in &mut self.children {
645 if let Node::Element(ref mut e) = *fork {
646 if e.is(name.as_ref(), namespace) {
647 return Some(e);
648 }
649 }
650 }
651 None
652 }
653
654 /// Returns whether a specific child with this name and namespace exists in the direct
655 /// descendants of the `Element`.
656 ///
657 /// # Examples
658 ///
659 /// ```rust
660 /// use minidom::{Element, NSChoice};
661 ///
662 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
663 /// assert_eq!(elem.has_child("a", "other_ns"), true);
664 /// assert_eq!(elem.has_child("a", "ns"), true);
665 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
666 /// assert_eq!(elem.has_child("b", "ns"), true);
667 /// assert_eq!(elem.has_child("b", "other_ns"), false);
668 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
669 /// ```
670 pub fn has_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
671 &self,
672 name: N,
673 namespace: NS,
674 ) -> bool {
675 self.get_child(name, namespace).is_some()
676 }
677
678 /// Removes the first child with this name and namespace, if it exists, and returns an
679 /// `Option<Element>` containing this child if it succeeds.
680 /// Returns `None` if no child matches this name and namespace.
681 ///
682 /// # Examples
683 ///
684 /// ```rust
685 /// use minidom::{Element, NSChoice};
686 ///
687 /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
688 /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
689 /// assert!(elem.remove_child("a", "ns").is_none());
690 /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
691 /// ```
692 pub fn remove_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
693 &mut self,
694 name: N,
695 namespace: NS,
696 ) -> Option<Element> {
697 let name = name.as_ref();
698 let namespace = namespace.into();
699 let idx = self.children.iter().position(|x| {
700 if let Node::Element(ref elm) = x {
701 elm.is(name, namespace)
702 } else {
703 false
704 }
705 })?;
706 self.children.remove(idx).into_element()
707 }
708
709 /// Remove the leading nodes up to the first child element and
710 /// return it
711 pub fn unshift_child(&mut self) -> Option<Element> {
712 while self.children.len() > 0 {
713 if let Some(el) = self.children.remove(0).into_element() {
714 return Some(el);
715 }
716 }
717
718 None
719 }
720}
721
722/// An iterator over references to child elements of an `Element`.
723pub struct Children<'a> {
724 iter: slice::Iter<'a, Node>,
725}
726
727impl<'a> Iterator for Children<'a> {
728 type Item = &'a Element;
729
730 fn next(&mut self) -> Option<&'a Element> {
731 for item in &mut self.iter {
732 if let Node::Element(ref child) = *item {
733 return Some(child);
734 }
735 }
736 None
737 }
738}
739
740/// An iterator over mutable references to child elements of an `Element`.
741pub struct ChildrenMut<'a> {
742 iter: slice::IterMut<'a, Node>,
743}
744
745impl<'a> Iterator for ChildrenMut<'a> {
746 type Item = &'a mut Element;
747
748 fn next(&mut self) -> Option<&'a mut Element> {
749 for item in &mut self.iter {
750 if let Node::Element(ref mut child) = *item {
751 return Some(child);
752 }
753 }
754 None
755 }
756}
757
758/// An iterator over references to child text nodes of an `Element`.
759pub struct Texts<'a> {
760 iter: slice::Iter<'a, Node>,
761}
762
763impl<'a> Iterator for Texts<'a> {
764 type Item = &'a str;
765
766 fn next(&mut self) -> Option<&'a str> {
767 for item in &mut self.iter {
768 if let Node::Text(ref child) = *item {
769 return Some(child);
770 }
771 }
772 None
773 }
774}
775
776/// An iterator over mutable references to child text nodes of an `Element`.
777pub struct TextsMut<'a> {
778 iter: slice::IterMut<'a, Node>,
779}
780
781impl<'a> Iterator for TextsMut<'a> {
782 type Item = &'a mut String;
783
784 fn next(&mut self) -> Option<&'a mut String> {
785 for item in &mut self.iter {
786 if let Node::Text(ref mut child) = *item {
787 return Some(child);
788 }
789 }
790 None
791 }
792}
793
794/// An iterator over references to all child nodes of an `Element`.
795pub type Nodes<'a> = slice::Iter<'a, Node>;
796
797/// An iterator over mutable references to all child nodes of an `Element`.
798pub type NodesMut<'a> = slice::IterMut<'a, Node>;
799
800/// An iterator over the attributes of an `Element`.
801pub struct Attrs<'a> {
802 iter: btree_map::Iter<'a, String, String>,
803}
804
805impl<'a> Iterator for Attrs<'a> {
806 type Item = (&'a str, &'a str);
807
808 fn next(&mut self) -> Option<Self::Item> {
809 self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
810 }
811}
812
813/// An iterator over the attributes of an `Element`, with the values mutable.
814pub struct AttrsMut<'a> {
815 iter: btree_map::IterMut<'a, String, String>,
816}
817
818impl<'a> Iterator for AttrsMut<'a> {
819 type Item = (&'a str, &'a mut String);
820
821 fn next(&mut self) -> Option<Self::Item> {
822 self.iter.next().map(|(x, y)| (x.as_ref(), y))
823 }
824}
825
826/// A builder for `Element`s.
827pub struct ElementBuilder {
828 root: Element,
829}
830
831impl ElementBuilder {
832 /// Sets a custom prefix. It is not possible to set the same prefix twice.
833 pub fn prefix<S: Into<Namespace>>(
834 mut self,
835 prefix: Prefix,
836 namespace: S,
837 ) -> Result<ElementBuilder> {
838 if self.root.prefixes.get(&prefix).is_some() {
839 return Err(Error::DuplicatePrefix);
840 }
841 self.root.prefixes.insert(prefix, namespace.into());
842 Ok(self)
843 }
844
845 /// Sets an attribute.
846 pub fn attr<S: Into<String>, V: IntoAttributeValue>(
847 mut self,
848 name: S,
849 value: V,
850 ) -> ElementBuilder {
851 self.root.set_attr(name, value);
852 self
853 }
854
855 /// Appends anything implementing `Into<Node>` into the tree.
856 pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
857 self.root.append_node(node.into());
858 self
859 }
860
861 /// Appends an iterator of things implementing `Into<Node>` into the tree.
862 pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(
863 mut self,
864 iter: I,
865 ) -> ElementBuilder {
866 for node in iter {
867 self.root.append_node(node.into());
868 }
869 self
870 }
871
872 /// Builds the `Element`.
873 pub fn build(self) -> Element {
874 self.root
875 }
876}
877
878#[cfg(test)]
879mod tests {
880 use super::*;
881
882 #[test]
883 fn test_element_new() {
884 use std::iter::FromIterator;
885
886 let elem = Element::new(
887 "name".to_owned(),
888 "namespace".to_owned(),
889 (None, "namespace".to_owned()),
890 BTreeMap::from_iter(vec![("name".to_string(), "value".to_string())].into_iter()),
891 Vec::new(),
892 );
893
894 assert_eq!(elem.name(), "name");
895 assert_eq!(elem.ns(), "namespace".to_owned());
896 assert_eq!(elem.attr("name"), Some("value"));
897 assert_eq!(elem.attr("inexistent"), None);
898 }
899
900 #[test]
901 fn test_from_reader_simple() {
902 let xml = b"<foo xmlns='ns1'></foo>";
903 let elem = Element::from_reader(&xml[..]);
904
905 let elem2 = Element::builder("foo", "ns1").build();
906
907 assert_eq!(elem.unwrap(), elem2);
908 }
909
910 #[test]
911 fn test_from_reader_nested() {
912 let xml = b"<foo xmlns='ns1'><bar xmlns='ns1' baz='qxx' /></foo>";
913 let elem = Element::from_reader(&xml[..]);
914
915 let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
916 let elem2 = Element::builder("foo", "ns1").append(nested).build();
917
918 assert_eq!(elem.unwrap(), elem2);
919 }
920
921 #[test]
922 fn test_from_reader_with_prefix() {
923 let xml = b"<foo xmlns='ns1'><prefix:bar xmlns:prefix='ns1' baz='qxx' /></foo>";
924 let elem = Element::from_reader(&xml[..]);
925
926 let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
927 let elem2 = Element::builder("foo", "ns1").append(nested).build();
928
929 assert_eq!(elem.unwrap(), elem2);
930 }
931
932 #[test]
933 fn test_from_reader_split_prefix() {
934 let xml = b"<foo:bar xmlns:foo='ns1'/>";
935 let elem = Element::from_reader(&xml[..]).unwrap();
936
937 assert_eq!(elem.name(), String::from("bar"));
938 assert_eq!(elem.ns(), String::from("ns1"));
939 // Ensure the prefix is properly added to the store
940 assert_eq!(
941 elem.prefixes.get(&Some(String::from("foo"))),
942 Some(&String::from("ns1"))
943 );
944 }
945
946 #[test]
947 fn parses_spectest_xml() {
948 // From: https://gitlab.com/lumi/minidom-rs/issues/8
949 let xml = br#"<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
950 <rng:name xmlns:rng="http://relaxng.org/ns/structure/1.0"></rng:name>
951 </rng:grammar>
952 "#;
953 let _ = Element::from_reader(&xml[..]).unwrap();
954 }
955
956 #[test]
957 fn does_not_unescape_cdata() {
958 let xml = b"<test xmlns='test'><![CDATA['>blah<blah>]]></test>";
959 let elem = Element::from_reader(&xml[..]).unwrap();
960 assert_eq!(elem.text(), "'>blah<blah>");
961 }
962
963 #[test]
964 fn test_compare_all_ns() {
965 let xml = b"<foo xmlns='foo' xmlns:bar='baz'><bar:meh xmlns:bar='baz' /></foo>";
966 let elem = Element::from_reader(&xml[..]).unwrap();
967
968 let elem2 = elem.clone();
969
970 let xml3 = b"<foo xmlns='foo'><bar:meh xmlns:bar='baz'/></foo>";
971 let elem3 = Element::from_reader(&xml3[..]).unwrap();
972
973 let xml4 = b"<prefix:foo xmlns:prefix='foo'><bar:meh xmlns:bar='baz'/></prefix:foo>";
974 let elem4 = Element::from_reader(&xml4[..]).unwrap();
975
976 assert_eq!(elem, elem2);
977 assert_eq!(elem, elem3);
978 assert_eq!(elem, elem4);
979 }
980
981 #[test]
982 fn test_from_reader_with_prefixes() {
983 let xml = b"<foo><bar xmlns='baz'/></foo>";
984 let elem =
985 Element::from_reader_with_prefixes(&xml[..], String::from("jabber:client")).unwrap();
986
987 let xml2 = b"<foo xmlns='jabber:client'><bar xmlns='baz'/></foo>";
988 let elem2 = Element::from_reader(&xml2[..]).unwrap();
989
990 assert_eq!(elem, elem2);
991 }
992
993 #[test]
994 fn failure_with_duplicate_namespace() {
995 let _: Element = r###"<?xml version="1.0" encoding="UTF-8"?>
996 <wsdl:definitions
997 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
998 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
999 <wsdl:types>
1000 <xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1001 </xsd:schema>
1002 </wsdl:types>
1003 </wsdl:definitions>
1004 "###
1005 .parse()
1006 .unwrap();
1007 }
1008}