1use super::context::XPathContext;
7use super::error::XPathError;
8use super::iterator::{XmlItemRef, XmlNodeIterator};
9use super::node_test::NodeTest;
10use super::{DomNavigator, DomNodeType, NamespaceAxisScope};
11
12use crate::types::ItemType;
13
14fn move_to_next_document_order<N: DomNavigator>(nav: &mut N) -> bool {
15 if nav.move_to_first_child() {
16 return true;
17 }
18 if nav.move_to_next_sibling() {
19 return true;
20 }
21 while nav.move_to_parent() {
22 if nav.move_to_next_sibling() {
23 return true;
24 }
25 }
26 false
27}
28
29fn move_to_next_kind<N: DomNavigator>(nav: &mut N, kind: DomNodeType) -> bool {
30 let mut cursor = nav.clone();
31 while cursor.move_to_next_sibling() {
32 if kind == DomNodeType::All || cursor.node_type() == kind {
33 nav.move_to(&cursor);
34 return true;
35 }
36 }
37 false
38}
39
40fn move_to_first_kind<N: DomNavigator>(nav: &mut N, kind: DomNodeType) -> bool {
41 if kind == DomNodeType::All {
42 nav.move_to_first_child()
43 } else {
44 nav.move_to_child_kind(kind)
45 }
46}
47
48fn move_to_next_kind_or_sibling<N: DomNavigator>(nav: &mut N, kind: DomNodeType) -> bool {
49 if kind == DomNodeType::All {
50 nav.move_to_next_sibling()
51 } else {
52 move_to_next_kind(nav, kind)
53 }
54}
55
56fn node_test_kind(node_test: &Option<NodeTest>) -> DomNodeType {
57 match node_test {
58 None => DomNodeType::All,
59 Some(NodeTest::Name(_)) => DomNodeType::Element,
60 Some(NodeTest::Type(seq)) => match &seq.item_type {
61 ItemType::AnyItem | ItemType::AnyNode => DomNodeType::All,
62 ItemType::Document(_) => DomNodeType::Root,
63 ItemType::Element(_, _) | ItemType::SchemaElement(_) => DomNodeType::Element,
64 ItemType::Attribute(_, _) | ItemType::SchemaAttribute(_) => DomNodeType::Attribute,
65 ItemType::NamespaceNode => DomNodeType::Namespace,
66 ItemType::Text => DomNodeType::Text,
67 ItemType::Comment => DomNodeType::Comment,
68 ItemType::ProcessingInstruction(_) => DomNodeType::ProcessingInstruction,
69 ItemType::AtomicType(_) | ItemType::SchemaAtomicType(_) => DomNodeType::All,
70 },
71 }
72}
73
74fn descendant_element_kind(node_test: &Option<NodeTest>) -> DomNodeType {
75 match node_test {
76 Some(NodeTest::Name(_)) => DomNodeType::Element,
77 Some(NodeTest::Type(seq)) => match &seq.item_type {
78 ItemType::Element(_, _) | ItemType::SchemaElement(_) => DomNodeType::Element,
79 _ => DomNodeType::All,
80 },
81 None => DomNodeType::All,
82 }
83}
84
85#[derive(Clone)]
86struct AxisNodeIteratorBase<'a, I: XmlNodeIterator> {
87 context: XPathContext<'a>,
88 node_test: Option<NodeTest>,
89 match_self: bool,
90 iter: I,
91 curr: Option<I::Navigator>,
92 sequential_position: usize,
93 accept: bool,
94}
95
96impl<'a, I: XmlNodeIterator> AxisNodeIteratorBase<'a, I> {
97 fn new(
98 context: XPathContext<'a>,
99 node_test: Option<NodeTest>,
100 match_self: bool,
101 iter: I,
102 ) -> Self {
103 Self {
104 context,
105 node_test,
106 match_self,
107 iter,
108 curr: None,
109 sequential_position: 0,
110 accept: false,
111 }
112 }
113
114 fn test_item(&self, nav: &I::Navigator) -> bool {
115 match &self.node_test {
116 Some(test) => test.matches(nav, &self.context),
117 None => true,
118 }
119 }
120
121 fn move_next_iter(&mut self) -> Result<bool, XPathError> {
122 if !self.iter.move_next()? {
123 return Ok(false);
124 }
125
126 let item = match self.iter.current() {
127 Some(item) => item,
128 None => return Ok(false),
129 };
130
131 let nav = match item {
132 XmlItemRef::Node(node) => node.clone(),
133 XmlItemRef::Atomic(_) => return Err(XPathError::XPTY0019),
134 };
135
136 self.curr = Some(nav);
137 self.sequential_position = 0;
138 self.accept = true;
139 Ok(true)
140 }
141}
142
143pub trait AxisTraversal<N: DomNavigator>: Clone {
144 fn move_to_first(&self, nav: &mut N) -> bool;
145 fn move_to_next(&self, nav: &mut N) -> bool;
146}
147
148#[derive(Debug, Clone, Copy, Default)]
149pub struct SelfAxis;
150
151impl<N: DomNavigator> AxisTraversal<N> for SelfAxis {
152 fn move_to_first(&self, _nav: &mut N) -> bool {
153 true
154 }
155
156 fn move_to_next(&self, _nav: &mut N) -> bool {
157 false
158 }
159}
160
161#[derive(Debug, Clone, Copy, Default)]
162pub struct ParentAxis;
163
164impl<N: DomNavigator> AxisTraversal<N> for ParentAxis {
165 fn move_to_first(&self, nav: &mut N) -> bool {
166 nav.move_to_parent()
167 }
168
169 fn move_to_next(&self, _nav: &mut N) -> bool {
170 false
171 }
172}
173
174#[derive(Debug, Clone, Copy, Default)]
175pub struct AncestorAxis;
176
177impl<N: DomNavigator> AxisTraversal<N> for AncestorAxis {
178 fn move_to_first(&self, nav: &mut N) -> bool {
179 nav.move_to_parent()
180 }
181
182 fn move_to_next(&self, nav: &mut N) -> bool {
183 nav.move_to_parent()
184 }
185}
186
187#[derive(Debug, Clone, Copy, Default)]
188pub struct ChildAxis;
189
190impl<N: DomNavigator> AxisTraversal<N> for ChildAxis {
191 fn move_to_first(&self, nav: &mut N) -> bool {
192 nav.move_to_first_child()
193 }
194
195 fn move_to_next(&self, nav: &mut N) -> bool {
196 nav.move_to_next_sibling()
197 }
198}
199
200#[derive(Debug, Clone, Copy, Default)]
201pub struct AttributeAxis;
202
203impl<N: DomNavigator> AxisTraversal<N> for AttributeAxis {
204 fn move_to_first(&self, nav: &mut N) -> bool {
205 nav.move_to_first_attribute()
206 }
207
208 fn move_to_next(&self, nav: &mut N) -> bool {
209 nav.move_to_next_attribute()
210 }
211}
212
213#[derive(Debug, Clone, Copy)]
214pub struct NamespaceAxis {
215 scope: NamespaceAxisScope,
216}
217
218impl NamespaceAxis {
219 pub fn new(scope: NamespaceAxisScope) -> Self {
220 Self { scope }
221 }
222}
223
224impl Default for NamespaceAxis {
225 fn default() -> Self {
226 Self {
227 scope: NamespaceAxisScope::All,
228 }
229 }
230}
231
232impl<N: DomNavigator> AxisTraversal<N> for NamespaceAxis {
233 fn move_to_first(&self, nav: &mut N) -> bool {
234 nav.move_to_first_namespace(self.scope)
235 }
236
237 fn move_to_next(&self, nav: &mut N) -> bool {
238 nav.move_to_next_namespace(self.scope)
239 }
240}
241
242#[derive(Debug, Clone, Copy, Default)]
243pub struct FollowingSiblingAxis;
244
245impl<N: DomNavigator> AxisTraversal<N> for FollowingSiblingAxis {
246 fn move_to_first(&self, nav: &mut N) -> bool {
247 nav.move_to_next_sibling()
248 }
249
250 fn move_to_next(&self, nav: &mut N) -> bool {
251 nav.move_to_next_sibling()
252 }
253}
254
255#[derive(Debug, Clone, Copy, Default)]
256pub struct PrecedingSiblingAxis;
257
258impl<N: DomNavigator> AxisTraversal<N> for PrecedingSiblingAxis {
259 fn move_to_first(&self, nav: &mut N) -> bool {
260 nav.move_to_prev_sibling()
261 }
262
263 fn move_to_next(&self, nav: &mut N) -> bool {
264 nav.move_to_prev_sibling()
265 }
266}
267
268#[derive(Clone)]
269pub struct SequentialAxisNodeIterator<'a, I, A>
270where
271 I: XmlNodeIterator,
272 A: AxisTraversal<I::Navigator>,
273{
274 base: AxisNodeIteratorBase<'a, I>,
275 axis: A,
276 first: bool,
277 index: Option<usize>,
278}
279
280impl<'a, I, A> SequentialAxisNodeIterator<'a, I, A>
281where
282 I: XmlNodeIterator,
283 A: AxisTraversal<I::Navigator>,
284{
285 pub fn new(
286 context: XPathContext<'a>,
287 node_test: Option<NodeTest>,
288 match_self: bool,
289 iter: I,
290 axis: A,
291 ) -> Self {
292 Self {
293 base: AxisNodeIteratorBase::new(context, node_test, match_self, iter),
294 axis,
295 first: false,
296 index: None,
297 }
298 }
299
300 fn next_item(&mut self) -> Result<bool, XPathError> {
301 loop {
302 if !self.base.accept {
303 if !self.base.move_next_iter()? {
304 return Ok(false);
305 }
306 self.first = true;
307 if self.base.match_self {
308 if let Some(curr) = self.base.curr.as_ref() {
309 if self.base.test_item(curr) {
310 self.base.sequential_position += 1;
311 return Ok(true);
312 }
313 }
314 }
315 }
316
317 let moved = if self.first {
318 self.first = false;
319 match self.base.curr.as_mut() {
320 Some(nav) => self.axis.move_to_first(nav),
321 None => false,
322 }
323 } else {
324 match self.base.curr.as_mut() {
325 Some(nav) => self.axis.move_to_next(nav),
326 None => false,
327 }
328 };
329
330 self.base.accept = moved;
331
332 if moved {
333 if let Some(curr) = self.base.curr.as_ref() {
334 if self.base.test_item(curr) {
335 self.base.sequential_position += 1;
336 return Ok(true);
337 }
338 }
339 }
340 }
341 }
342}
343
344impl<'a, I, A> XmlNodeIterator for SequentialAxisNodeIterator<'a, I, A>
345where
346 I: XmlNodeIterator,
347 A: AxisTraversal<I::Navigator>,
348{
349 type Navigator = I::Navigator;
350
351 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
352 self.base.curr.as_ref().map(XmlItemRef::Node)
353 }
354
355 fn current_position(&self) -> Option<usize> {
356 self.index
357 }
358
359 fn move_next(&mut self) -> Result<bool, XPathError> {
360 if self.next_item()? {
361 let next_index = match self.index {
362 None => 0,
363 Some(i) => i + 1,
364 };
365 self.index = Some(next_index);
366 Ok(true)
367 } else {
368 self.index = None;
369 self.base.curr = None;
370 Ok(false)
371 }
372 }
373
374 fn sequential_position(&self) -> Option<usize> {
375 self.current_position()
376 .map(|_| self.base.sequential_position)
377 }
378
379 fn reset_sequential_position(&mut self) {
380 self.base.accept = false;
381 }
382}
383
384#[derive(Debug, Clone, Copy)]
385pub struct SpecialChildAxis {
386 kind: DomNodeType,
387}
388
389impl SpecialChildAxis {
390 pub fn new(kind: DomNodeType) -> Self {
391 Self { kind }
392 }
393}
394
395impl<N: DomNavigator> AxisTraversal<N> for SpecialChildAxis {
396 fn move_to_first(&self, nav: &mut N) -> bool {
397 nav.move_to_child_kind(self.kind)
398 }
399
400 fn move_to_next(&self, nav: &mut N) -> bool {
401 move_to_next_kind(nav, self.kind)
402 }
403}
404
405#[derive(Clone)]
406pub struct SpecialChildNodeIterator<'a, I: XmlNodeIterator> {
407 inner: SequentialAxisNodeIterator<'a, I, SpecialChildAxis>,
408}
409
410impl<'a, I: XmlNodeIterator> SpecialChildNodeIterator<'a, I> {
411 pub fn new(context: XPathContext<'a>, node_test: Option<NodeTest>, iter: I) -> Self {
412 let kind = node_test_kind(&node_test);
413 let axis = SpecialChildAxis::new(kind);
414 Self {
415 inner: SequentialAxisNodeIterator::new(context, node_test, false, iter, axis),
416 }
417 }
418}
419
420impl<'a, I: XmlNodeIterator> XmlNodeIterator for SpecialChildNodeIterator<'a, I> {
421 type Navigator = I::Navigator;
422
423 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
424 self.inner.current()
425 }
426
427 fn current_position(&self) -> Option<usize> {
428 self.inner.current_position()
429 }
430
431 fn move_next(&mut self) -> Result<bool, XPathError> {
432 self.inner.move_next()
433 }
434
435 fn sequential_position(&self) -> Option<usize> {
436 self.inner.sequential_position()
437 }
438
439 fn reset_sequential_position(&mut self) {
440 self.inner.reset_sequential_position();
441 }
442}
443
444#[derive(Clone)]
445pub struct DescendantNodeIterator<'a, I: XmlNodeIterator> {
446 base: AxisNodeIteratorBase<'a, I>,
447 depth: usize,
448 index: Option<usize>,
449}
450
451impl<'a, I: XmlNodeIterator> DescendantNodeIterator<'a, I> {
452 pub fn new(
453 context: XPathContext<'a>,
454 node_test: Option<NodeTest>,
455 match_self: bool,
456 iter: I,
457 ) -> Self {
458 Self {
459 base: AxisNodeIteratorBase::new(context, node_test, match_self, iter),
460 depth: 0,
461 index: None,
462 }
463 }
464
465 fn next_item(&mut self) -> Result<bool, XPathError> {
466 loop {
467 if !self.base.accept {
468 if !self.base.move_next_iter()? {
469 return Ok(false);
470 }
471 if self.base.match_self {
472 if let Some(curr) = self.base.curr.as_ref() {
473 if self.base.test_item(curr) {
474 self.base.sequential_position += 1;
475 return Ok(true);
476 }
477 }
478 }
479 }
480
481 let moved_to_child = match self.base.curr.as_mut() {
482 Some(nav) => nav.move_to_first_child(),
483 None => false,
484 };
485
486 if moved_to_child {
487 self.depth += 1;
488 } else {
489 loop {
490 if self.depth == 0 {
491 self.base.accept = false;
492 break;
493 }
494 let moved_to_sibling = match self.base.curr.as_mut() {
495 Some(nav) => nav.move_to_next_sibling(),
496 None => false,
497 };
498 if moved_to_sibling {
499 break;
500 }
501 if let Some(nav) = self.base.curr.as_mut() {
502 nav.move_to_parent();
503 }
504 if self.depth > 0 {
505 self.depth -= 1;
506 }
507 }
508 if !self.base.accept {
509 continue;
510 }
511 }
512
513 if let Some(curr) = self.base.curr.as_ref() {
514 if self.base.test_item(curr) {
515 self.base.sequential_position += 1;
516 return Ok(true);
517 }
518 }
519 }
520 }
521}
522
523impl<'a, I: XmlNodeIterator> XmlNodeIterator for DescendantNodeIterator<'a, I> {
524 type Navigator = I::Navigator;
525
526 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
527 self.base.curr.as_ref().map(XmlItemRef::Node)
528 }
529
530 fn current_position(&self) -> Option<usize> {
531 self.index
532 }
533
534 fn move_next(&mut self) -> Result<bool, XPathError> {
535 if self.next_item()? {
536 let next_index = match self.index {
537 None => 0,
538 Some(i) => i + 1,
539 };
540 self.index = Some(next_index);
541 Ok(true)
542 } else {
543 self.index = None;
544 self.base.curr = None;
545 Ok(false)
546 }
547 }
548
549 fn sequential_position(&self) -> Option<usize> {
550 self.current_position()
551 .map(|_| self.base.sequential_position)
552 }
553
554 fn reset_sequential_position(&mut self) {
555 self.base.accept = false;
556 }
557}
558
559#[derive(Clone)]
560pub struct SpecialDescendantNodeIterator<'a, I: XmlNodeIterator> {
561 base: AxisNodeIteratorBase<'a, I>,
562 kind: DomNodeType,
563 depth: usize,
564 index: Option<usize>,
565}
566
567impl<'a, I: XmlNodeIterator> SpecialDescendantNodeIterator<'a, I> {
568 pub fn new(
569 context: XPathContext<'a>,
570 node_test: Option<NodeTest>,
571 match_self: bool,
572 iter: I,
573 ) -> Self {
574 let kind = descendant_element_kind(&node_test);
575 Self {
576 base: AxisNodeIteratorBase::new(context, node_test, match_self, iter),
577 kind,
578 depth: 0,
579 index: None,
580 }
581 }
582
583 fn next_item(&mut self) -> Result<bool, XPathError> {
584 loop {
585 if !self.base.accept {
586 if !self.base.move_next_iter()? {
587 return Ok(false);
588 }
589 self.depth = 0;
590 if self.base.match_self {
591 if let Some(curr) = self.base.curr.as_ref() {
592 if self.base.test_item(curr) {
593 self.base.sequential_position += 1;
594 return Ok(true);
595 }
596 }
597 }
598 }
599
600 let kind = self.kind;
601 let moved_to_child = match self.base.curr.as_mut() {
602 Some(nav) => move_to_first_kind(nav, kind),
603 None => false,
604 };
605
606 if moved_to_child {
607 self.depth += 1;
608 } else {
609 loop {
610 if self.depth == 0 {
611 self.base.accept = false;
612 break;
613 }
614 let moved_to_next = match self.base.curr.as_mut() {
615 Some(nav) => move_to_next_kind_or_sibling(nav, kind),
616 None => false,
617 };
618 if moved_to_next {
619 break;
620 }
621 if let Some(nav) = self.base.curr.as_mut() {
622 nav.move_to_parent();
623 }
624 if self.depth > 0 {
625 self.depth -= 1;
626 }
627 }
628 if !self.base.accept {
629 continue;
630 }
631 }
632
633 if let Some(curr) = self.base.curr.as_ref() {
634 if self.base.test_item(curr) {
635 self.base.sequential_position += 1;
636 return Ok(true);
637 }
638 }
639 }
640 }
641}
642
643impl<'a, I: XmlNodeIterator> XmlNodeIterator for SpecialDescendantNodeIterator<'a, I> {
644 type Navigator = I::Navigator;
645
646 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
647 self.base.curr.as_ref().map(XmlItemRef::Node)
648 }
649
650 fn current_position(&self) -> Option<usize> {
651 self.index
652 }
653
654 fn move_next(&mut self) -> Result<bool, XPathError> {
655 if self.next_item()? {
656 let next_index = match self.index {
657 None => 0,
658 Some(i) => i + 1,
659 };
660 self.index = Some(next_index);
661 Ok(true)
662 } else {
663 self.index = None;
664 self.base.curr = None;
665 Ok(false)
666 }
667 }
668
669 fn sequential_position(&self) -> Option<usize> {
670 self.current_position()
671 .map(|_| self.base.sequential_position)
672 }
673
674 fn reset_sequential_position(&mut self) {
675 self.base.accept = false;
676 }
677}
678
679#[derive(Clone)]
680pub struct ChildOverDescendantsNodeIterator<'a, I: XmlNodeIterator> {
681 context: XPathContext<'a>,
682 node_tests: Vec<NodeTest>,
683 last_test: NodeTest,
684 iter: I,
685 curr: Option<I::Navigator>,
686 kind: DomNodeType,
687 depth: usize,
688 accept: bool,
689 sequential_position: usize,
690 index: Option<usize>,
691}
692
693impl<'a, I: XmlNodeIterator> ChildOverDescendantsNodeIterator<'a, I> {
694 pub fn new(context: XPathContext<'a>, node_tests: Vec<NodeTest>, iter: I) -> Self {
695 let last_test = node_tests
696 .last()
697 .expect("ChildOverDescendants requires at least one NodeTest")
698 .clone();
699 let kind = descendant_element_kind(&Some(last_test.clone()));
700 Self {
701 context,
702 node_tests,
703 last_test,
704 iter,
705 curr: None,
706 kind,
707 depth: 0,
708 accept: false,
709 sequential_position: 0,
710 index: None,
711 }
712 }
713
714 fn test_item(&self, nav: &I::Navigator, test: &NodeTest) -> bool {
715 test.matches(nav, &self.context)
716 }
717
718 fn next_item(&mut self) -> Result<bool, XPathError> {
719 loop {
720 if !self.accept {
721 if !self.iter.move_next()? {
722 return Ok(false);
723 }
724 let item = match self.iter.current() {
725 Some(item) => item,
726 None => return Ok(false),
727 };
728 let nav = match item {
729 XmlItemRef::Node(node) => node.clone(),
730 XmlItemRef::Atomic(_) => return Err(XPathError::XPTY0019),
731 };
732 self.curr = Some(nav);
733 self.depth = 0;
734 self.sequential_position = 0;
735 self.accept = true;
736 }
737
738 let kind = self.kind;
739 let moved_to_child = match self.curr.as_mut() {
740 Some(nav) => move_to_first_kind(nav, kind),
741 None => false,
742 };
743 if moved_to_child {
744 self.depth += 1;
745 } else {
746 loop {
747 if self.depth == 0 {
748 self.accept = false;
749 break;
750 }
751 let moved_to_next = match self.curr.as_mut() {
752 Some(nav) => move_to_next_kind_or_sibling(nav, kind),
753 None => false,
754 };
755 if moved_to_next {
756 break;
757 }
758 if let Some(nav) = self.curr.as_mut() {
759 nav.move_to_parent();
760 }
761 if self.depth > 0 {
762 self.depth -= 1;
763 }
764 }
765 if !self.accept {
766 continue;
767 }
768 }
769
770 let curr = match self.curr.as_ref() {
771 Some(curr) => curr,
772 None => continue,
773 };
774
775 if self.depth < self.node_tests.len() || !self.test_item(curr, &self.last_test) {
776 continue;
777 }
778
779 let mut nav = curr.clone();
780 let mut matched = true;
781 for test in self.node_tests[..self.node_tests.len() - 1].iter().rev() {
782 if !(nav.move_to_parent() && self.test_item(&nav, test)) {
783 matched = false;
784 break;
785 }
786 }
787 if !matched {
788 continue;
789 }
790 self.sequential_position += 1;
791 return Ok(true);
792 }
793 }
794}
795
796impl<'a, I: XmlNodeIterator> XmlNodeIterator for ChildOverDescendantsNodeIterator<'a, I> {
797 type Navigator = I::Navigator;
798
799 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
800 self.curr.as_ref().map(XmlItemRef::Node)
801 }
802
803 fn current_position(&self) -> Option<usize> {
804 self.index
805 }
806
807 fn move_next(&mut self) -> Result<bool, XPathError> {
808 if self.next_item()? {
809 let next_index = match self.index {
810 None => 0,
811 Some(i) => i + 1,
812 };
813 self.index = Some(next_index);
814 Ok(true)
815 } else {
816 self.index = None;
817 self.curr = None;
818 Ok(false)
819 }
820 }
821
822 fn sequential_position(&self) -> Option<usize> {
823 self.current_position().map(|_| self.sequential_position)
824 }
825
826 fn reset_sequential_position(&mut self) {
827 self.accept = false;
828 }
829}
830
831#[derive(Clone)]
832pub struct FollowingNodeIterator<'a, I: XmlNodeIterator> {
833 base: AxisNodeIteratorBase<'a, I>,
834 kind: DomNodeType,
835 index: Option<usize>,
836}
837
838impl<'a, I: XmlNodeIterator> FollowingNodeIterator<'a, I> {
839 pub fn new(context: XPathContext<'a>, node_test: Option<NodeTest>, iter: I) -> Self {
840 let kind = node_test_kind(&node_test);
841 Self {
842 base: AxisNodeIteratorBase::new(context, node_test, false, iter),
843 kind,
844 index: None,
845 }
846 }
847
848 fn next_item(&mut self) -> Result<bool, XPathError> {
849 loop {
850 if !self.base.accept && !self.base.move_next_iter()? {
851 return Ok(false);
852 }
853
854 let moved = match self.base.curr.as_mut() {
855 Some(nav) => nav.move_to_following(self.kind, None),
856 None => false,
857 };
858 self.base.accept = moved;
859 if moved {
860 if let Some(curr) = self.base.curr.as_ref() {
861 if self.base.test_item(curr) {
862 self.base.sequential_position += 1;
863 return Ok(true);
864 }
865 }
866 }
867 }
868 }
869}
870
871impl<'a, I: XmlNodeIterator> XmlNodeIterator for FollowingNodeIterator<'a, I> {
872 type Navigator = I::Navigator;
873
874 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
875 self.base.curr.as_ref().map(XmlItemRef::Node)
876 }
877
878 fn current_position(&self) -> Option<usize> {
879 self.index
880 }
881
882 fn move_next(&mut self) -> Result<bool, XPathError> {
883 if self.next_item()? {
884 let next_index = match self.index {
885 None => 0,
886 Some(i) => i + 1,
887 };
888 self.index = Some(next_index);
889 Ok(true)
890 } else {
891 self.index = None;
892 self.base.curr = None;
893 Ok(false)
894 }
895 }
896
897 fn sequential_position(&self) -> Option<usize> {
898 self.current_position()
899 .map(|_| self.base.sequential_position)
900 }
901
902 fn reset_sequential_position(&mut self) {
903 self.base.accept = false;
904 }
905}
906
907#[derive(Clone)]
908pub struct PrecedingNodeIterator<'a, I: XmlNodeIterator> {
909 base: AxisNodeIteratorBase<'a, I>,
910 kind: DomNodeType,
911 anchor: Option<I::Navigator>,
912 ancestors: Vec<I::Navigator>,
913 started: bool,
914 index: Option<usize>,
915}
916
917impl<'a, I: XmlNodeIterator> PrecedingNodeIterator<'a, I> {
918 pub fn new(context: XPathContext<'a>, node_test: Option<NodeTest>, iter: I) -> Self {
919 let kind = node_test_kind(&node_test);
920 Self {
921 base: AxisNodeIteratorBase::new(context, node_test, false, iter),
922 kind,
923 anchor: None,
924 ancestors: Vec::new(),
925 started: false,
926 index: None,
927 }
928 }
929
930 fn collect_ancestors(&mut self, anchor: &I::Navigator) {
931 self.ancestors.clear();
932 let mut cursor = anchor.clone();
933 while cursor.move_to_parent() {
934 self.ancestors.push(cursor.clone());
935 }
936 }
937
938 fn is_ancestor(&self, nav: &I::Navigator) -> bool {
939 self.ancestors
940 .iter()
941 .any(|ancestor| nav.is_same_position(ancestor))
942 }
943
944 fn next_item(&mut self) -> Result<bool, XPathError> {
945 loop {
946 if !self.base.accept {
947 if !self.base.move_next_iter()? {
948 return Ok(false);
949 }
950 let mut anchor = match self.base.curr.as_ref() {
951 Some(nav) => nav.clone(),
952 None => return Ok(false),
953 };
954 if matches!(
955 anchor.node_type(),
956 DomNodeType::Attribute | DomNodeType::Namespace
957 ) {
958 anchor.move_to_parent();
959 }
960 self.anchor = Some(anchor.clone());
961 self.collect_ancestors(&anchor);
962 if let Some(curr) = self.base.curr.as_mut() {
963 curr.move_to_visible_root();
970 }
971 self.started = false;
972 }
973
974 let moved = match self.base.curr.as_mut() {
975 Some(curr) => {
976 if self.started {
977 move_to_next_document_order(curr)
978 } else {
979 self.started = true;
980 curr.move_to_first_child()
981 }
982 }
983 None => false,
984 };
985 if !moved {
986 self.base.accept = false;
987 continue;
988 }
989 let curr = match self.base.curr.as_ref() {
990 Some(curr) => curr,
991 None => {
992 self.base.accept = false;
993 continue;
994 }
995 };
996 if let Some(anchor) = self.anchor.as_ref() {
997 if curr.is_same_position(anchor) {
998 self.base.accept = false;
999 continue;
1000 }
1001 }
1002 if self.kind != DomNodeType::All && curr.node_type() != self.kind {
1003 continue;
1004 }
1005 if self.is_ancestor(curr) {
1006 continue;
1007 }
1008 if self.base.test_item(curr) {
1009 self.base.sequential_position += 1;
1010 return Ok(true);
1011 }
1012 }
1013 }
1014}
1015
1016impl<'a, I: XmlNodeIterator> XmlNodeIterator for PrecedingNodeIterator<'a, I> {
1017 type Navigator = I::Navigator;
1018
1019 fn current(&self) -> Option<XmlItemRef<'_, Self::Navigator>> {
1020 self.base.curr.as_ref().map(XmlItemRef::Node)
1021 }
1022
1023 fn current_position(&self) -> Option<usize> {
1024 self.index
1025 }
1026
1027 fn move_next(&mut self) -> Result<bool, XPathError> {
1028 if self.next_item()? {
1029 let next_index = match self.index {
1030 None => 0,
1031 Some(i) => i + 1,
1032 };
1033 self.index = Some(next_index);
1034 Ok(true)
1035 } else {
1036 self.index = None;
1037 self.base.curr = None;
1038 Ok(false)
1039 }
1040 }
1041
1042 fn sequential_position(&self) -> Option<usize> {
1043 self.current_position()
1044 .map(|_| self.base.sequential_position)
1045 }
1046
1047 fn reset_sequential_position(&mut self) {
1048 self.base.accept = false;
1049 }
1050}
1051
1052#[cfg(test)]
1053mod tests {
1054 use super::*;
1055
1056 use crate::namespace::table::NameTable;
1057 use crate::navigator::RoXmlNavigator;
1058 use crate::types::{ItemType, NameTest, SequenceType};
1059 use crate::xpath::iterator::{VecNodeIterator, XmlItem};
1060
1061 fn collect_local_names<N: DomNavigator>(
1062 iter: &mut impl XmlNodeIterator<Navigator = N>,
1063 ) -> Vec<String> {
1064 let mut names = Vec::new();
1065 while iter.move_next().unwrap() {
1066 match iter.current() {
1067 Some(XmlItemRef::Node(node)) => names.push(node.local_name().to_string()),
1068 _ => panic!("expected node item"),
1069 }
1070 }
1071 names
1072 }
1073
1074 #[test]
1075 fn test_self_axis() {
1076 let doc = roxmltree::Document::parse("<root><child/></root>").expect("parse xml");
1077 let mut nav = RoXmlNavigator::new(&doc);
1078 nav.move_to_first_child();
1079
1080 let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1081 let table = NameTable::new();
1082 let ctx = XPathContext::new(&table);
1083 let mut iter = SequentialAxisNodeIterator::new(
1084 ctx,
1085 Some(NodeTest::Type(SequenceType::node())),
1086 false,
1087 base,
1088 SelfAxis,
1089 );
1090
1091 assert!(iter.move_next().unwrap());
1092 match iter.current() {
1093 Some(XmlItemRef::Node(node)) => assert_eq!(node.local_name(), "root"),
1094 _ => panic!("expected node"),
1095 }
1096 assert_eq!(iter.current_position(), Some(0));
1097 assert_eq!(iter.sequential_position(), Some(1));
1098 assert!(!iter.move_next().unwrap());
1099 }
1100
1101 #[test]
1102 fn test_parent_axis() {
1103 let doc = roxmltree::Document::parse("<root><child/></root>").expect("parse xml");
1104 let mut nav = RoXmlNavigator::new(&doc);
1105 nav.move_to_first_child();
1106 nav.move_to_first_child();
1107
1108 let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1109 let table = NameTable::new();
1110 let ctx = XPathContext::new(&table);
1111 let mut iter = SequentialAxisNodeIterator::new(
1112 ctx,
1113 Some(NodeTest::Type(SequenceType::node())),
1114 false,
1115 base,
1116 ParentAxis,
1117 );
1118
1119 assert!(iter.move_next().unwrap());
1120 match iter.current() {
1121 Some(XmlItemRef::Node(node)) => assert_eq!(node.local_name(), "root"),
1122 _ => panic!("expected node"),
1123 }
1124 assert!(!iter.move_next().unwrap());
1125 }
1126
1127 #[test]
1128 fn test_child_axis() {
1129 let doc = roxmltree::Document::parse("<root><a/><b/></root>").expect("parse xml");
1130 let mut nav = RoXmlNavigator::new(&doc);
1131 nav.move_to_first_child();
1132
1133 let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1134 let table = NameTable::new();
1135 let ctx = XPathContext::new(&table);
1136 let mut iter = SequentialAxisNodeIterator::new(
1137 ctx,
1138 Some(NodeTest::Name(NameTest::Wildcard)),
1139 false,
1140 base,
1141 ChildAxis,
1142 );
1143
1144 let names = collect_local_names(&mut iter);
1145 assert_eq!(names, vec!["a".to_string(), "b".to_string()]);
1146 }
1147
1148 #[test]
1149 fn test_attribute_axis() {
1150 let doc = roxmltree::Document::parse("<root a=\"1\" b=\"2\"/>").expect("parse xml");
1151 let mut nav = RoXmlNavigator::new(&doc);
1152 nav.move_to_first_child();
1153
1154 let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1155 let table = NameTable::new();
1156 let ctx = XPathContext::new(&table);
1157 let mut iter = SequentialAxisNodeIterator::new(
1158 ctx,
1159 Some(NodeTest::Name(NameTest::Wildcard)),
1160 false,
1161 base,
1162 AttributeAxis,
1163 );
1164
1165 let mut names = collect_local_names(&mut iter);
1166 names.sort();
1167 assert_eq!(names, vec!["a".to_string(), "b".to_string()]);
1168 }
1169
1170 #[test]
1171 fn test_following_sibling_axis() {
1172 let doc = roxmltree::Document::parse("<root><a/><b/><c/></root>").expect("parse xml");
1173 let mut nav = RoXmlNavigator::new(&doc);
1174 nav.move_to_first_child(); nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1178 let table = NameTable::new();
1179 let ctx = XPathContext::new(&table);
1180 let mut iter = SequentialAxisNodeIterator::new(
1181 ctx,
1182 Some(NodeTest::Name(NameTest::Wildcard)),
1183 false,
1184 base,
1185 FollowingSiblingAxis,
1186 );
1187
1188 let names = collect_local_names(&mut iter);
1189 assert_eq!(names, vec!["b".to_string(), "c".to_string()]);
1190 }
1191
1192 #[test]
1193 fn test_preceding_sibling_axis() {
1194 let doc = roxmltree::Document::parse("<root><a/><b/><c/></root>").expect("parse xml");
1195 let mut nav = RoXmlNavigator::new(&doc);
1196 nav.move_to_first_child(); nav.move_to_first_child(); nav.move_to_next_sibling(); nav.move_to_next_sibling(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1202 let table = NameTable::new();
1203 let ctx = XPathContext::new(&table);
1204 let mut iter = SequentialAxisNodeIterator::new(
1205 ctx,
1206 Some(NodeTest::Name(NameTest::Wildcard)),
1207 false,
1208 base,
1209 PrecedingSiblingAxis,
1210 );
1211
1212 let names = collect_local_names(&mut iter);
1213 assert_eq!(names, vec!["b".to_string(), "a".to_string()]);
1214 }
1215
1216 #[test]
1217 fn test_ancestor_axis() {
1218 let doc = roxmltree::Document::parse("<root><a><b/></a></root>").expect("parse xml");
1219 let mut nav = RoXmlNavigator::new(&doc);
1220 nav.move_to_first_child(); nav.move_to_first_child(); nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1225 let table = NameTable::new();
1226 let ctx = XPathContext::new(&table);
1227 let mut iter = SequentialAxisNodeIterator::new(
1228 ctx,
1229 Some(NodeTest::Name(NameTest::Wildcard)),
1230 false,
1231 base,
1232 AncestorAxis,
1233 );
1234
1235 let names = collect_local_names(&mut iter);
1236 assert_eq!(names, vec!["a".to_string(), "root".to_string()]);
1237 }
1238
1239 #[test]
1240 fn test_namespace_axis() {
1241 let doc = roxmltree::Document::parse(
1242 r#"<root xmlns="urn:default" xmlns:p="urn:test"><p:child/></root>"#,
1243 )
1244 .expect("parse xml");
1245 let mut nav = RoXmlNavigator::new(&doc);
1246 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1249 let table = NameTable::new();
1250 let ctx = XPathContext::new(&table);
1251 let mut iter = SequentialAxisNodeIterator::new(
1252 ctx,
1253 Some(NodeTest::Type(SequenceType::one(ItemType::NamespaceNode))),
1254 false,
1255 base,
1256 NamespaceAxis::new(NamespaceAxisScope::Local),
1257 );
1258
1259 let names = collect_local_names(&mut iter);
1260 assert!(names.contains(&"".to_string()));
1261 assert!(names.contains(&"p".to_string()));
1262 }
1263
1264 #[test]
1265 fn test_descendant_axis() {
1266 let doc =
1267 roxmltree::Document::parse("<root><a><b/><c/></a><d/></root>").expect("parse xml");
1268 let mut nav = RoXmlNavigator::new(&doc);
1269 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1272 let table = NameTable::new();
1273 let ctx = XPathContext::new(&table);
1274 let mut iter =
1275 DescendantNodeIterator::new(ctx, Some(NodeTest::Name(NameTest::Wildcard)), false, base);
1276
1277 let names = collect_local_names(&mut iter);
1278 assert_eq!(
1279 names,
1280 vec![
1281 "a".to_string(),
1282 "b".to_string(),
1283 "c".to_string(),
1284 "d".to_string()
1285 ]
1286 );
1287 }
1288
1289 #[test]
1290 fn test_descendant_or_self_axis() {
1291 let doc = roxmltree::Document::parse("<root><a/></root>").expect("parse xml");
1292 let mut nav = RoXmlNavigator::new(&doc);
1293 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1296 let table = NameTable::new();
1297 let ctx = XPathContext::new(&table);
1298 let mut iter =
1299 DescendantNodeIterator::new(ctx, Some(NodeTest::Name(NameTest::Wildcard)), true, base);
1300
1301 let names = collect_local_names(&mut iter);
1302 assert_eq!(names, vec!["root".to_string(), "a".to_string()]);
1303 }
1304
1305 #[test]
1306 fn test_following_axis() {
1307 let doc =
1308 roxmltree::Document::parse("<root><a><b/><c/></a><d/></root>").expect("parse xml");
1309 let mut nav = RoXmlNavigator::new(&doc);
1310 nav.move_to_first_child(); nav.move_to_first_child(); nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1315 let table = NameTable::new();
1316 let ctx = XPathContext::new(&table);
1317 let mut iter =
1318 FollowingNodeIterator::new(ctx, Some(NodeTest::Name(NameTest::Wildcard)), base);
1319
1320 let names = collect_local_names(&mut iter);
1321 assert_eq!(names, vec!["c".to_string(), "d".to_string()]);
1322 }
1323
1324 #[test]
1325 fn test_preceding_axis() {
1326 let doc =
1327 roxmltree::Document::parse("<root><a><b/><c/></a><d/></root>").expect("parse xml");
1328 let mut nav = RoXmlNavigator::new(&doc);
1329 nav.move_to_first_child(); nav.move_to_first_child(); nav.move_to_first_child(); nav.move_to_next_sibling(); nav.move_to_parent(); nav.move_to_next_sibling(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1337 let table = NameTable::new();
1338 let ctx = XPathContext::new(&table);
1339 let mut iter =
1340 PrecedingNodeIterator::new(ctx, Some(NodeTest::Name(NameTest::Wildcard)), base);
1341
1342 let names = collect_local_names(&mut iter);
1343 assert_eq!(
1344 names,
1345 vec!["a".to_string(), "b".to_string(), "c".to_string()]
1346 );
1347 }
1348
1349 #[test]
1350 fn test_special_child_axis() {
1351 let doc = roxmltree::Document::parse("<root>text<a/><b/></root>").expect("parse xml");
1352 let mut nav = RoXmlNavigator::new(&doc);
1353 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1356 let table = NameTable::new();
1357 let ctx = XPathContext::new(&table);
1358 let mut iter =
1359 SpecialChildNodeIterator::new(ctx, Some(NodeTest::Name(NameTest::Wildcard)), base);
1360
1361 let names = collect_local_names(&mut iter);
1362 assert_eq!(names, vec!["a".to_string(), "b".to_string()]);
1363 }
1364
1365 #[test]
1366 fn test_special_descendant_axis() {
1367 let doc = roxmltree::Document::parse("<root>text<a><b/></a></root>").expect("parse xml");
1368 let mut nav = RoXmlNavigator::new(&doc);
1369 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1372 let table = NameTable::new();
1373 let ctx = XPathContext::new(&table);
1374 let mut iter = SpecialDescendantNodeIterator::new(
1375 ctx,
1376 Some(NodeTest::Name(NameTest::Wildcard)),
1377 false,
1378 base,
1379 );
1380
1381 let names = collect_local_names(&mut iter);
1382 assert_eq!(names, vec!["a".to_string(), "b".to_string()]);
1383 }
1384
1385 #[test]
1386 fn test_child_over_descendants() {
1387 let doc = roxmltree::Document::parse("<root><a><b><c/></b></a><x><b><c/></b></x></root>")
1388 .expect("parse xml");
1389 let mut nav = RoXmlNavigator::new(&doc);
1390 nav.move_to_first_child(); let base = VecNodeIterator::new(vec![XmlItem::Node(nav.clone())]);
1393 let table = NameTable::new();
1394 let a_id = table.add("a");
1396 let b_id = table.add("b");
1397 let c_id = table.add("c");
1398 let ctx = XPathContext::new(&table);
1399 let tests = vec![
1401 NodeTest::Name(NameTest::NamespaceWildcard(a_id)),
1402 NodeTest::Name(NameTest::NamespaceWildcard(b_id)),
1403 NodeTest::Name(NameTest::NamespaceWildcard(c_id)),
1404 ];
1405 let mut iter = ChildOverDescendantsNodeIterator::new(ctx, tests, base);
1406
1407 let names = collect_local_names(&mut iter);
1408 assert_eq!(names, vec!["c".to_string()]);
1409 }
1410}