/// <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); }