Exemplo n.º 1
0
 protected BaseAxisQuery(BaseAxisQuery other) : base(other)
 {
     this.qyInput     = Clone(other.qyInput);
     _name            = other._name;
     _prefix          = other._prefix;
     _nsUri           = other._nsUri;
     _typeTest        = other._typeTest;
     _nameTest        = other._nameTest;
     this.position    = other.position;
     this.currentNode = other.currentNode;
 }
 protected BaseAxisQuery(BaseAxisQuery other) : base(other)
 {
     this.qyInput     = Query.Clone(other.qyInput);
     this.name        = other.name;
     this.prefix      = other.prefix;
     this.nsUri       = other.nsUri;
     this.typeTest    = other.typeTest;
     this.nameTest    = other.nameTest;
     this.position    = other.position;
     this.currentNode = other.currentNode;
 }
Exemplo n.º 3
0
        private Query ProcessAxis(Axis root, Flags flags, out Props props)
        {
            Query qyParent = null;
            Query query2;

            if (root.Prefix.Length > 0)
            {
                this.needContext = true;
            }
            this.firstInput = null;
            if (root.Input != null)
            {
                Flags none = Flags.None;
                if ((flags & Flags.PosFilter) == Flags.None)
                {
                    Axis input = root.Input as Axis;
                    if (((input != null) && (root.TypeOfAxis == Axis.AxisType.Child)) && ((input.TypeOfAxis == Axis.AxisType.DescendantOrSelf) && (input.NodeType == XPathNodeType.All)))
                    {
                        Query query3;
                        if (input.Input != null)
                        {
                            query3 = this.ProcessNode(input.Input, Flags.SmartDesc, out props);
                        }
                        else
                        {
                            query3 = new ContextQuery();
                            props  = Props.None;
                        }
                        qyParent = new DescendantQuery(query3, root.Name, root.Prefix, root.NodeType, false, input.AbbrAxis);
                        if ((props & Props.NonFlat) != Props.None)
                        {
                            qyParent = new DocumentOrderQuery(qyParent);
                        }
                        props |= Props.NonFlat;
                        return(qyParent);
                    }
                    if ((root.TypeOfAxis == Axis.AxisType.Descendant) || (root.TypeOfAxis == Axis.AxisType.DescendantOrSelf))
                    {
                        none |= Flags.SmartDesc;
                    }
                }
                query2 = this.ProcessNode(root.Input, none, out props);
            }
            else
            {
                query2 = new ContextQuery();
                props  = Props.None;
            }
            switch (root.TypeOfAxis)
            {
            case Axis.AxisType.Ancestor:
                qyParent = new XPathAncestorQuery(query2, root.Name, root.Prefix, root.NodeType, false);
                props   |= Props.NonFlat;
                return(qyParent);

            case Axis.AxisType.AncestorOrSelf:
                qyParent = new XPathAncestorQuery(query2, root.Name, root.Prefix, root.NodeType, true);
                props   |= Props.NonFlat;
                return(qyParent);

            case Axis.AxisType.Attribute:
                return(new AttributeQuery(query2, root.Name, root.Prefix, root.NodeType));

            case Axis.AxisType.Child:
                if ((props & Props.NonFlat) == Props.None)
                {
                    return(new ChildrenQuery(query2, root.Name, root.Prefix, root.NodeType));
                }
                return(new CacheChildrenQuery(query2, root.Name, root.Prefix, root.NodeType));

            case Axis.AxisType.Descendant:
                if ((flags & Flags.SmartDesc) == Flags.None)
                {
                    qyParent = new DescendantQuery(query2, root.Name, root.Prefix, root.NodeType, false, false);
                    if ((props & Props.NonFlat) != Props.None)
                    {
                        qyParent = new DocumentOrderQuery(qyParent);
                    }
                    break;
                }
                qyParent = new DescendantOverDescendantQuery(query2, false, root.Name, root.Prefix, root.NodeType, false);
                break;

            case Axis.AxisType.DescendantOrSelf:
                if ((flags & Flags.SmartDesc) == Flags.None)
                {
                    qyParent = new DescendantQuery(query2, root.Name, root.Prefix, root.NodeType, true, root.AbbrAxis);
                    if ((props & Props.NonFlat) != Props.None)
                    {
                        qyParent = new DocumentOrderQuery(qyParent);
                    }
                }
                else
                {
                    qyParent = new DescendantOverDescendantQuery(query2, true, root.Name, root.Prefix, root.NodeType, root.AbbrAxis);
                }
                props |= Props.NonFlat;
                return(qyParent);

            case Axis.AxisType.Following:
                qyParent = new FollowingQuery(query2, root.Name, root.Prefix, root.NodeType);
                props   |= Props.NonFlat;
                return(qyParent);

            case Axis.AxisType.FollowingSibling:
                qyParent = new FollSiblingQuery(query2, root.Name, root.Prefix, root.NodeType);
                if ((props & Props.NonFlat) != Props.None)
                {
                    qyParent = new DocumentOrderQuery(qyParent);
                }
                return(qyParent);

            case Axis.AxisType.Namespace:
                if ((((root.NodeType == XPathNodeType.All) || (root.NodeType == XPathNodeType.Element)) || (root.NodeType == XPathNodeType.Attribute)) && (root.Prefix.Length == 0))
                {
                    return(new NamespaceQuery(query2, root.Name, root.Prefix, root.NodeType));
                }
                return(new EmptyQuery());

            case Axis.AxisType.Parent:
                return(new ParentQuery(query2, root.Name, root.Prefix, root.NodeType));

            case Axis.AxisType.Preceding:
                qyParent = new PrecedingQuery(query2, root.Name, root.Prefix, root.NodeType);
                props   |= Props.NonFlat;
                return(qyParent);

            case Axis.AxisType.PrecedingSibling:
                return(new PreSiblingQuery(query2, root.Name, root.Prefix, root.NodeType));

            case Axis.AxisType.Self:
                return(new XPathSelfQuery(query2, root.Name, root.Prefix, root.NodeType));

            default:
                throw XPathException.Create("Xp_NotSupported", this.query);
            }
            props |= Props.NonFlat;
            return(qyParent);
        }
Exemplo n.º 4
0
        private Query ProcessFilter(MS.Internal.Xml.XPath.Filter root, Flags flags, out Props props)
        {
            Props props2;
            bool  flag = (flags & Flags.Filter) == Flags.None;
            Query q    = this.ProcessNode(root.Condition, Flags.None, out props2);

            if (this.CanBeNumber(q) || ((props2 & (Props.HasLast | Props.HasPosition)) != Props.None))
            {
                props2 |= Props.HasPosition;
                flags  |= Flags.PosFilter;
            }
            flags &= ~Flags.SmartDesc;
            Query input = this.ProcessNode(root.Input, flags | Flags.Filter, out props);

            if (root.Input.Type != AstNode.AstType.Filter)
            {
                props &= ~Props.PosFilter;
            }
            if ((props2 & Props.HasPosition) != Props.None)
            {
                props |= Props.PosFilter;
            }
            FilterQuery query3 = input as FilterQuery;

            if (((query3 != null) && ((props2 & Props.HasPosition) == Props.None)) && (query3.Condition.StaticType != XPathResultType.Any))
            {
                Query condition = query3.Condition;
                if (condition.StaticType == XPathResultType.Number)
                {
                    condition = new LogicalExpr(Operator.Op.EQ, new NodeFunctions(Function.FunctionType.FuncPosition, null), condition);
                }
                q     = new BooleanExpr(Operator.Op.AND, condition, q);
                input = query3.qyInput;
            }
            if (((props & Props.PosFilter) != Props.None) && (input is DocumentOrderQuery))
            {
                input = ((DocumentOrderQuery)input).input;
            }
            if (this.firstInput == null)
            {
                this.firstInput = input as BaseAxisQuery;
            }
            bool flag2 = (input.Properties & QueryProps.Merge) != QueryProps.None;
            bool flag3 = (input.Properties & QueryProps.Reverse) != QueryProps.None;

            if ((props2 & Props.HasPosition) != Props.None)
            {
                if (flag3)
                {
                    input = new ReversePositionQuery(input);
                }
                else if ((props2 & Props.HasLast) != Props.None)
                {
                    input = new ForwardPositionQuery(input);
                }
            }
            if (flag && (this.firstInput != null))
            {
                if (flag2 && ((props & Props.PosFilter) != Props.None))
                {
                    input = new FilterQuery(input, q, false);
                    Query qyInput = this.firstInput.qyInput;
                    if (!(qyInput is ContextQuery))
                    {
                        this.firstInput.qyInput = new ContextQuery();
                        this.firstInput         = null;
                        return(new MergeFilterQuery(qyInput, input));
                    }
                    this.firstInput = null;
                    return(input);
                }
                this.firstInput = null;
            }
            return(new FilterQuery(input, q, (props2 & Props.HasPosition) == Props.None));
        }
Exemplo n.º 5
0
        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(Res.Xp_NotSupported, query);
            }

            return(result);
        }
Exemplo n.º 6
0
        private Query ProcessFilter(Filter root, Flags flags, out Props props)
        {
            bool first = ((flags & Flags.Filter) == 0);

            Props propsCond;
            Query cond = ProcessNode(root.Condition, Flags.None, out propsCond);

            if (
                CanBeNumber(cond) ||
                (propsCond & (Props.HasPosition | Props.HasLast)) != 0
                )
            {
                propsCond |= Props.HasPosition;
                flags     |= Flags.PosFilter;
            }

            // We don't want DescendantOverDescendant pattern to be recognized here (in case descendent::foo[expr]/descendant::bar)
            // So we clean this flag here:
            flags &= ~Flags.SmartDesc;
            // ToDo: Instead it would be nice to wrap descendent::foo[expr] into special query that will flatten it -- i.e.
            //       remove all nodes that are descendant of other nodes. This is very easy becuase for sorted nodesets all children
            //       follow its parent. One step caching. This can be easyly done by rightmost DescendantQuery itsef.
            //       Interesting note! Can we garatee that DescendantOverDescendant returns flat nodeset? This defenetely true if it's input is flat.

            Query qyInput = ProcessNode(root.Input, flags | Flags.Filter, out props);

            if (root.Input.Type != AstNode.AstType.Filter)
            {
                // Props.PosFilter is for nested filters only.
                // We clean it here to avoid cleaning it in all other ast nodes.
                props &= ~Props.PosFilter;
            }
            if ((propsCond & Props.HasPosition) != 0)
            {
                // this condition is positional rightmost filter should be avare of this.
                props |= Props.PosFilter;
            }

            /*merging predicates*/ {
                FilterQuery qyFilter = qyInput as FilterQuery;
                if (qyFilter != null && (propsCond & Props.HasPosition) == 0 && qyFilter.Condition.StaticType != XPathResultType.Any)
                {
                    Query prevCond = qyFilter.Condition;
                    if (prevCond.StaticType == XPathResultType.Number)
                    {
                        prevCond = new LogicalExpr(Operator.Op.EQ, new NodeFunctions(FT.FuncPosition, null), prevCond);
                    }
                    cond    = new BooleanExpr(Operator.Op.AND, prevCond, cond);
                    qyInput = qyFilter.qyInput;
                }
            }

            if ((props & Props.PosFilter) != 0 && qyInput is DocumentOrderQuery)
            {
                qyInput = ((DocumentOrderQuery)qyInput).input;
            }
            if (firstInput == null)
            {
                firstInput = qyInput as BaseAxisQuery;
            }

            bool merge   = (qyInput.Properties & QueryProps.Merge) != 0;
            bool reverse = (qyInput.Properties & QueryProps.Reverse) != 0;

            if ((propsCond & Props.HasPosition) != 0)
            {
                if (reverse)
                {
                    qyInput = new ReversePositionQuery(qyInput);
                }
                else if ((propsCond & Props.HasLast) != 0)
                {
                    qyInput = new ForwardPositionQuery(qyInput);
                }
            }

            if (first && firstInput != null)
            {
                if (merge && (props & Props.PosFilter) != 0)
                {
                    qyInput = new FilterQuery(qyInput, cond, /*noPosition:*/ false);
                    Query parent = firstInput.qyInput;
                    if (!(parent is ContextQuery))    // we don't need to wrap filter with MergeFilterQuery when cardinality is parent <: ?
                    {
                        firstInput.qyInput = new ContextQuery();
                        firstInput         = null;
                        return(new MergeFilterQuery(parent, qyInput));
                    }
                    firstInput = null;
                    return(qyInput);
                }
                firstInput = null;
            }
            return(new FilterQuery(qyInput, cond, /*noPosition:*/ (propsCond & Props.HasPosition) == 0));
        }