1/*!
2Represent an [XML 1.0](https://www.w3.org/TR/xml/) document as a read-only tree.
3
4The root point of the documentations is [`Document::parse`].
5
6You can find more details in the [README] and the [parsing doc].
7
8The tree structure itself is a heavily modified <https://github.com/causal-agent/ego-tree>
9License: ISC.
10
11[`Document::parse`]: struct.Document.html#method.parse
12[README]: https://github.com/RazrFalcon/roxmltree/blob/master/README.md
13[parsing doc]: https://github.com/RazrFalcon/roxmltree/blob/master/docs/parsing.md
14*/
15
16#![no_std]
17#![forbid(unsafe_code)]
18#![warn(missing_docs)]
19#![warn(missing_copy_implementations)]
20#![warn(missing_debug_implementations)]
21
22extern crate alloc;
23
24#[cfg(feature = "std")]
25extern crate std;
26
27use core::cmp::Ordering;
28use core::fmt;
29use core::hash::{Hash, Hasher};
30use core::num::NonZeroU32;
31use core::ops::Range;
32
33use alloc::vec::Vec;
34
35mod parse;
36mod tokenizer;
37
38#[cfg(test)]
39mod tokenizer_tests;
40
41pub use crate::parse::*;
42
43/// The <http://www.w3.org/XML/1998/namespace> URI.
44pub const NS_XML_URI: &str = "http://www.w3.org/XML/1998/namespace";
45/// The prefix 'xml', which is by definition bound to NS_XML_URI
46const NS_XML_PREFIX: &str = "xml";
47
48/// The <http://www.w3.org/2000/xmlns/> URI.
49pub const NS_XMLNS_URI: &str = "http://www.w3.org/2000/xmlns/";
50/// The string 'xmlns', which is used to declare new namespaces
51const XMLNS: &str = "xmlns";
52
53/// Position in text.
54///
55/// Position indicates a row/line and a column in the original text. Starting from 1:1.
56#[allow(missing_docs)]
57#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
58pub struct TextPos {
59 pub row: u32,
60 pub col: u32,
61}
62
63impl TextPos {
64 /// Constructs a new `TextPos`.
65 pub fn new(row: u32, col: u32) -> TextPos {
66 TextPos { row, col }
67 }
68}
69
70impl fmt::Display for TextPos {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 write!(f, "{}:{}", self.row, self.col)
73 }
74}
75
76/// An XML tree container.
77///
78/// A tree consists of [`Nodes`].
79/// There are no separate structs for each node type.
80/// So you should check the current node type yourself via [`Node::node_type()`].
81/// There are only [5 types](enum.NodeType.html):
82/// Root, Element, PI, Comment and Text.
83///
84/// As you can see there are no XML declaration and CDATA types.
85/// The XML declaration is basically skipped, since it doesn't contain any
86/// valuable information (we support only UTF-8 anyway).
87/// And CDATA will be converted into a Text node as is, without
88/// any preprocessing (you can read more about it
89/// [here](https://github.com/RazrFalcon/roxmltree/blob/master/docs/parsing.md)).
90///
91/// Also, the Text node data can be accessed from the text node itself or from
92/// the parent element via [`Node::text()`] or [`Node::tail()`].
93///
94/// [`Nodes`]: struct.Node.html
95/// [`Node::node_type()`]: struct.Node.html#method.node_type
96/// [`Node::text()`]: struct.Node.html#method.text
97/// [`Node::tail()`]: struct.Node.html#method.tail
98pub struct Document<'input> {
99 /// An original data.
100 ///
101 /// Required for `text_pos_at` methods.
102 text: &'input str,
103 nodes: Vec<NodeData<'input>>,
104 attributes: Vec<AttributeData<'input>>,
105 namespaces: Namespaces<'input>,
106}
107
108impl<'input> Document<'input> {
109 /// Returns the root node.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// let doc = roxmltree::Document::parse("<e/>").unwrap();
115 /// assert!(doc.root().is_root());
116 /// assert!(doc.root().first_child().unwrap().has_tag_name("e"));
117 /// ```
118 #[inline]
119 pub fn root<'a>(&'a self) -> Node<'a, 'input> {
120 Node {
121 id: NodeId::new(0),
122 d: &self.nodes[0],
123 doc: self,
124 }
125 }
126
127 /// Returns the node of the tree with the given NodeId.
128 ///
129 /// Note: NodeId::new(0) represents the root node
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// let doc = roxmltree::Document::parse("\
135 /// <p>
136 /// text
137 /// </p>
138 /// ").unwrap();
139 ///
140 /// use roxmltree::NodeId;
141 /// assert_eq!(doc.get_node(NodeId::new(0)).unwrap(), doc.root());
142 /// assert_eq!(doc.get_node(NodeId::new(1)), doc.descendants().find(|n| n.has_tag_name("p")));
143 /// assert_eq!(doc.get_node(NodeId::new(2)), doc.descendants().find(|n| n.is_text()));
144 /// assert_eq!(doc.get_node(NodeId::new(3)), None);
145 /// ```
146 #[inline]
147 pub fn get_node<'a>(&'a self, id: NodeId) -> Option<Node<'a, 'input>> {
148 self.nodes.get(id.get_usize()).map(|data| Node {
149 id,
150 d: data,
151 doc: self,
152 })
153 }
154
155 /// Returns the root element of the document.
156 ///
157 /// Unlike `root`, will return a first element node.
158 ///
159 /// The root element always exists.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// let doc = roxmltree::Document::parse("<!-- comment --><e/>").unwrap();
165 /// assert!(doc.root_element().has_tag_name("e"));
166 /// ```
167 #[inline]
168 pub fn root_element<'a>(&'a self) -> Node<'a, 'input> {
169 // `expect` is safe, because the `Document` is guarantee to have at least one element.
170 self.root()
171 .first_element_child()
172 .expect("XML documents must contain a root element")
173 }
174
175 /// Returns an iterator over document's descendant nodes.
176 ///
177 /// Shorthand for `doc.root().descendants()`.
178 #[inline]
179 pub fn descendants(&self) -> Descendants<'_, 'input> {
180 self.root().descendants()
181 }
182
183 /// Calculates `TextPos` in the original document from position in bytes.
184 ///
185 /// **Note:** this operation is expensive.
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// use roxmltree::*;
191 ///
192 /// let doc = Document::parse("\
193 /// <!-- comment -->
194 /// <e/>"
195 /// ).unwrap();
196 ///
197 /// assert_eq!(doc.text_pos_at(10), TextPos::new(1, 11));
198 /// assert_eq!(doc.text_pos_at(9999), TextPos::new(2, 5));
199 /// ```
200 #[inline]
201 pub fn text_pos_at(&self, pos: usize) -> TextPos {
202 tokenizer::Stream::new(self.text).gen_text_pos_from(pos)
203 }
204
205 /// Returns the input text of the original document.
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use roxmltree::*;
211 ///
212 /// let doc = Document::parse("<e/>").unwrap();
213 ///
214 /// assert_eq!(doc.input_text(), "<e/>");
215 /// ```
216 #[inline]
217 pub fn input_text(&self) -> &'input str {
218 self.text
219 }
220}
221
222impl<'input> fmt::Debug for Document<'input> {
223 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
224 if !self.root().has_children() {
225 return write!(f, "Document []");
226 }
227
228 macro_rules! writeln_indented {
229 ($depth:expr, $f:expr, $fmt:expr) => {
230 for _ in 0..$depth { write!($f, " ")?; }
231 writeln!($f, $fmt)?;
232 };
233 ($depth:expr, $f:expr, $fmt:expr, $($arg:tt)*) => {
234 for _ in 0..$depth { write!($f, " ")?; }
235 writeln!($f, $fmt, $($arg)*)?;
236 };
237 }
238
239 fn print_into_iter<
240 T: fmt::Debug,
241 E: ExactSizeIterator<Item = T>,
242 I: IntoIterator<Item = T, IntoIter = E>,
243 >(
244 prefix: &str,
245 data: I,
246 depth: usize,
247 f: &mut fmt::Formatter,
248 ) -> Result<(), fmt::Error> {
249 let data = data.into_iter();
250 if data.len() == 0 {
251 return Ok(());
252 }
253
254 writeln_indented!(depth, f, "{}: [", prefix);
255 for v in data {
256 writeln_indented!(depth + 1, f, "{:?}", v);
257 }
258 writeln_indented!(depth, f, "]");
259
260 Ok(())
261 }
262
263 fn print_children(
264 parent: Node,
265 depth: usize,
266 f: &mut fmt::Formatter,
267 ) -> Result<(), fmt::Error> {
268 for child in parent.children() {
269 if child.is_element() {
270 writeln_indented!(depth, f, "Element {{");
271 writeln_indented!(depth, f, " tag_name: {:?}", child.tag_name());
272 print_into_iter("attributes", child.attributes(), depth + 1, f)?;
273 print_into_iter("namespaces", child.namespaces(), depth + 1, f)?;
274
275 if child.has_children() {
276 writeln_indented!(depth, f, " children: [");
277 print_children(child, depth + 2, f)?;
278 writeln_indented!(depth, f, " ]");
279 }
280
281 writeln_indented!(depth, f, "}}");
282 } else {
283 writeln_indented!(depth, f, "{:?}", child);
284 }
285 }
286
287 Ok(())
288 }
289
290 writeln!(f, "Document [")?;
291 print_children(self.root(), 1, f)?;
292 writeln!(f, "]")?;
293
294 Ok(())
295 }
296}
297
298/// A list of supported node types.
299#[derive(Clone, Copy, PartialEq, Eq, Debug)]
300pub enum NodeType {
301 /// The root node of the `Document`.
302 Root,
303 /// An element node.
304 ///
305 /// Only an element can have a tag name and attributes.
306 Element,
307 /// A processing instruction.
308 PI,
309 /// A comment node.
310 Comment,
311 /// A text node.
312 Text,
313}
314
315/// A processing instruction.
316#[derive(Clone, Copy, PartialEq, Eq, Debug)]
317#[allow(missing_docs)]
318pub struct PI<'input> {
319 pub target: &'input str,
320 pub value: Option<&'input str>,
321}
322
323/// A short range.
324///
325/// Just like Range, but only for `u32` and copyable.
326#[derive(Clone, Copy, Debug)]
327struct ShortRange {
328 start: u32,
329 end: u32,
330}
331
332impl From<Range<usize>> for ShortRange {
333 #[inline]
334 fn from(range: Range<usize>) -> Self {
335 debug_assert!(range.start <= core::u32::MAX as usize);
336 debug_assert!(range.end <= core::u32::MAX as usize);
337 ShortRange::new(range.start as u32, range.end as u32)
338 }
339}
340
341impl ShortRange {
342 #[inline]
343 fn new(start: u32, end: u32) -> Self {
344 ShortRange { start, end }
345 }
346
347 #[inline]
348 fn to_urange(self) -> Range<usize> {
349 self.start as usize..self.end as usize
350 }
351}
352
353/// A node ID stored as `u32`.
354///
355/// An index into a `Tree`-internal `Vec`.
356///
357/// Note that this value should be used with care since `roxmltree` doesn't
358/// check that `NodeId` actually belongs to a selected `Document`.
359/// So you can end up in a situation, when `NodeId` produced by one `Document`
360/// is used to select a node in another `Document`.
361#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
362pub struct NodeId(NonZeroU32);
363
364impl NodeId {
365 /// Construct a new `NodeId` from a `u32`.
366 #[inline]
367 pub fn new(id: u32) -> Self {
368 debug_assert!(id < core::u32::MAX);
369
370 // We are using `NonZeroU32` to reduce overhead of `Option<NodeId>`.
371 NodeId(NonZeroU32::new(id + 1).unwrap())
372 }
373
374 /// Returns the `u32` representation of the `NodeId`.
375 #[inline]
376 pub fn get(self) -> u32 {
377 self.0.get() - 1
378 }
379
380 /// Returns the `usize` representation of the `NodeId`.
381 #[inline]
382 pub fn get_usize(self) -> usize {
383 self.get() as usize
384 }
385}
386
387impl From<u32> for NodeId {
388 #[inline]
389 fn from(id: u32) -> Self {
390 NodeId::new(id)
391 }
392}
393
394impl From<usize> for NodeId {
395 #[inline]
396 fn from(id: usize) -> Self {
397 // We already checked that `id` is limited by u32::MAX.
398 debug_assert!(id <= core::u32::MAX as usize);
399 NodeId::new(id as u32)
400 }
401}
402
403#[derive(Debug)]
404enum NodeKind<'input> {
405 Root,
406 Element {
407 tag_name: ExpandedNameIndexed<'input>,
408 attributes: ShortRange,
409 namespaces: ShortRange,
410 },
411 PI(PI<'input>),
412 Comment(StringStorage<'input>),
413 Text(StringStorage<'input>),
414}
415
416#[derive(Debug)]
417struct NodeData<'input> {
418 parent: Option<NodeId>,
419 prev_sibling: Option<NodeId>,
420 next_subtree: Option<NodeId>,
421 last_child: Option<NodeId>,
422 kind: NodeKind<'input>,
423 #[cfg(feature = "positions")]
424 range: Range<usize>,
425}
426
427#[cfg(target_has_atomic = "ptr")]
428type OwnedSharedString = alloc::sync::Arc<str>;
429
430#[cfg(not(target_has_atomic = "ptr"))]
431type OwnedSharedString = alloc::rc::Rc<str>;
432
433/// A string storage.
434///
435/// Used by text nodes and attributes values.
436///
437/// We try our best not to allocate strings, referencing the input string as much as possible.
438/// But in some cases post-processing is necessary and we have to allocate them.
439///
440/// All owned, allocated strings are stored as `Arc<str>` or as `Rc<str>` on targets
441/// were `Arc` isn't available.
442/// And unlike `Cow<&str>`, `StringStorage` is immutable and can be cheaply cloned.
443#[derive(Clone, Eq, Debug)]
444pub enum StringStorage<'input> {
445 /// A raw slice of the input string.
446 Borrowed(&'input str),
447
448 /// A reference-counted string.
449 Owned(OwnedSharedString),
450}
451
452impl StringStorage<'_> {
453 /// Creates a new owned string from `&str` or `String`.
454 pub fn new_owned<T: Into<OwnedSharedString>>(s: T) -> Self {
455 StringStorage::Owned(s.into())
456 }
457
458 /// Returns a string slice.
459 pub fn as_str(&self) -> &str {
460 match self {
461 StringStorage::Borrowed(s: &&str) => s,
462 StringStorage::Owned(s: &Arc) => s,
463 }
464 }
465}
466
467impl PartialEq for StringStorage<'_> {
468 fn eq(&self, other: &Self) -> bool {
469 self.as_str() == other.as_str()
470 }
471}
472
473impl core::fmt::Display for StringStorage<'_> {
474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 write!(f, "{}", self.as_str())
476 }
477}
478
479impl core::ops::Deref for StringStorage<'_> {
480 type Target = str;
481
482 fn deref(&self) -> &Self::Target {
483 self.as_str()
484 }
485}
486
487#[derive(Clone, Debug)]
488struct AttributeData<'input> {
489 name: ExpandedNameIndexed<'input>,
490 value: StringStorage<'input>,
491 #[cfg(feature = "positions")]
492 pos: usize,
493}
494
495/// An attribute.
496#[derive(Copy, Clone)]
497pub struct Attribute<'a, 'input: 'a> {
498 doc: &'a Document<'input>,
499 data: &'a AttributeData<'input>,
500}
501
502impl<'a, 'input> Attribute<'a, 'input> {
503 /// Returns attribute's namespace URI.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// let doc = roxmltree::Document::parse(
509 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
510 /// ).unwrap();
511 ///
512 /// assert_eq!(doc.root_element().attributes().nth(0).unwrap().namespace(), None);
513 /// assert_eq!(doc.root_element().attributes().nth(1).unwrap().namespace(), Some("http://www.w3.org"));
514 /// ```
515 #[inline]
516 pub fn namespace(&self) -> Option<&'a str> {
517 self.data.name.namespace(self.doc).map(Namespace::uri)
518 }
519
520 /// Returns attribute's name.
521 ///
522 /// # Examples
523 ///
524 /// ```
525 /// let doc = roxmltree::Document::parse(
526 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
527 /// ).unwrap();
528 ///
529 /// assert_eq!(doc.root_element().attributes().nth(0).unwrap().name(), "a");
530 /// assert_eq!(doc.root_element().attributes().nth(1).unwrap().name(), "a");
531 /// ```
532 #[inline]
533 pub fn name(&self) -> &'input str {
534 self.data.name.local_name
535 }
536
537 /// Returns attribute's value.
538 ///
539 /// # Examples
540 ///
541 /// ```
542 /// let doc = roxmltree::Document::parse(
543 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
544 /// ).unwrap();
545 ///
546 /// assert_eq!(doc.root_element().attributes().nth(0).unwrap().value(), "b");
547 /// assert_eq!(doc.root_element().attributes().nth(1).unwrap().value(), "c");
548 /// ```
549 #[inline]
550 pub fn value(&self) -> &'a str {
551 &self.data.value
552 }
553
554 /// Returns attribute's value storage.
555 ///
556 /// Useful when you need a more low-level access to an allocated string.
557 #[inline]
558 pub fn value_storage(&self) -> &StringStorage<'input> {
559 &self.data.value
560 }
561
562 /// Returns attribute's position in bytes in the original document.
563 ///
564 /// You can calculate a human-readable text position via [Document::text_pos_at].
565 ///
566 /// ```text
567 /// <e attr='value'/>
568 /// ^
569 /// ```
570 ///
571 /// [Document::text_pos_at]: struct.Document.html#method.text_pos_at
572 #[cfg(feature = "positions")]
573 #[inline]
574 pub fn position(&self) -> usize {
575 self.data.pos
576 }
577}
578
579impl PartialEq for Attribute<'_, '_> {
580 #[inline]
581 fn eq(&self, other: &Attribute<'_, '_>) -> bool {
582 self.data.name.as_expanded_name(self.doc) == other.data.name.as_expanded_name(other.doc)
583 && self.data.value == other.data.value
584 }
585}
586
587impl fmt::Debug for Attribute<'_, '_> {
588 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
589 write!(
590 f,
591 "Attribute {{ name: {:?}, value: {:?} }}",
592 self.data.name.as_expanded_name(self.doc),
593 self.data.value
594 )
595 }
596}
597
598/// A namespace.
599///
600/// Contains URI and *prefix* pair.
601#[derive(Clone, PartialEq, Eq, Debug)]
602pub struct Namespace<'input> {
603 name: Option<&'input str>,
604 uri: StringStorage<'input>,
605}
606
607impl<'input> Namespace<'input> {
608 /// Returns namespace name/prefix.
609 ///
610 /// # Examples
611 ///
612 /// ```
613 /// let doc = roxmltree::Document::parse(
614 /// "<e xmlns:n='http://www.w3.org'/>"
615 /// ).unwrap();
616 ///
617 /// assert_eq!(doc.root_element().namespaces().nth(0).unwrap().name(), Some("n"));
618 /// ```
619 ///
620 /// ```
621 /// let doc = roxmltree::Document::parse(
622 /// "<e xmlns='http://www.w3.org'/>"
623 /// ).unwrap();
624 ///
625 /// assert_eq!(doc.root_element().namespaces().nth(0).unwrap().name(), None);
626 /// ```
627 #[inline]
628 pub fn name(&self) -> Option<&'input str> {
629 self.name
630 }
631
632 /// Returns namespace URI.
633 ///
634 /// # Examples
635 ///
636 /// ```
637 /// let doc = roxmltree::Document::parse(
638 /// "<e xmlns:n='http://www.w3.org'/>"
639 /// ).unwrap();
640 ///
641 /// assert_eq!(doc.root_element().namespaces().nth(0).unwrap().uri(), "http://www.w3.org");
642 /// ```
643 #[inline]
644 pub fn uri(&self) -> &str {
645 self.uri.as_ref()
646 }
647}
648
649#[derive(Default)]
650struct Namespaces<'input> {
651 // Deduplicated namespace values used throughout the document
652 values: Vec<Namespace<'input>>,
653 // Indices into the above in tree order as the document is parsed
654 tree_order: Vec<NamespaceIdx>,
655 // Indices into the above sorted by value used for deduplication
656 sorted_order: Vec<NamespaceIdx>,
657}
658
659impl<'input> Namespaces<'input> {
660 fn push_ns(
661 &mut self,
662 name: Option<&'input str>,
663 uri: StringStorage<'input>,
664 ) -> Result<(), Error> {
665 debug_assert_ne!(name, Some(""));
666
667 let idx = match self.sorted_order.binary_search_by(|idx| {
668 let value = &self.values[idx.0 as usize];
669
670 (value.name, value.uri.as_ref()).cmp(&(name, uri.as_str()))
671 }) {
672 Ok(sorted_idx) => self.sorted_order[sorted_idx],
673 Err(sorted_idx) => {
674 if self.values.len() > core::u16::MAX as usize {
675 return Err(Error::NamespacesLimitReached);
676 }
677 let idx = NamespaceIdx(self.values.len() as u16);
678 self.values.push(Namespace { name, uri });
679 self.sorted_order.insert(sorted_idx, idx);
680 idx
681 }
682 };
683
684 self.tree_order.push(idx);
685
686 Ok(())
687 }
688
689 #[inline]
690 fn push_ref(&mut self, tree_idx: usize) {
691 let idx = self.tree_order[tree_idx];
692 self.tree_order.push(idx);
693 }
694
695 #[inline]
696 fn exists(&self, start: usize, prefix: Option<&str>) -> bool {
697 self.tree_order[start..]
698 .iter()
699 .any(|idx| self.values[idx.0 as usize].name == prefix)
700 }
701
702 fn shrink_to_fit(&mut self) {
703 self.values.shrink_to_fit();
704 self.tree_order.shrink_to_fit();
705 self.sorted_order.shrink_to_fit();
706 }
707
708 #[inline]
709 fn get(&self, idx: NamespaceIdx) -> &Namespace<'input> {
710 &self.values[idx.0 as usize]
711 }
712}
713
714#[derive(Clone, Copy, Debug)]
715#[repr(transparent)]
716struct NamespaceIdx(u16);
717
718#[derive(Clone, Copy, Debug)]
719struct ExpandedNameIndexed<'input> {
720 namespace_idx: Option<NamespaceIdx>,
721 local_name: &'input str,
722}
723
724impl<'input> ExpandedNameIndexed<'input> {
725 #[inline]
726 fn namespace<'a>(&self, doc: &'a Document<'input>) -> Option<&'a Namespace<'input>> {
727 self.namespace_idx.map(|idx: NamespaceIdx| doc.namespaces.get(idx))
728 }
729
730 #[inline]
731 fn as_expanded_name<'a>(&self, doc: &'a Document<'input>) -> ExpandedName<'a, 'input> {
732 ExpandedName {
733 uri: self.namespace(doc).map(Namespace::uri),
734 name: self.local_name,
735 }
736 }
737}
738
739/// An expanded name.
740///
741/// Contains an namespace URI and name pair.
742#[derive(Clone, Copy, PartialEq, Eq)]
743pub struct ExpandedName<'a, 'b> {
744 uri: Option<&'a str>,
745 name: &'b str,
746}
747
748impl<'a, 'b> ExpandedName<'a, 'b> {
749 /// Returns a namespace URI.
750 ///
751 /// # Examples
752 ///
753 /// ```
754 /// let doc = roxmltree::Document::parse("<e xmlns='http://www.w3.org'/>").unwrap();
755 ///
756 /// assert_eq!(doc.root_element().tag_name().namespace(), Some("http://www.w3.org"));
757 /// ```
758 #[inline]
759 pub fn namespace(&self) -> Option<&'a str> {
760 self.uri
761 }
762
763 /// Returns a local name.
764 ///
765 /// # Examples
766 ///
767 /// ```
768 /// let doc = roxmltree::Document::parse("<e/>").unwrap();
769 ///
770 /// assert_eq!(doc.root_element().tag_name().name(), "e");
771 /// ```
772 #[inline]
773 pub fn name(&self) -> &'b str {
774 self.name
775 }
776}
777
778impl ExpandedName<'static, 'static> {
779 /// Create a new instance from static data.
780 ///
781 /// # Example
782 ///
783 /// ```rust
784 /// use roxmltree::ExpandedName;
785 /// const DAV_HREF: ExpandedName =
786 /// ExpandedName::from_static("urn:ietf:params:xml:ns:caldav:", "calendar-data");
787 /// ```
788 pub const fn from_static(uri: &'static str, name: &'static str) -> Self {
789 Self {
790 uri: Some(uri),
791 name,
792 }
793 }
794}
795
796impl fmt::Debug for ExpandedName<'_, '_> {
797 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
798 match self.namespace() {
799 Some(ns: &str) => write!(f, "{{{}}}{}", ns, self.name),
800 None => write!(f, "{}", self.name),
801 }
802 }
803}
804
805impl<'a, 'b> From<&'b str> for ExpandedName<'a, 'b> {
806 #[inline]
807 fn from(v: &'b str) -> Self {
808 ExpandedName { uri: None, name: v }
809 }
810}
811
812impl<'a, 'b> From<(&'a str, &'b str)> for ExpandedName<'a, 'b> {
813 #[inline]
814 fn from(v: (&'a str, &'b str)) -> Self {
815 ExpandedName {
816 uri: Some(v.0),
817 name: v.1,
818 }
819 }
820}
821
822/// A node in a document.
823///
824/// # Document Order
825///
826/// The implementation of the `Ord` traits for `Node` is based on the concept of *document-order*.
827/// In layman's terms, document-order is the order in which one would see each element if
828/// one opened a document in a text editor or web browser and scrolled down.
829/// Document-order convention is followed in XPath, CSS Counters, and DOM selectors API
830/// to ensure consistent results from selection.
831/// One difference in `roxmltree` is that there is the notion of more than one document
832/// in existence at a time. While Nodes within the same document are in document-order,
833/// Nodes in different documents will be grouped together, but not in any particular
834/// order.
835///
836/// As an example, if we have a Document `a` with Nodes `[a0, a1, a2]` and a
837/// Document `b` with Nodes `[b0, b1]`, these Nodes in order could be either
838/// `[a0, a1, a2, b0, b1]` or `[b0, b1, a0, a1, a2]` and roxmltree makes no
839/// guarantee which it will be.
840///
841/// Document-order is defined here in the
842/// [W3C XPath Recommendation](https://www.w3.org/TR/xpath-3/#id-document-order)
843/// The use of document-order in DOM Selectors is described here in the
844/// [W3C Selectors API Level 1](https://www.w3.org/TR/selectors-api/#the-apis)
845#[derive(Clone, Copy)]
846pub struct Node<'a, 'input: 'a> {
847 /// Node's ID.
848 id: NodeId,
849
850 /// The tree containing the node.
851 doc: &'a Document<'input>,
852
853 /// Node's data.
854 d: &'a NodeData<'input>,
855}
856
857impl Eq for Node<'_, '_> {}
858
859impl PartialEq for Node<'_, '_> {
860 #[inline]
861 fn eq(&self, other: &Self) -> bool {
862 (self.id, self.doc as *const _) == (other.id, other.doc as *const _)
863 }
864}
865
866impl PartialOrd for Node<'_, '_> {
867 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
868 Some(self.cmp(other))
869 }
870}
871
872impl Ord for Node<'_, '_> {
873 fn cmp(&self, other: &Self) -> Ordering {
874 (self.id.0, self.doc as *const _).cmp(&(other.id.0, other.doc as *const _))
875 }
876}
877
878impl Hash for Node<'_, '_> {
879 fn hash<H: Hasher>(&self, state: &mut H) {
880 self.id.0.hash(state);
881 (self.doc as *const Document).hash(state);
882 (self.d as *const NodeData).hash(state);
883 }
884}
885
886impl<'a, 'input: 'a> Node<'a, 'input> {
887 /// Returns node's type.
888 #[inline]
889 pub fn node_type(&self) -> NodeType {
890 match self.d.kind {
891 NodeKind::Root => NodeType::Root,
892 NodeKind::Element { .. } => NodeType::Element,
893 NodeKind::PI { .. } => NodeType::PI,
894 NodeKind::Comment(_) => NodeType::Comment,
895 NodeKind::Text(_) => NodeType::Text,
896 }
897 }
898
899 /// Checks that node is a root node.
900 #[inline]
901 pub fn is_root(&self) -> bool {
902 self.node_type() == NodeType::Root
903 }
904
905 /// Checks that node is an element node.
906 #[inline]
907 pub fn is_element(&self) -> bool {
908 self.node_type() == NodeType::Element
909 }
910
911 /// Checks that node is a processing instruction node.
912 #[inline]
913 pub fn is_pi(&self) -> bool {
914 self.node_type() == NodeType::PI
915 }
916
917 /// Checks that node is a comment node.
918 #[inline]
919 pub fn is_comment(&self) -> bool {
920 self.node_type() == NodeType::Comment
921 }
922
923 /// Checks that node is a text node.
924 #[inline]
925 pub fn is_text(&self) -> bool {
926 self.node_type() == NodeType::Text
927 }
928
929 /// Returns node's document.
930 #[inline]
931 pub fn document(&self) -> &'a Document<'input> {
932 self.doc
933 }
934
935 /// Returns node's tag name.
936 ///
937 /// Returns an empty name with no namespace if the current node is not an element.
938 ///
939 /// # Examples
940 ///
941 /// ```
942 /// let doc = roxmltree::Document::parse("<e xmlns='http://www.w3.org'/>").unwrap();
943 ///
944 /// assert_eq!(doc.root_element().tag_name().namespace(), Some("http://www.w3.org"));
945 /// assert_eq!(doc.root_element().tag_name().name(), "e");
946 /// ```
947 #[inline]
948 pub fn tag_name(&self) -> ExpandedName<'a, 'input> {
949 match self.d.kind {
950 NodeKind::Element { ref tag_name, .. } => tag_name.as_expanded_name(self.doc),
951 _ => "".into(),
952 }
953 }
954
955 /// Checks that node has a specified tag name.
956 ///
957 /// # Examples
958 ///
959 /// ```
960 /// let doc = roxmltree::Document::parse("<e xmlns='http://www.w3.org'/>").unwrap();
961 ///
962 /// assert!(doc.root_element().has_tag_name("e"));
963 /// assert!(doc.root_element().has_tag_name(("http://www.w3.org", "e")));
964 ///
965 /// assert!(!doc.root_element().has_tag_name("b"));
966 /// assert!(!doc.root_element().has_tag_name(("http://www.w4.org", "e")));
967 /// ```
968 pub fn has_tag_name<'n, 'm, N>(&self, name: N) -> bool
969 where
970 N: Into<ExpandedName<'n, 'm>>,
971 {
972 let name = name.into();
973
974 match self.d.kind {
975 NodeKind::Element { ref tag_name, .. } => match name.namespace() {
976 Some(_) => tag_name.as_expanded_name(self.doc) == name,
977 None => tag_name.local_name == name.name,
978 },
979 _ => false,
980 }
981 }
982
983 /// Returns node's default namespace URI.
984 ///
985 /// # Examples
986 ///
987 /// ```
988 /// let doc = roxmltree::Document::parse("<e xmlns='http://www.w3.org'/>").unwrap();
989 ///
990 /// assert_eq!(doc.root_element().default_namespace(), Some("http://www.w3.org"));
991 /// ```
992 ///
993 /// ```
994 /// let doc = roxmltree::Document::parse("<e xmlns:n='http://www.w3.org'/>").unwrap();
995 ///
996 /// assert_eq!(doc.root_element().default_namespace(), None);
997 /// ```
998 pub fn default_namespace(&self) -> Option<&'a str> {
999 self.namespaces()
1000 .find(|ns| ns.name.is_none())
1001 .map(|v| v.uri.as_ref())
1002 }
1003
1004 /// Returns a prefix for a given namespace URI.
1005 ///
1006 /// # Examples
1007 ///
1008 /// ```
1009 /// let doc = roxmltree::Document::parse("<e xmlns:n='http://www.w3.org'/>").unwrap();
1010 ///
1011 /// assert_eq!(doc.root_element().lookup_prefix("http://www.w3.org"), Some("n"));
1012 /// ```
1013 ///
1014 /// ```
1015 /// let doc = roxmltree::Document::parse("<e xmlns:n=''/>").unwrap();
1016 ///
1017 /// assert_eq!(doc.root_element().lookup_prefix(""), Some("n"));
1018 /// ```
1019 pub fn lookup_prefix(&self, uri: &str) -> Option<&'input str> {
1020 if uri == NS_XML_URI {
1021 return Some(NS_XML_PREFIX);
1022 }
1023
1024 self.namespaces()
1025 .find(|ns| &*ns.uri == uri)
1026 .map(|v| v.name)
1027 .unwrap_or(None)
1028 }
1029
1030 /// Returns an URI for a given prefix.
1031 ///
1032 /// # Examples
1033 ///
1034 /// ```
1035 /// let doc = roxmltree::Document::parse("<e xmlns:n='http://www.w3.org'/>").unwrap();
1036 ///
1037 /// assert_eq!(doc.root_element().lookup_namespace_uri(Some("n")), Some("http://www.w3.org"));
1038 /// ```
1039 ///
1040 /// ```
1041 /// let doc = roxmltree::Document::parse("<e xmlns='http://www.w3.org'/>").unwrap();
1042 ///
1043 /// assert_eq!(doc.root_element().lookup_namespace_uri(None), Some("http://www.w3.org"));
1044 /// ```
1045 pub fn lookup_namespace_uri(&self, prefix: Option<&str>) -> Option<&'a str> {
1046 self.namespaces()
1047 .find(|ns| ns.name == prefix)
1048 .map(|v| v.uri.as_ref())
1049 }
1050
1051 /// Returns element's attribute value.
1052 ///
1053 /// # Examples
1054 ///
1055 /// ```
1056 /// let doc = roxmltree::Document::parse("<e a='b'/>").unwrap();
1057 ///
1058 /// assert_eq!(doc.root_element().attribute("a"), Some("b"));
1059 /// ```
1060 ///
1061 /// ```
1062 /// let doc = roxmltree::Document::parse(
1063 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
1064 /// ).unwrap();
1065 ///
1066 /// assert_eq!(doc.root_element().attribute("a"), Some("b"));
1067 /// assert_eq!(doc.root_element().attribute(("http://www.w3.org", "a")), Some("c"));
1068 /// ```
1069 pub fn attribute<'n, 'm, N>(&self, name: N) -> Option<&'a str>
1070 where
1071 N: Into<ExpandedName<'n, 'm>>,
1072 {
1073 let name = name.into();
1074 self.attributes()
1075 .find(|a| a.data.name.as_expanded_name(self.doc) == name)
1076 .map(|a| a.value())
1077 }
1078
1079 /// Returns element's attribute object.
1080 ///
1081 /// The same as [`attribute()`], but returns the `Attribute` itself instead of a value string.
1082 ///
1083 /// [`attribute()`]: struct.Node.html#method.attribute
1084 pub fn attribute_node<'n, 'm, N>(&self, name: N) -> Option<Attribute<'a, 'input>>
1085 where
1086 N: Into<ExpandedName<'n, 'm>>,
1087 {
1088 let name = name.into();
1089 self.attributes()
1090 .find(|a| a.data.name.as_expanded_name(self.doc) == name)
1091 }
1092
1093 /// Checks that element has a specified attribute.
1094 ///
1095 /// # Examples
1096 ///
1097 /// ```
1098 /// let doc = roxmltree::Document::parse(
1099 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
1100 /// ).unwrap();
1101 ///
1102 /// assert!(doc.root_element().has_attribute("a"));
1103 /// assert!(doc.root_element().has_attribute(("http://www.w3.org", "a")));
1104 ///
1105 /// assert!(!doc.root_element().has_attribute("b"));
1106 /// assert!(!doc.root_element().has_attribute(("http://www.w4.org", "a")));
1107 /// ```
1108 pub fn has_attribute<'n, 'm, N>(&self, name: N) -> bool
1109 where
1110 N: Into<ExpandedName<'n, 'm>>,
1111 {
1112 let name = name.into();
1113 self.attributes()
1114 .any(|a| a.data.name.as_expanded_name(self.doc) == name)
1115 }
1116
1117 /// Returns element's attributes.
1118 ///
1119 /// # Examples
1120 ///
1121 /// ```
1122 /// let doc = roxmltree::Document::parse(
1123 /// "<e xmlns:n='http://www.w3.org' a='b' n:a='c'/>"
1124 /// ).unwrap();
1125 ///
1126 /// assert_eq!(doc.root_element().attributes().len(), 2);
1127 /// ```
1128 #[inline]
1129 pub fn attributes(&self) -> Attributes<'a, 'input> {
1130 Attributes::new(self)
1131 }
1132
1133 /// Returns element's namespaces.
1134 ///
1135 /// # Examples
1136 ///
1137 /// ```
1138 /// let doc = roxmltree::Document::parse(
1139 /// "<e xmlns:n='http://www.w3.org'/>"
1140 /// ).unwrap();
1141 ///
1142 /// assert_eq!(doc.root_element().namespaces().len(), 1);
1143 /// ```
1144 #[inline]
1145 pub fn namespaces(&self) -> NamespaceIter<'a, 'input> {
1146 let namespaces = match self.d.kind {
1147 NodeKind::Element { ref namespaces, .. } => {
1148 &self.doc.namespaces.tree_order[namespaces.to_urange()]
1149 }
1150 _ => &[],
1151 };
1152
1153 NamespaceIter {
1154 doc: self.doc,
1155 namespaces: namespaces.iter(),
1156 }
1157 }
1158
1159 /// Returns node's text.
1160 ///
1161 /// - for an element will return a first text child
1162 /// - for a comment will return a self text
1163 /// - for a text node will return a self text
1164 ///
1165 /// # Examples
1166 ///
1167 /// ```
1168 /// let doc = roxmltree::Document::parse("\
1169 /// <p>
1170 /// text
1171 /// </p>
1172 /// ").unwrap();
1173 ///
1174 /// assert_eq!(doc.root_element().text(),
1175 /// Some("\n text\n"));
1176 /// assert_eq!(doc.root_element().first_child().unwrap().text(),
1177 /// Some("\n text\n"));
1178 /// ```
1179 ///
1180 /// ```
1181 /// let doc = roxmltree::Document::parse("<!-- comment --><e/>").unwrap();
1182 ///
1183 /// assert_eq!(doc.root().first_child().unwrap().text(), Some(" comment "));
1184 /// ```
1185 #[inline]
1186 pub fn text(&self) -> Option<&'a str> {
1187 self.text_storage().map(|s| s.as_str())
1188 }
1189
1190 /// Returns node's text storage.
1191 ///
1192 /// Useful when you need a more low-level access to an allocated string.
1193 pub fn text_storage(&self) -> Option<&'a StringStorage<'input>> {
1194 match self.d.kind {
1195 NodeKind::Element { .. } => match self.first_child() {
1196 Some(child) if child.is_text() => match self.doc.nodes[child.id.get_usize()].kind {
1197 NodeKind::Text(ref text) => Some(text),
1198 _ => None,
1199 },
1200 _ => None,
1201 },
1202 NodeKind::Comment(ref text) => Some(text),
1203 NodeKind::Text(ref text) => Some(text),
1204 _ => None,
1205 }
1206 }
1207
1208 /// Returns element's tail text.
1209 ///
1210 /// # Examples
1211 ///
1212 /// ```
1213 /// let doc = roxmltree::Document::parse("\
1214 /// <root>
1215 /// text1
1216 /// <p/>
1217 /// text2
1218 /// </root>
1219 /// ").unwrap();
1220 ///
1221 /// let p = doc.descendants().find(|n| n.has_tag_name("p")).unwrap();
1222 /// assert_eq!(p.tail(), Some("\n text2\n"));
1223 /// ```
1224 #[inline]
1225 pub fn tail(&self) -> Option<&'a str> {
1226 self.tail_storage().map(|s| s.as_str())
1227 }
1228
1229 /// Returns element's tail text storage.
1230 ///
1231 /// Useful when you need a more low-level access to an allocated string.
1232 pub fn tail_storage(&self) -> Option<&'a StringStorage<'input>> {
1233 if !self.is_element() {
1234 return None;
1235 }
1236
1237 match self.next_sibling().map(|n| n.id) {
1238 Some(id) => match self.doc.nodes[id.get_usize()].kind {
1239 NodeKind::Text(ref text) => Some(text),
1240 _ => None,
1241 },
1242 None => None,
1243 }
1244 }
1245
1246 /// Returns node as Processing Instruction.
1247 #[inline]
1248 pub fn pi(&self) -> Option<PI<'input>> {
1249 match self.d.kind {
1250 NodeKind::PI(pi) => Some(pi),
1251 _ => None,
1252 }
1253 }
1254
1255 /// Returns the parent of this node.
1256 #[inline]
1257 pub fn parent(&self) -> Option<Self> {
1258 self.d.parent.map(|id| self.doc.get_node(id).unwrap())
1259 }
1260
1261 /// Returns the parent element of this node.
1262 pub fn parent_element(&self) -> Option<Self> {
1263 self.ancestors().skip(1).find(|n| n.is_element())
1264 }
1265
1266 /// Returns the previous sibling of this node.
1267 #[inline]
1268 pub fn prev_sibling(&self) -> Option<Self> {
1269 self.d.prev_sibling.map(|id| self.doc.get_node(id).unwrap())
1270 }
1271
1272 /// Returns the previous sibling element of this node.
1273 pub fn prev_sibling_element(&self) -> Option<Self> {
1274 self.prev_siblings().skip(1).find(|n| n.is_element())
1275 }
1276
1277 /// Returns the next sibling of this node.
1278 #[inline]
1279 pub fn next_sibling(&self) -> Option<Self> {
1280 self.d
1281 .next_subtree
1282 .map(|id| self.doc.get_node(id).unwrap())
1283 .and_then(|node| {
1284 let possibly_self = node
1285 .d
1286 .prev_sibling
1287 .expect("next_subtree will always have a previous sibling");
1288 if possibly_self == self.id {
1289 Some(node)
1290 } else {
1291 None
1292 }
1293 })
1294 }
1295
1296 /// Returns the next sibling element of this node.
1297 pub fn next_sibling_element(&self) -> Option<Self> {
1298 self.next_siblings().skip(1).find(|n| n.is_element())
1299 }
1300
1301 /// Returns the first child of this node.
1302 #[inline]
1303 pub fn first_child(&self) -> Option<Self> {
1304 self.d
1305 .last_child
1306 .map(|_| self.doc.get_node(NodeId::new(self.id.get() + 1)).unwrap())
1307 }
1308
1309 /// Returns the first element child of this node.
1310 pub fn first_element_child(&self) -> Option<Self> {
1311 self.children().find(|n| n.is_element())
1312 }
1313
1314 /// Returns the last child of this node.
1315 #[inline]
1316 pub fn last_child(&self) -> Option<Self> {
1317 self.d.last_child.map(|id| self.doc.get_node(id).unwrap())
1318 }
1319
1320 /// Returns the last element child of this node.
1321 pub fn last_element_child(&self) -> Option<Self> {
1322 self.children().filter(|n| n.is_element()).last()
1323 }
1324
1325 /// Returns true if this node has siblings.
1326 #[inline]
1327 pub fn has_siblings(&self) -> bool {
1328 self.d.prev_sibling.is_some() || self.next_sibling().is_some()
1329 }
1330
1331 /// Returns true if this node has children.
1332 #[inline]
1333 pub fn has_children(&self) -> bool {
1334 self.d.last_child.is_some()
1335 }
1336
1337 /// Returns an iterator over ancestor nodes starting at this node.
1338 #[inline]
1339 pub fn ancestors(&self) -> AxisIter<'a, 'input> {
1340 AxisIter {
1341 node: Some(*self),
1342 next: Node::parent,
1343 }
1344 }
1345
1346 /// Returns an iterator over previous sibling nodes starting at this node.
1347 #[inline]
1348 pub fn prev_siblings(&self) -> AxisIter<'a, 'input> {
1349 AxisIter {
1350 node: Some(*self),
1351 next: Node::prev_sibling,
1352 }
1353 }
1354
1355 /// Returns an iterator over next sibling nodes starting at this node.
1356 #[inline]
1357 pub fn next_siblings(&self) -> AxisIter<'a, 'input> {
1358 AxisIter {
1359 node: Some(*self),
1360 next: Node::next_sibling,
1361 }
1362 }
1363
1364 /// Returns an iterator over first children nodes starting at this node.
1365 #[inline]
1366 pub fn first_children(&self) -> AxisIter<'a, 'input> {
1367 AxisIter {
1368 node: Some(*self),
1369 next: Node::first_child,
1370 }
1371 }
1372
1373 /// Returns an iterator over last children nodes starting at this node.
1374 #[inline]
1375 pub fn last_children(&self) -> AxisIter<'a, 'input> {
1376 AxisIter {
1377 node: Some(*self),
1378 next: Node::last_child,
1379 }
1380 }
1381
1382 /// Returns an iterator over children nodes.
1383 #[inline]
1384 pub fn children(&self) -> Children<'a, 'input> {
1385 Children {
1386 front: self.first_child(),
1387 back: self.last_child(),
1388 }
1389 }
1390
1391 /// Returns an iterator over this node and its descendants.
1392 #[inline]
1393 pub fn descendants(&self) -> Descendants<'a, 'input> {
1394 Descendants::new(*self)
1395 }
1396
1397 /// Returns node's range in bytes in the original document.
1398 #[cfg(feature = "positions")]
1399 #[inline]
1400 pub fn range(&self) -> Range<usize> {
1401 self.d.range.clone()
1402 }
1403
1404 /// Returns node's NodeId
1405 #[inline]
1406 pub fn id(&self) -> NodeId {
1407 self.id
1408 }
1409}
1410
1411impl<'a, 'input: 'a> fmt::Debug for Node<'a, 'input> {
1412 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1413 match self.d.kind {
1414 NodeKind::Root => write!(f, "Root"),
1415 NodeKind::Element { .. } => {
1416 write!(
1417 f,
1418 "Element {{ tag_name: {:?}, attributes: {:?}, namespaces: {:?} }}",
1419 self.tag_name(),
1420 self.attributes(),
1421 self.namespaces()
1422 )
1423 }
1424 NodeKind::PI(pi: PI<'_>) => {
1425 write!(f, "PI {{ target: {:?}, value: {:?} }}", pi.target, pi.value)
1426 }
1427 NodeKind::Comment(ref text: &StringStorage<'_>) => write!(f, "Comment({:?})", text.as_str()),
1428 NodeKind::Text(ref text: &StringStorage<'_>) => write!(f, "Text({:?})", text.as_str()),
1429 }
1430 }
1431}
1432
1433/// Iterator over a node's attributes
1434#[derive(Clone)]
1435pub struct Attributes<'a, 'input> {
1436 doc: &'a Document<'input>,
1437 attrs: core::slice::Iter<'a, AttributeData<'input>>,
1438}
1439
1440impl<'a, 'input> Attributes<'a, 'input> {
1441 #[inline]
1442 fn new(node: &Node<'a, 'input>) -> Attributes<'a, 'input> {
1443 let attrs: &[AttributeData<'_>] = match node.d.kind {
1444 NodeKind::Element { ref attributes: &ShortRange, .. } => {
1445 &node.doc.attributes[attributes.to_urange()]
1446 }
1447 _ => &[],
1448 };
1449 Attributes {
1450 doc: node.doc,
1451 attrs: attrs.iter(),
1452 }
1453 }
1454}
1455
1456impl<'a, 'input> Iterator for Attributes<'a, 'input> {
1457 type Item = Attribute<'a, 'input>;
1458
1459 #[inline]
1460 fn next(&mut self) -> Option<Self::Item> {
1461 self.attrs.next().map(|attr: &AttributeData<'_>| Attribute {
1462 doc: self.doc,
1463 data: attr,
1464 })
1465 }
1466
1467 #[inline]
1468 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1469 self.attrs.nth(n).map(|attr: &AttributeData<'_>| Attribute {
1470 doc: self.doc,
1471 data: attr,
1472 })
1473 }
1474
1475 #[inline]
1476 fn size_hint(&self) -> (usize, Option<usize>) {
1477 self.attrs.size_hint()
1478 }
1479}
1480
1481impl<'a, 'input> DoubleEndedIterator for Attributes<'a, 'input> {
1482 #[inline]
1483 fn next_back(&mut self) -> Option<Self::Item> {
1484 self.attrs.next_back().map(|attr: &AttributeData<'_>| Attribute {
1485 doc: self.doc,
1486 data: attr,
1487 })
1488 }
1489}
1490
1491impl ExactSizeIterator for Attributes<'_, '_> {}
1492
1493impl fmt::Debug for Attributes<'_, '_> {
1494 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1495 f&mut DebugStruct<'_, '_>.debug_struct("Attributes")
1496 .field(name:"attrs", &self.attrs)
1497 .finish()
1498 }
1499}
1500
1501/// Iterator over specified axis.
1502#[derive(Clone)]
1503pub struct AxisIter<'a, 'input: 'a> {
1504 node: Option<Node<'a, 'input>>,
1505 next: fn(&Node<'a, 'input>) -> Option<Node<'a, 'input>>,
1506}
1507
1508impl<'a, 'input: 'a> Iterator for AxisIter<'a, 'input> {
1509 type Item = Node<'a, 'input>;
1510
1511 #[inline]
1512 fn next(&mut self) -> Option<Self::Item> {
1513 let node: Option> = self.node.take();
1514 self.node = node.as_ref().and_then(self.next);
1515 node
1516 }
1517}
1518
1519impl fmt::Debug for AxisIter<'_, '_> {
1520 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1521 f&mut DebugStruct<'_, '_>.debug_struct("AxisIter")
1522 .field("node", &self.node)
1523 .field(name:"next", &"fn()")
1524 .finish()
1525 }
1526}
1527
1528/// Iterator over children.
1529#[derive(Clone, Debug)]
1530pub struct Children<'a, 'input: 'a> {
1531 front: Option<Node<'a, 'input>>,
1532 back: Option<Node<'a, 'input>>,
1533}
1534
1535impl<'a, 'input: 'a> Iterator for Children<'a, 'input> {
1536 type Item = Node<'a, 'input>;
1537
1538 #[inline]
1539 fn next(&mut self) -> Option<Self::Item> {
1540 if self.front == self.back {
1541 let node: Option> = self.front.take();
1542 self.back = None;
1543 node
1544 } else {
1545 let node: Option> = self.front.take();
1546 self.front = node.as_ref().and_then(Node::next_sibling);
1547 node
1548 }
1549 }
1550}
1551
1552impl<'a, 'input: 'a> DoubleEndedIterator for Children<'a, 'input> {
1553 #[inline]
1554 fn next_back(&mut self) -> Option<Self::Item> {
1555 if self.back == self.front {
1556 let node: Option> = self.back.take();
1557 self.front = None;
1558 node
1559 } else {
1560 let node: Option> = self.back.take();
1561 self.back = node.as_ref().and_then(Node::prev_sibling);
1562 node
1563 }
1564 }
1565}
1566
1567/// Iterator over a node and its descendants.
1568#[derive(Clone)]
1569pub struct Descendants<'a, 'input> {
1570 doc: &'a Document<'input>,
1571 nodes: core::iter::Enumerate<core::slice::Iter<'a, NodeData<'input>>>,
1572 from: usize,
1573}
1574
1575impl<'a, 'input> Descendants<'a, 'input> {
1576 #[inline]
1577 fn new(start: Node<'a, 'input>) -> Self {
1578 let from: usize = start.id.get_usize();
1579
1580 let until: usize = start
1581 .d
1582 .next_subtree
1583 .map(NodeId::get_usize)
1584 .unwrap_or(default:start.doc.nodes.len());
1585
1586 let nodes: impl Iterator = start.doc.nodes[from..until].iter().enumerate();
1587
1588 Self {
1589 doc: start.doc,
1590 nodes,
1591 from,
1592 }
1593 }
1594}
1595
1596impl<'a, 'input> Iterator for Descendants<'a, 'input> {
1597 type Item = Node<'a, 'input>;
1598
1599 #[inline]
1600 fn next(&mut self) -> Option<Self::Item> {
1601 self.nodes.next().map(|(idx, data)| Node {
1602 id: NodeId::from(self.from + idx),
1603 d: data,
1604 doc: self.doc,
1605 })
1606 }
1607
1608 #[inline]
1609 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1610 self.nodes.nth(n).map(|(idx, data)| Node {
1611 id: NodeId::from(self.from + idx),
1612 d: data,
1613 doc: self.doc,
1614 })
1615 }
1616
1617 #[inline]
1618 fn size_hint(&self) -> (usize, Option<usize>) {
1619 self.nodes.size_hint()
1620 }
1621}
1622
1623impl<'a, 'input> DoubleEndedIterator for Descendants<'a, 'input> {
1624 #[inline]
1625 fn next_back(&mut self) -> Option<Self::Item> {
1626 self.nodes.next_back().map(|(idx: usize, data: &NodeData<'_>)| Node {
1627 id: NodeId::from(self.from + idx),
1628 d: data,
1629 doc: self.doc,
1630 })
1631 }
1632}
1633
1634impl ExactSizeIterator for Descendants<'_, '_> {}
1635
1636impl fmt::Debug for Descendants<'_, '_> {
1637 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1638 f&mut DebugStruct<'_, '_>.debug_struct("Descendants")
1639 .field("nodes", &self.nodes)
1640 .field(name:"from", &self.from)
1641 .finish()
1642 }
1643}
1644
1645/// Iterator over the namespaces attached to a node.
1646#[derive(Clone)]
1647pub struct NamespaceIter<'a, 'input> {
1648 doc: &'a Document<'input>,
1649 namespaces: core::slice::Iter<'a, NamespaceIdx>,
1650}
1651
1652impl<'a, 'input> Iterator for NamespaceIter<'a, 'input> {
1653 type Item = &'a Namespace<'input>;
1654
1655 #[inline]
1656 fn next(&mut self) -> Option<Self::Item> {
1657 self.namespaces
1658 .next()
1659 .map(|idx: &NamespaceIdx| self.doc.namespaces.get(*idx))
1660 }
1661
1662 #[inline]
1663 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1664 self.namespaces
1665 .nth(n)
1666 .map(|idx: &NamespaceIdx| self.doc.namespaces.get(*idx))
1667 }
1668
1669 #[inline]
1670 fn size_hint(&self) -> (usize, Option<usize>) {
1671 self.namespaces.size_hint()
1672 }
1673}
1674
1675impl<'a, 'input> DoubleEndedIterator for NamespaceIter<'a, 'input> {
1676 #[inline]
1677 fn next_back(&mut self) -> Option<Self::Item> {
1678 self.namespaces
1679 .next()
1680 .map(|idx: &NamespaceIdx| self.doc.namespaces.get(*idx))
1681 }
1682}
1683
1684impl ExactSizeIterator for NamespaceIter<'_, '_> {}
1685
1686impl fmt::Debug for NamespaceIter<'_, '_> {
1687 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1688 f&mut DebugStruct<'_, '_>.debug_struct("NamespaceIter")
1689 .field(name:"namespaces", &self.namespaces)
1690 .finish()
1691 }
1692}
1693