1pub(crate) mod booleans;
41pub mod callable;
42pub(crate) mod construct;
43pub mod context;
44pub(crate) mod controlflow;
45pub(crate) mod datetime;
46pub(crate) mod functions;
47pub(crate) mod grouping;
48mod keys;
49pub(crate) mod logic;
50pub(crate) mod misc;
51pub(crate) mod navigate;
52pub mod numbers;
53pub(crate) mod strings;
54pub mod template;
55pub(crate) mod variables;
56
57#[allow(unused_imports)]
58use crate::item::Sequence;
59use crate::item::{Item, Node, NodeType, SequenceTrait};
60use crate::output::OutputSpec;
61use crate::pattern::Pattern;
62use crate::transform::callable::ActualParameters;
63use crate::transform::context::{Context, ContextBuilder, StaticContext};
64use crate::transform::numbers::Numbering;
65use crate::value::Operator;
66#[allow(unused_imports)]
67use crate::value::Value;
68use crate::xdmerror::{Error, ErrorKind};
69use qualname::{NamespaceDeclaration, NamespaceMap, NamespacePrefix, NamespaceUri, NcName, QName};
70use std::convert::TryFrom;
71use std::fmt;
72use std::fmt::{Debug, Formatter};
73use std::rc::Rc;
74use url::Url;
75
76#[derive(Clone)]
78pub enum Transform<N: Node> {
79 Root,
81 ContextItem,
83 CurrentItem,
85
86 Compose(Vec<Transform<N>>),
89 Step(NodeMatch),
91 StepPredicated(NodeMatch, Vec<Transform<N>>),
97 Filter(Box<Transform<N>>),
103
104 Empty,
106 Literal(Item<N>),
108 LiteralElement(QName, Box<Transform<N>>),
110 Element(Box<Transform<N>>, Box<Transform<N>>),
112 LiteralText(Box<Transform<N>>, OutputSpec),
114 LiteralAttribute(QName, Box<Transform<N>>),
117 LiteralComment(Box<Transform<N>>),
119 LiteralProcessingInstruction(Box<Transform<N>>, Box<Transform<N>>),
121 NamespaceDeclaration(
123 Option<Box<Transform<N>>>,
124 Box<Transform<N>>,
125 Box<Transform<N>>,
126 ),
127 SequenceItems(Vec<Transform<N>>),
129
130 Copy(Box<Transform<N>>, Box<Transform<N>>),
133 DeepCopy(Box<Transform<N>>),
135
136 Or(Vec<Transform<N>>),
138 And(Vec<Transform<N>>),
140
141 GeneralComparison(Operator, Box<Transform<N>>, Box<Transform<N>>),
144 ValueComparison(Operator, Box<Transform<N>>, Box<Transform<N>>),
147
148 Concat(Vec<Transform<N>>),
150 Range(Box<Transform<N>>, Box<Transform<N>>),
153 Arithmetic(Vec<ArithmeticOperand<N>>),
155
156 Loop(Vec<(String, Transform<N>)>, Box<Transform<N>>),
158 Switch(Vec<(Transform<N>, Transform<N>)>, Box<Transform<N>>),
160
161 ForEach(
163 Option<Grouping<N>>,
164 Box<Transform<N>>,
165 Box<Transform<N>>,
166 Vec<(Order, Transform<N>)>,
167 ),
168 ApplyTemplates(Box<Transform<N>>, Option<QName>, Vec<(Order, Transform<N>)>),
171 ApplyImports,
173 NextMatch,
174
175 Union(Vec<Transform<N>>),
177
178 Call(Box<Transform<N>>, Vec<Transform<N>>, Rc<NamespaceMap>),
181
182 VariableDeclaration(
185 String,
186 Box<Transform<N>>,
187 Box<Transform<N>>,
188 Rc<NamespaceMap>,
189 ),
190 VariableReference(String, Rc<NamespaceMap>),
193
194 SetAttribute(QName, Box<Transform<N>>),
197
198 Position,
200 Last,
201 Count(Box<Transform<N>>),
202 LocalName(Option<Box<Transform<N>>>),
203 Name(Option<Box<Transform<N>>>),
204 String(Box<Transform<N>>),
205 StartsWith(Box<Transform<N>>, Box<Transform<N>>),
206 EndsWith(Box<Transform<N>>, Box<Transform<N>>),
207 Contains(Box<Transform<N>>, Box<Transform<N>>),
208 Substring(
209 Box<Transform<N>>,
210 Box<Transform<N>>,
211 Option<Box<Transform<N>>>,
212 ),
213 SubstringBefore(Box<Transform<N>>, Box<Transform<N>>),
214 SubstringAfter(Box<Transform<N>>, Box<Transform<N>>),
215 NormalizeSpace(Option<Box<Transform<N>>>),
216 Translate(Box<Transform<N>>, Box<Transform<N>>, Box<Transform<N>>),
217 GenerateId(Option<Box<Transform<N>>>),
218 Boolean(Box<Transform<N>>),
219 Not(Box<Transform<N>>),
220 True,
221 False,
222 Number(Box<Transform<N>>),
223 Sum(Box<Transform<N>>),
224 Avg(Box<Transform<N>>),
225 Min(Box<Transform<N>>),
226 Max(Box<Transform<N>>),
227 Floor(Box<Transform<N>>),
228 Ceiling(Box<Transform<N>>),
229 Round(Box<Transform<N>>, Option<Box<Transform<N>>>),
230 CurrentDateTime,
231 CurrentDate,
232 CurrentTime,
233 FormatDateTime(
234 Box<Transform<N>>,
235 Box<Transform<N>>,
236 Option<Box<Transform<N>>>,
237 Option<Box<Transform<N>>>,
238 Option<Box<Transform<N>>>,
239 ),
240 FormatDate(
241 Box<Transform<N>>,
242 Box<Transform<N>>,
243 Option<Box<Transform<N>>>,
244 Option<Box<Transform<N>>>,
245 Option<Box<Transform<N>>>,
246 ),
247 FormatTime(
248 Box<Transform<N>>,
249 Box<Transform<N>>,
250 Option<Box<Transform<N>>>,
251 Option<Box<Transform<N>>>,
252 Option<Box<Transform<N>>>,
253 ),
254 FormatNumber(
255 Box<Transform<N>>,
256 Box<Transform<N>>,
257 Option<Box<Transform<N>>>,
258 ),
259 FormatInteger(Box<Transform<N>>, Box<Transform<N>>),
265 GenerateIntegers(Box<Transform<N>>, Box<Transform<N>>, Box<Numbering<N>>),
272 CurrentGroup,
273 CurrentGroupingKey,
274 Key(
278 Box<Transform<N>>,
279 Box<Transform<N>>,
280 Option<Box<Transform<N>>>,
281 Rc<NamespaceMap>,
282 ),
283 SystemProperty(Box<Transform<N>>, Rc<NamespaceMap>),
285 AvailableSystemProperties,
286 Document(Box<Transform<N>>, Option<Box<Transform<N>>>),
288
289 Invoke(QName, ActualParameters<N>, Rc<NamespaceMap>),
291
292 Message(
294 Box<Transform<N>>,
295 Option<Box<Transform<N>>>,
296 Box<Transform<N>>,
297 Box<Transform<N>>,
298 ),
299
300 NotImplemented(String),
303
304 Error(ErrorKind, String),
306}
307
308impl<N: Node> Debug for Transform<N> {
309 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
310 match self {
311 Transform::Root => write!(f, "root node"),
312 Transform::ContextItem => write!(f, "context item"),
313 Transform::CurrentItem => write!(f, "current item"),
314 Transform::SequenceItems(v) => write!(f, "Sequence of {} items", v.len()),
315 Transform::Compose(v) => {
316 write!(f, "Compose {} steps [", v.len()).expect("unable to format step");
317 v.iter().for_each(|s| {
318 s.fmt(f).expect("unable to format step");
319 write!(f, "; ").expect("unable to format step")
320 });
321 write!(f, "]")
322 }
323 Transform::Step(nm) => write!(f, "Step matching {}", nm),
324 Transform::StepPredicated(nm, p) => {
325 write!(f, "Step matching {} with {} predicate(s)", nm, p.len())
326 }
327 Transform::Filter(_) => write!(f, "Filter"),
328 Transform::Empty => write!(f, "Empty"),
329 Transform::Literal(_) => write!(f, "literal value"),
330 Transform::LiteralElement(qn, _) => write!(f, "literal element named \"{}\"", qn),
331 Transform::Element(_, _) => write!(f, "constructed element"),
332 Transform::LiteralText(_, b) => write!(f, "literal text (disable escaping {:?})", b),
333 Transform::LiteralAttribute(qn, _) => write!(f, "literal attribute named \"{}\"", qn),
334 Transform::LiteralComment(_) => write!(f, "literal comment"),
335 Transform::LiteralProcessingInstruction(_, _) => {
336 write!(f, "literal processing-instruction")
337 }
338 Transform::NamespaceDeclaration(_, _, _) => write!(f, "namespace declaration"),
339 Transform::Copy(_, _) => write!(f, "shallow copy"),
340 Transform::DeepCopy(_) => write!(f, "deep copy"),
341 Transform::GeneralComparison(o, v, u) => {
342 write!(f, "general comparison {} of {:?} and {:?}", o, v, u)
343 }
344 Transform::ValueComparison(o, v, u) => {
345 write!(f, "value comparison {} of {:?} and {:?}", o, v, u)
346 }
347 Transform::Concat(o) => write!(f, "Concatenate {} operands", o.len()),
348 Transform::Range(_, _) => write!(f, "range"),
349 Transform::Arithmetic(o) => write!(f, "Arithmetic {} operands", o.len()),
350 Transform::And(o) => write!(f, "AND {} operands", o.len()),
351 Transform::Or(o) => write!(f, "OR {} operands", o.len()),
352 Transform::Loop(_, _) => write!(f, "loop"),
353 Transform::Switch(c, _) => write!(f, "switch {} clauses", c.len()),
354 Transform::ForEach(_g, _, _, o) => write!(f, "for-each ({} sort keys)", o.len()),
355 Transform::Union(v) => {
356 write!(f, "union of {} operands", v.len()).ok();
357 v.iter().for_each(|o| {
358 write!(f, "\noperand: {:?}", o).ok();
359 });
360 Ok(())
361 }
362 Transform::ApplyTemplates(_, m, o) => {
363 write!(f, "Apply templates (mode {:?}, {} sort keys)", m, o.len())
364 }
365 Transform::Call(_, a, _) => write!(f, "Call transform with {} arguments", a.len()),
366 Transform::ApplyImports => write!(f, "Apply imports"),
367 Transform::NextMatch => write!(f, "next-match"),
368 Transform::VariableDeclaration(n, _, _, _) => write!(f, "declare variable \"{}\"", n),
369 Transform::VariableReference(n, _) => write!(f, "reference variable \"{}\"", n),
370 Transform::SetAttribute(n, _) => write!(f, "set attribute named \"{}\"", n),
371 Transform::Position => write!(f, "position"),
372 Transform::Last => write!(f, "last"),
373 Transform::Count(_s) => write!(f, "count()"),
374 Transform::Name(_n) => write!(f, "name()"),
375 Transform::LocalName(_n) => write!(f, "local-name()"),
376 Transform::String(s) => write!(f, "string({:?})", s),
377 Transform::StartsWith(s, t) => write!(f, "starts-with({:?}, {:?})", s, t),
378 Transform::EndsWith(s, t) => write!(f, "ends-with({:?}, {:?})", s, t),
379 Transform::Contains(s, t) => write!(f, "contains({:?}, {:?})", s, t),
380 Transform::Substring(s, t, _l) => write!(f, "substring({:?}, {:?}, ...)", s, t),
381 Transform::SubstringBefore(s, t) => write!(f, "substring-before({:?}, {:?})", s, t),
382 Transform::SubstringAfter(s, t) => write!(f, "substring-after({:?}, {:?})", s, t),
383 Transform::NormalizeSpace(_s) => write!(f, "normalize-space()"),
384 Transform::Translate(s, t, u) => write!(f, "translate({:?}, {:?}, {:?})", s, t, u),
385 Transform::GenerateId(_) => write!(f, "generate-id()"),
386 Transform::Boolean(b) => write!(f, "boolean({:?})", b),
387 Transform::Not(b) => write!(f, "not({:?})", b),
388 Transform::True => write!(f, "true"),
389 Transform::False => write!(f, "false"),
390 Transform::Number(n) => write!(f, "number({:?})", n),
391 Transform::Sum(n) => write!(f, "sum({:?})", n),
392 Transform::Avg(n) => write!(f, "avg({:?})", n),
393 Transform::Min(n) => write!(f, "min({:?})", n),
394 Transform::Max(n) => write!(f, "max({:?})", n),
395 Transform::Floor(n) => write!(f, "floor({:?})", n),
396 Transform::Ceiling(n) => write!(f, "ceiling({:?})", n),
397 Transform::Round(n, _p) => write!(f, "round({:?},...)", n),
398 Transform::CurrentDateTime => write!(f, "current-date-time"),
399 Transform::CurrentDate => write!(f, "current-date"),
400 Transform::CurrentTime => write!(f, "current-time"),
401 Transform::FormatDateTime(p, q, _, _, _) => {
402 write!(f, "format-date-time({:?}, {:?}, ...)", p, q)
403 }
404 Transform::FormatDate(p, q, _, _, _) => write!(f, "format-date({:?}, {:?}, ...)", p, q),
405 Transform::FormatTime(p, q, _, _, _) => write!(f, "format-time({:?}, {:?}, ...)", p, q),
406 Transform::FormatNumber(v, p, _) => write!(f, "format-number({:?}, {:?})", v, p),
407 Transform::FormatInteger(i, s) => write!(f, "format-integer({:?}, {:?})", i, s),
408 Transform::GenerateIntegers(_start_at, _select, _n) => write!(f, "generate-integers"),
409 Transform::CurrentGroup => write!(f, "current-group"),
410 Transform::CurrentGroupingKey => write!(f, "current-grouping-key"),
411 Transform::Key(s, _, _, _) => write!(f, "key({:?}, ...)", s),
412 Transform::SystemProperty(p, _) => write!(f, "system-properties({:?})", p),
413 Transform::AvailableSystemProperties => write!(f, "available-system-properties"),
414 Transform::Document(uris, _) => write!(f, "document({:?})", uris),
415 Transform::Invoke(qn, _a, _) => write!(f, "invoke \"{}\"", qn),
416 Transform::Message(_, _, _, _) => write!(f, "message"),
417 Transform::NotImplemented(s) => write!(f, "Not implemented: \"{}\"", s),
418 Transform::Error(k, s) => write!(f, "Error: {} \"{}\"", k, s),
419 }
420 }
421}
422
423pub fn in_scope_namespaces<N: Node>(n: Option<N>) -> Rc<NamespaceMap> {
425 if let Some(nn) = n {
426 Rc::new(nn.namespace_iter().fold(NamespaceMap::new(), |mut hm, ns| {
427 hm.push(
428 NamespaceDeclaration::new(
429 ns.name().map(|nsprefix| {
431 NamespacePrefix::try_from(nsprefix.local_name().to_string().as_str())
432 .unwrap()
433 }),
434 NamespaceUri::try_from(ns.value().to_string().as_str()).unwrap(),
435 )
436 .unwrap(),
437 );
438 hm
439 }))
440 } else {
441 Rc::new(NamespaceMap::new())
442 }
443}
444
445#[derive(Clone, PartialEq, Debug)]
447pub enum Order {
448 Ascending,
449 Descending,
450}
451
452pub(crate) fn do_sort<
454 N: Node,
455 F: FnMut(&str) -> Result<(), Error>,
456 G: FnMut(&str) -> Result<N, Error>,
457 H: FnMut(&Url) -> Result<String, Error>,
458>(
459 seq: &mut Sequence<N>,
460 o: &Vec<(Order, Transform<N>)>,
461 ctxt: &Context<N>,
462 stctxt: &mut StaticContext<N, F, G, H>,
463) -> Result<(), Error> {
464 if !o.is_empty() {
467 seq.sort_by_cached_key(|k| {
468 let key_seq = ContextBuilder::from(ctxt)
470 .context(vec![k.clone()])
471 .build()
472 .dispatch(stctxt, &o[0].1)
473 .expect("unable to determine key value");
474 key_seq.to_string()
478 });
479 if o[0].0 == Order::Descending {
480 seq.reverse();
481 }
482 }
483 Ok(())
484}
485
486#[derive(Clone, Debug)]
490pub enum Grouping<N: Node> {
491 By(Vec<Transform<N>>),
492 StartingWith(Box<Pattern<N>>),
493 EndingWith(Box<Pattern<N>>),
494 Adjacent(Vec<Transform<N>>),
495}
496
497impl<N: Node> Grouping<N> {
498 fn to_string(&self) -> String {
499 match self {
500 Grouping::By(_) => "group-by".to_string(),
501 Grouping::Adjacent(_) => "group-adjacent".to_string(),
502 Grouping::StartingWith(_) => "group-starting-with".to_string(),
503 Grouping::EndingWith(_) => "group-ending-with".to_string(),
504 }
505 }
506}
507
508impl<N: Node> fmt::Display for Grouping<N> {
509 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
510 write!(f, "{}", self.to_string())
511 }
512}
513
514#[derive(Clone, Debug)]
515pub struct NodeMatch {
516 pub axis: Axis,
517 pub nodetest: NodeTest,
518}
519
520impl NodeMatch {
521 pub fn new(axis: Axis, nodetest: NodeTest) -> Self {
522 NodeMatch { axis, nodetest }
523 }
524 pub fn matches_item<N: Node>(&self, i: &Item<N>) -> bool {
525 match i {
526 Item::Node(n) => self.matches(n),
527 _ => false,
528 }
529 }
530 pub fn matches<N: Node>(&self, n: &N) -> bool {
531 self.nodetest.matches(n)
532 }
533}
534
535impl fmt::Display for NodeMatch {
536 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
537 write!(f, "node match {} {}", self.axis, self.nodetest)
538 }
539}
540
541#[derive(Clone, Debug)]
542pub enum NodeTest {
543 Kind(KindTest),
544 Name(NameTest),
545}
546
547impl NodeTest {
548 pub fn matches_item<N: Node>(&self, i: &Item<N>) -> bool {
549 match i {
550 Item::Node(n) => self.matches(n),
551 _ => false,
552 }
553 }
554 pub fn matches<N: Node>(&self, n: &N) -> bool {
555 match self {
556 NodeTest::Kind(k) => k.matches(n),
557 NodeTest::Name(nm) => nm.matches(n),
558 }
559 }
560}
561
562impl fmt::Display for NodeTest {
563 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
564 match self {
565 NodeTest::Kind(k) => write!(f, "kind test {}", k),
566 NodeTest::Name(nm) => write!(f, "name test {}", nm),
567 }
568 }
569}
570
571impl TryFrom<&str> for NodeTest {
572 type Error = Error;
573
574 fn try_from(s: &str) -> Result<Self, Self::Error> {
575 let tok: Vec<&str> = s.split(':').collect();
577 match tok.len() {
578 1 => {
579 if tok[0] == "*" {
581 Ok(NodeTest::Name(NameTest::Wildcard(
582 WildcardOrNamespaceUri::Wildcard,
583 WildcardOrName::Wildcard,
584 )))
585 } else {
586 Ok(NodeTest::Name(NameTest::Name(QName::from_local_name(
587 NcName::try_from(tok[0])
588 .map_err(|_| Error::new(ErrorKind::ParseError, "not a NcName"))?,
589 ))))
590 }
591 }
592 2 => {
593 if tok[0] == "*" {
595 if tok[1] == "*" {
596 Ok(NodeTest::Name(NameTest::Wildcard(
597 WildcardOrNamespaceUri::Wildcard,
598 WildcardOrName::Wildcard,
599 )))
600 } else {
601 Ok(NodeTest::Name(NameTest::Wildcard(
602 WildcardOrNamespaceUri::Wildcard,
603 WildcardOrName::Name(QName::from_local_name(
604 NcName::try_from(tok[1]).map_err(|_| {
605 Error::new(ErrorKind::ParseError, "not a NcName")
606 })?,
607 )),
608 )))
609 }
610 } else if tok[1] == "*" {
611 Ok(NodeTest::Name(NameTest::Wildcard(
612 WildcardOrNamespaceUri::NamespaceUri(
613 NamespaceUri::try_from(tok[0]).map_err(|_| {
614 Error::new(ErrorKind::ParseError, "not a namespace URI")
615 })?,
616 ),
617 WildcardOrName::Wildcard,
618 )))
619 } else {
620 Ok(NodeTest::Name(NameTest::Name(QName::new_from_parts(
621 NcName::try_from(tok[1])
622 .map_err(|_| Error::new(ErrorKind::ParseError, "not a NcName"))?,
623 Some(
624 NamespaceUri::try_from(tok[1])
625 .map_err(|_| Error::new(ErrorKind::ParseError, "not a NcName"))?,
626 ),
627 ))))
628 }
629 }
630 _ => Result::Err(Error::new(
631 ErrorKind::TypeError,
632 "invalid NodeTest".to_string(),
633 )),
634 }
635 }
636}
637
638#[derive(Copy, Clone, Debug)]
639pub enum KindTest {
640 Document,
641 Element,
642 Attribute,
643 SchemaElement,
644 SchemaAttribute,
645 PI,
646 Comment,
647 Text,
648 Namespace,
649 Any,
650}
651
652impl fmt::Display for KindTest {
653 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
654 match self {
655 KindTest::Document => write!(f, "document"),
656 KindTest::Element => write!(f, "element"),
657 KindTest::Attribute => write!(f, "attribute"),
658 KindTest::SchemaElement => write!(f, "schema element"),
659 KindTest::SchemaAttribute => write!(f, "schema attribute"),
660 KindTest::PI => write!(f, "processing instruction"),
661 KindTest::Comment => write!(f, "comment"),
662 KindTest::Text => write!(f, "text"),
663 KindTest::Namespace => write!(f, "namespace"),
664 KindTest::Any => write!(f, "any node"),
665 }
666 }
667}
668
669impl KindTest {
670 pub fn matches_item<N: Node>(&self, i: &Item<N>) -> bool {
672 match i {
673 Item::Node(n) => self.matches(n),
674 _ => false,
675 }
676 }
677 pub fn matches<N: Node>(&self, n: &N) -> bool {
678 match (self, n.node_type()) {
679 (KindTest::Document, NodeType::Document) => true,
680 (KindTest::Document, _) => false,
681 (KindTest::Element, NodeType::Element) => true,
682 (KindTest::Element, _) => false,
683 (KindTest::Attribute, NodeType::Attribute) => true,
684 (KindTest::Attribute, _) => false,
685 (KindTest::SchemaElement, _) => false, (KindTest::SchemaAttribute, _) => false, (KindTest::PI, NodeType::ProcessingInstruction) => true,
688 (KindTest::PI, _) => false,
689 (KindTest::Comment, NodeType::Comment) => true,
690 (KindTest::Comment, _) => false,
691 (KindTest::Text, NodeType::Text) => true,
692 (KindTest::Text, _) => false,
693 (KindTest::Namespace, _) => false, (KindTest::Any, _) => true,
695 }
696 }
697 pub fn to_string(&self) -> &'static str {
698 match self {
699 KindTest::Document => "DocumentTest",
700 KindTest::Element => "ElementTest",
701 KindTest::Attribute => "AttributeTest",
702 KindTest::SchemaElement => "SchemaElementTest",
703 KindTest::SchemaAttribute => "SchemaAttributeTest",
704 KindTest::PI => "PITest",
705 KindTest::Comment => "CommentTest",
706 KindTest::Text => "TextTest",
707 KindTest::Namespace => "NamespaceNodeTest",
708 KindTest::Any => "AnyKindTest",
709 }
710 }
711}
712
713#[derive(Clone, Debug)]
714pub enum NameTest {
715 Name(QName),
716 Wildcard(WildcardOrNamespaceUri, WildcardOrName),
717}
718impl NameTest {
725 pub fn matches_item<N: Node>(&self, i: &Item<N>) -> bool {
735 match i {
736 Item::Node(n) => self.matches(n),
737 _ => false, }
739 }
740 pub fn matches<N: Node>(&self, n: &N) -> bool {
741 if let Some(nm) = n.name() {
742 match self {
744 NameTest::Name(qn) => *qn == nm,
745 NameTest::Wildcard(nsw, nmw) => {
746 let nsb = match nsw {
747 WildcardOrNamespaceUri::Wildcard => true,
748 WildcardOrNamespaceUri::NamespaceUri(nsuri) => {
749 nm.namespace_uri().is_some_and(|ns| *nsuri == ns)
750 }
751 };
752 let nmb = match nmw {
753 WildcardOrName::Wildcard => true,
754 WildcardOrName::Name(nmwn) => nmwn.local_name() == nm.local_name(),
755 };
756 nsb && nmb
757 }
758 }
759 } else {
781 false
782 }
783 }
784}
785
786impl fmt::Display for NameTest {
787 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
788 match self {
789 NameTest::Name(nm) => f.write_str(nm.to_string().as_str()),
790 NameTest::Wildcard(nsw, nmw) => {
791 let _ = f.write_str("{");
792 let _ = match nsw {
793 WildcardOrNamespaceUri::NamespaceUri(nsuri) => {
794 f.write_str(nsuri.to_string().as_str())
795 }
796 WildcardOrNamespaceUri::Wildcard => f.write_str("*"),
797 };
798 let _ = f.write_str("}");
799 match nmw {
800 WildcardOrName::Wildcard => f.write_str("*"),
801 WildcardOrName::Name(n) => f.write_str(n.to_string().as_str()),
802 }
803 }
804 }
805 }
806}
807
808#[derive(Clone)]
809pub enum WildcardOrNamespaceUri {
810 Wildcard,
811 NamespaceUri(NamespaceUri),
812}
813
814impl Debug for WildcardOrNamespaceUri {
815 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
816 match self {
817 WildcardOrNamespaceUri::Wildcard => f.write_str("WildcardOrNamespaceUri::Wildcard"),
818 WildcardOrNamespaceUri::NamespaceUri(ns) => f.write_str(
819 format!("WildcardOrNamespaceUri::NamespaceUri({})", ns.to_string()).as_str(),
820 ),
821 }
822 }
823}
824
825#[derive(Clone)]
826pub enum WildcardOrName {
827 Wildcard,
828 Name(QName), }
830
831impl Debug for WildcardOrName {
832 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
833 match self {
834 WildcardOrName::Wildcard => f.write_str("WildcardOrNamespaceUri::Wildcard"),
835 WildcardOrName::Name(n) => f.write_str(format!("WildcardOrName::Name({})", n).as_str()),
836 }
837 }
838}
839
840#[derive(Copy, Clone, Debug, PartialEq)]
841pub enum Axis {
842 Child,
843 Descendant,
844 DescendantOrSelf,
845 DescendantOrSelfOrRoot,
846 Attribute,
847 SelfAttribute, SelfAxis,
849 SelfDocument, SelfNamespace, Following,
852 FollowingSibling,
853 Namespace,
854 Parent,
855 ParentDocument, Ancestor,
857 AncestorOrSelf,
858 AncestorOrSelfOrRoot, Preceding,
860 PrecedingSibling,
861 Unknown,
862}
863
864impl From<&str> for Axis {
865 fn from(s: &str) -> Self {
866 match s {
867 "child" => Axis::Child,
868 "descendant" => Axis::Descendant,
869 "descendant-or-self" => Axis::DescendantOrSelf,
870 "attribute" => Axis::Attribute,
871 "self" => Axis::SelfAxis,
872 "following" => Axis::Following,
873 "following-sibling" => Axis::FollowingSibling,
874 "namespace" => Axis::Namespace,
875 "parent" => Axis::Parent,
876 "ancestor" => Axis::Ancestor,
877 "ancestor-or-self" => Axis::AncestorOrSelf,
878 "preceding" => Axis::Preceding,
879 "preceding-sibling" => Axis::PrecedingSibling,
880 _ => Axis::Unknown,
881 }
882 }
883}
884
885impl fmt::Display for Axis {
886 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
887 let result = match self {
888 Axis::Child => "child".to_string(),
889 Axis::Descendant => "descendant".to_string(),
890 Axis::DescendantOrSelf => "descendant-or-self".to_string(),
891 Axis::DescendantOrSelfOrRoot => "descendant-or-self-or-root".to_string(),
892 Axis::Attribute => "attribute".to_string(),
893 Axis::SelfAttribute => "self-attribute".to_string(),
894 Axis::SelfAxis => "self".to_string(),
895 Axis::SelfDocument => "self-document".to_string(),
896 Axis::Following => "following".to_string(),
897 Axis::FollowingSibling => "following-sibling".to_string(),
898 Axis::Namespace => "namespace".to_string(),
899 Axis::Parent => "parent".to_string(),
900 Axis::ParentDocument => "parent-document".to_string(),
901 Axis::Ancestor => "ancestor".to_string(),
902 Axis::AncestorOrSelf => "ancestor-or-self".to_string(),
903 Axis::Preceding => "preceding".to_string(),
904 Axis::PrecedingSibling => "preceding-sibling".to_string(),
905 _ => "unknown".to_string(),
906 };
907 f.write_str(result.as_str())
908 }
909}
910
911#[derive(Clone, Debug)]
912pub struct ArithmeticOperand<N: Node> {
913 pub op: ArithmeticOperator,
914 pub operand: Transform<N>,
915}
916
917impl<N: Node> ArithmeticOperand<N> {
918 pub fn new(op: ArithmeticOperator, operand: Transform<N>) -> Self {
919 ArithmeticOperand { op, operand }
920 }
921}
922
923#[derive(Copy, Clone, Debug, PartialEq)]
924pub enum ArithmeticOperator {
925 Noop,
926 Add,
927 Multiply,
928 Divide,
929 IntegerDivide,
930 Subtract,
931 Modulo,
932}
933
934impl fmt::Display for ArithmeticOperator {
935 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
936 match self {
937 ArithmeticOperator::Add => f.write_str("+"),
938 ArithmeticOperator::Multiply => f.write_str("*"),
939 ArithmeticOperator::Divide => f.write_str("div"),
940 ArithmeticOperator::IntegerDivide => f.write_str("idiv"),
941 ArithmeticOperator::Subtract => f.write_str("-"),
942 ArithmeticOperator::Modulo => f.write_str("mod"),
943 ArithmeticOperator::Noop => f.write_str("noop"),
944 }
945 }
946}
947
948impl From<&str> for ArithmeticOperator {
949 fn from(a: &str) -> Self {
950 match a {
951 "+" => ArithmeticOperator::Add,
952 "*" => ArithmeticOperator::Multiply,
953 "div" => ArithmeticOperator::Divide,
954 "idiv" => ArithmeticOperator::IntegerDivide,
955 "-" => ArithmeticOperator::Subtract,
956 "mod" => ArithmeticOperator::Modulo,
957 _ => ArithmeticOperator::Noop,
958 }
959 }
960}
961
962impl From<String> for ArithmeticOperator {
963 fn from(a: String) -> Self {
964 match a.as_str() {
965 "+" => ArithmeticOperator::Add,
966 "*" => ArithmeticOperator::Multiply,
967 "div" => ArithmeticOperator::Divide,
968 "idiv" => ArithmeticOperator::IntegerDivide,
969 "-" => ArithmeticOperator::Subtract,
970 "mod" => ArithmeticOperator::Modulo,
971 _ => ArithmeticOperator::Noop,
972 }
973 }
974}
975
976pub(crate) const MAXDEPTH: usize = 200;