示例#1
0
        /// <summary> translate an xpath path reference into a TreeReference
        /// TreeReferences only support a subset of true xpath paths; restrictions are:
        /// simple child name tests 'child::name', '.', and '..' allowed only
        /// no predicates
        /// all '..' steps must come before anything else
        /// </summary>
        public virtual TreeReference getReference(bool allowPredicates)
        {
            TreeReference ref_Renamed = new TreeReference();
            bool          parentsAllowed;

            switch (init_context)
            {
            case XPathPathExpr.INIT_CONTEXT_ROOT:
                ref_Renamed.RefLevel = TreeReference.REF_ABSOLUTE;
                parentsAllowed       = false;
                break;

            case XPathPathExpr.INIT_CONTEXT_RELATIVE:
                ref_Renamed.RefLevel = 0;
                parentsAllowed       = true;
                break;

            case XPathPathExpr.INIT_CONTEXT_EXPR:
                if (this.filtExpr.x != null && this.filtExpr.x is XPathFuncExpr)
                {
                    XPathFuncExpr func = (XPathFuncExpr)(this.filtExpr.x);
                    if (func.id.ToString().Equals("instance"))
                    {
                        ref_Renamed.RefLevel = TreeReference.REF_ABSOLUTE;                                 //i assume when refering the non main instance you have to be absolute
                        parentsAllowed       = false;
                        if (func.args.Length != 1)
                        {
                            throw new XPathUnsupportedException("instance() function used with " + func.args.Length + " arguements. Expecting 1 arguement");
                        }
                        if (!(func.args[0] is XPathStringLiteral))
                        {
                            throw new XPathUnsupportedException("instance() function expecting 1 string literal arguement arguement");
                        }
                        XPathStringLiteral strLit = (XPathStringLiteral)(func.args[0]);
                        //we've got a non-standard instance in play, watch out
                        if (strLit.s == null)
                        {
                            // absolute reference to the main instance
                            ref_Renamed.Context      = TreeReference.CONTEXT_ABSOLUTE;
                            ref_Renamed.InstanceName = null;
                        }
                        else
                        {
                            ref_Renamed.Context      = TreeReference.CONTEXT_INSTANCE;
                            ref_Renamed.InstanceName = strLit.s;
                        }
                    }
                    else
                    {
                        if (func.id.ToString().Equals("current"))
                        {
                            parentsAllowed      = true;
                            ref_Renamed.Context = TreeReference.CONTEXT_ORIGINAL;
                        }
                        else
                        {
                            //We only support expression root contexts for instance refs, everything else is an illegal filter
                            throw new XPathUnsupportedException("filter expression");
                        }
                    }
                }
                else
                {
                    //We only support expression root contexts for instance refs, everything else is an illegal filter
                    throw new XPathUnsupportedException("filter expression");
                }

                break;

            default:  throw new XPathUnsupportedException("filter expression");
            }
            for (int i = 0; i < steps.Length; i++)
            {
                XPathStep step = steps[i];
                if (step.axis == XPathStep.AXIS_SELF)
                {
                    if (step.test != XPathStep.TEST_TYPE_NODE)
                    {
                        throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
                    }
                }
                else if (step.axis == XPathStep.AXIS_PARENT)
                {
                    if (!parentsAllowed || step.test != XPathStep.TEST_TYPE_NODE)
                    {
                        throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
                    }
                    else
                    {
                        ref_Renamed.incrementRefLevel();
                    }
                }
                else if (step.axis == XPathStep.AXIS_ATTRIBUTE)
                {
                    if (step.test == XPathStep.TEST_NAME)
                    {
                        ref_Renamed.add(step.name.ToString(), TreeReference.INDEX_ATTRIBUTE);
                        parentsAllowed = false;
                        //TODO: Can you step back from an attribute, or should this always be
                        //the last step?
                    }
                    else
                    {
                        throw new XPathUnsupportedException("attribute step other than 'attribute::name");
                    }
                }
                else if (step.axis == XPathStep.AXIS_CHILD)
                {
                    if (step.test == XPathStep.TEST_NAME)
                    {
                        ref_Renamed.add(step.name.ToString(), TreeReference.INDEX_UNBOUND);
                        parentsAllowed = true;
                    }
                    else if (step.test == XPathStep.TEST_NAME_WILDCARD)
                    {
                        ref_Renamed.add(TreeReference.NAME_WILDCARD, TreeReference.INDEX_UNBOUND);
                        parentsAllowed = true;
                    }
                    else
                    {
                        throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
                    }
                }
                else
                {
                    throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
                }

                if (step.predicates.Length > 0)
                {
                    int refLevel = ref_Renamed.RefLevel;

                    List <XPathExpression> v = new List <XPathExpression>();
                    for (int j = 0; j < step.predicates.Length; j++)
                    {
                        v.addElement(step.predicates[j]);
                    }
                    ref_Renamed.addPredicate(i, v);
                }
            }
            return(ref_Renamed);
        }