private Query ProcessAxis(Axis root, Flags flags, out Props props) { Query result = null; if (root.Prefix.Length > 0) { _needContext = true; } _firstInput = null; Query qyInput; { if (root.Input != null) { Flags inputFlags = Flags.None; if ((flags & Flags.PosFilter) == 0) { Axis input = root.Input as Axis; if (input != null) { if ( root.TypeOfAxis == Axis.AxisType.Child && input.TypeOfAxis == Axis.AxisType.DescendantOrSelf && input.NodeType == XPathNodeType.All ) { Query qyGrandInput; if (input.Input != null) { qyGrandInput = ProcessNode(input.Input, Flags.SmartDesc, out props); } else { qyGrandInput = new ContextQuery(); props = Props.None; } result = new DescendantQuery(qyGrandInput, root.Name, root.Prefix, root.NodeType, false, input.AbbrAxis); if ((props & Props.NonFlat) != 0) { result = new DocumentOrderQuery(result); } props |= Props.NonFlat; return result; } } if (root.TypeOfAxis == Axis.AxisType.Descendant || root.TypeOfAxis == Axis.AxisType.DescendantOrSelf) { inputFlags |= Flags.SmartDesc; } } qyInput = ProcessNode(root.Input, inputFlags, out props); } else { qyInput = new ContextQuery(); props = Props.None; } } switch (root.TypeOfAxis) { case Axis.AxisType.Ancestor: result = new XPathAncestorQuery(qyInput, root.Name, root.Prefix, root.NodeType, false); props |= Props.NonFlat; break; case Axis.AxisType.AncestorOrSelf: result = new XPathAncestorQuery(qyInput, root.Name, root.Prefix, root.NodeType, true); props |= Props.NonFlat; break; case Axis.AxisType.Child: if ((props & Props.NonFlat) != 0) { result = new CacheChildrenQuery(qyInput, root.Name, root.Prefix, root.NodeType); } else { result = new ChildrenQuery(qyInput, root.Name, root.Prefix, root.NodeType); } break; case Axis.AxisType.Parent: result = new ParentQuery(qyInput, root.Name, root.Prefix, root.NodeType); break; case Axis.AxisType.Descendant: if ((flags & Flags.SmartDesc) != 0) { result = new DescendantOverDescendantQuery(qyInput, false, root.Name, root.Prefix, root.NodeType, /*abbrAxis:*/false); } else { result = new DescendantQuery(qyInput, root.Name, root.Prefix, root.NodeType, false, /*abbrAxis:*/false); if ((props & Props.NonFlat) != 0) { result = new DocumentOrderQuery(result); } } props |= Props.NonFlat; break; case Axis.AxisType.DescendantOrSelf: if ((flags & Flags.SmartDesc) != 0) { result = new DescendantOverDescendantQuery(qyInput, true, root.Name, root.Prefix, root.NodeType, root.AbbrAxis); } else { result = new DescendantQuery(qyInput, root.Name, root.Prefix, root.NodeType, true, root.AbbrAxis); if ((props & Props.NonFlat) != 0) { result = new DocumentOrderQuery(result); } } props |= Props.NonFlat; break; case Axis.AxisType.Preceding: result = new PrecedingQuery(qyInput, root.Name, root.Prefix, root.NodeType); props |= Props.NonFlat; break; case Axis.AxisType.Following: result = new FollowingQuery(qyInput, root.Name, root.Prefix, root.NodeType); props |= Props.NonFlat; break; case Axis.AxisType.FollowingSibling: result = new FollSiblingQuery(qyInput, root.Name, root.Prefix, root.NodeType); if ((props & Props.NonFlat) != 0) { result = new DocumentOrderQuery(result); } break; case Axis.AxisType.PrecedingSibling: result = new PreSiblingQuery(qyInput, root.Name, root.Prefix, root.NodeType); break; case Axis.AxisType.Attribute: result = new AttributeQuery(qyInput, root.Name, root.Prefix, root.NodeType); break; case Axis.AxisType.Self: result = new XPathSelfQuery(qyInput, root.Name, root.Prefix, root.NodeType); break; case Axis.AxisType.Namespace: if ((root.NodeType == XPathNodeType.All || root.NodeType == XPathNodeType.Element || root.NodeType == XPathNodeType.Attribute) && root.Prefix.Length == 0) { result = new NamespaceQuery(qyInput, root.Name, root.Prefix, root.NodeType); } else { result = new EmptyQuery(); } break; default: throw XPathException.Create(SR.Xp_NotSupported, _query); } return result; }
protected PreSiblingQuery(PreSiblingQuery other) : base(other) { }