private static void DecodeName(Axis node, StringBuilder expr) { string name = node.Name; if (name == null || name.Length == 0) { expr.Append(s_Star); } else { string prefix = node.Prefix; if (prefix != null && prefix.Length > 0) { expr.Append(prefix); expr.Append(s_Colon); } expr.Append(name); } }
private static void DecodeNodeTest(Axis node, StringBuilder expr) { switch (node.Type) { case XPathNodeType.Element: case XPathNodeType.Attribute: DecodeName(node, expr); break; case XPathNodeType.Text: expr.Append(s_Text); break; case XPathNodeType.ProcessingInstruction: expr.Append(s_ProcessingInstruction); expr.Append(s_LParens); string name = node.Name; if (name != null && name.Length > 0) expr.Append(name); expr.Append(s_RParens); break; case XPathNodeType.Comment: expr.Append(s_Comment); break; case XPathNodeType.All: expr.Append(s_Node); break; default: Debug.Fail("Unexpected node type in axis"); break; } }
//>> NodeTest ::= NameTest | 'comment ()' | 'text ()' | 'node ()' | 'processing-instruction (' Literal ? ')' private AstNode ParseNodeTest(AstNode qyInput, Axis.AxisType axisType, XPathNodeType nodeType) { string nodeName, nodePrefix; switch (this.scanner.Kind) { case XPathScanner.LexKind.Name : if (this.scanner.CanBeFunction && IsNodeType(this.scanner)) { nodePrefix = string.Empty; nodeName = string.Empty; nodeType = ( this.scanner.Name == "comment" ? XPathNodeType.Comment : this.scanner.Name == "text" ? XPathNodeType.Text : this.scanner.Name == "node" ? XPathNodeType.All : this.scanner.Name == "processing-instruction" ? XPathNodeType.ProcessingInstruction : /* default: */ XPathNodeType.Root ); Debug.Assert(nodeType != XPathNodeType.Root); NextLex(); PassToken(XPathScanner.LexKind.LParens); if (nodeType == XPathNodeType.ProcessingInstruction) { if (this.scanner.Kind != XPathScanner.LexKind.RParens) { //>> 'processing-instruction (' Literal ')' CheckToken(XPathScanner.LexKind.String); nodeName = this.scanner.StringValue; NextLex(); } } PassToken(XPathScanner.LexKind.RParens); } else { nodePrefix = this.scanner.Prefix; nodeName = this.scanner.Name; NextLex(); if (nodeName == "*") { nodeName = string.Empty; } } break; case XPathScanner.LexKind.Star : nodePrefix = string.Empty; nodeName = string.Empty; NextLex(); break; default : throw new XPathException(Res.Xp_NodeSetExpected, this.scanner.SourceText); } return new Axis(axisType, qyInput, nodePrefix, nodeName, nodeType); }
//>> LocationPathPattern ::= '/' | RelativePathPattern | '//' RelativePathPattern | '/' RelativePathPattern //>> | IdKeyPattern (('/' | '//') RelativePathPattern)? private AstNode ParseLocationPathPattern(AstNode qyInput) { AstNode opnd = null; switch (this.scanner.Kind) { case XPathScanner.LexKind.Slash : NextLex(); opnd = new Root(); if (this.scanner.Kind == XPathScanner.LexKind.Eof || this.scanner.Kind == XPathScanner.LexKind.Union) { return opnd; } break; case XPathScanner.LexKind.SlashSlash : NextLex(); opnd = new Axis(Axis.AxisType.DescendantOrSelf, new Root()); break; case XPathScanner.LexKind.Name : if (this.scanner.CanBeFunction) { opnd = ParseIdKeyPattern(qyInput); if (opnd != null) { switch (this.scanner.Kind) { case XPathScanner.LexKind.Slash : NextLex(); break; case XPathScanner.LexKind.SlashSlash : NextLex(); opnd = new Axis(Axis.AxisType.DescendantOrSelf, opnd); break; default : return opnd; } } } break; } return ParseRelativePathPattern(opnd); }
// depending on axis.Name & axis.Prefix, i will set the axis._urn; // also, record urn from prefix during this // 4 different types of element or attribute (with @ before it) combinations: // (1) a:b (2) b (3) * (4) a:* // i will check xpath to be strictly conformed from these forms // for (1) & (4) i will have URN set properly // for (2) the URN is null // for (3) the URN is empty private void SetURN (Axis axis, XmlNamespaceManager nsmgr) { if (axis.Prefix != String.Empty) { // (1) (4) XmlNameTable nameTable = nsmgr.NameTable; if (nameTable != null) { axis._urn = nsmgr.LookupNamespace(nsmgr.NameTable.Get(axis.Prefix)); } else { axis._urn = nsmgr.LookupNamespace(axis.Prefix); } // axis._urn = prefix == null ? null : nsmgr.LookupNamespace(prefix); // wrong prefix, throw exceptions if (axis._urn == null) { throw new XmlSchemaException(Res.Sch_UnresolvedPrefix, axis.Prefix); } } else if (axis.Name != String.Empty) { // (2) axis._urn = null; } else { // (3) axis._urn = ""; } }
//>> Step ::= '.' | '..' | ( AxisName '::' | '@' )? NodeTest Predicate* private AstNode ParseStep(AstNode qyInput) { AstNode opnd; if (XPathScanner.LexKind.Dot == this.scanner.Kind) { //>> '.' NextLex(); opnd = new Axis(Axis.AxisType.Self, qyInput); } else if (XPathScanner.LexKind.DotDot == this.scanner.Kind) { //>> '..' NextLex(); opnd = new Axis(Axis.AxisType.Parent, qyInput); } else { //>> ( AxisName '::' | '@' )? NodeTest Predicate* Axis.AxisType axisType = Axis.AxisType.Child; switch (this.scanner.Kind) { case XPathScanner.LexKind.At: //>> '@' axisType = Axis.AxisType.Attribute; NextLex(); break; case XPathScanner.LexKind.Axe: //>> AxisName '::' axisType = GetAxis(this.scanner); NextLex(); break; } XPathNodeType nodeType = ( axisType == Axis.AxisType.Attribute ? XPathNodeType.Attribute : // axisType == Axis.AxisType.Namespace ? XPathNodeType.Namespace : // No Idea why it's this way but othervise Axes doesn't work /* default: */ XPathNodeType.Element ); opnd = ParseNodeTest(qyInput, axisType, nodeType); while (XPathScanner.LexKind.LBracket == this.scanner.Kind) { opnd = new Filter(opnd, ParsePredicate(opnd)); } } return opnd; }
private static bool IsDescendantOrSelf(Axis ast) { return ((ast.TypeOfAxis == Axis.AxisType.DescendantOrSelf) && (ast.Type == XPathNodeType.All) && (ast.abbrAxis)); }
private IQuery ProcessNode(AstNode root, IQuery qyInput,int parent, Axis.AxisType parentaxis, ref bool cache, ref bool position) { IQuery result = null; if (root == null) return null; switch (root.TypeOfAst) { case AstNode.QueryType.Axis: filterCount = 0; firstInput = null; Axis axis = (Axis)root; if (axis.TypeOfAxis == Axis.AxisType.Descendant || axis.TypeOfAxis == Axis.AxisType.DescendantOrSelf) if (_smart > 0) { result = ProcessAxis( axis, ProcessNode(axis.Input, qyInput,Smart_D, axis.TypeOfAxis, ref cache, ref position), parent, parentaxis); break; } _smart++; result = ProcessAxis( axis, ProcessNode(axis.Input, qyInput,Regular_D, axis.TypeOfAxis, ref cache, ref position), parent, parentaxis); _smart--; break; case AstNode.QueryType.Operator: _smart = 2; result = ProcessOperator((Operator)root, null, ref cache, ref position); break; case AstNode.QueryType.Filter: _smart = 2; result = ProcessFilter((Filter)root, ref cache, ref position); break; case AstNode.QueryType.ConstantOperand: result = ProcessOperand((Operand)root); break; case AstNode.QueryType.Variable: result = ProcessVariable((Variable)root); break; case AstNode.QueryType.Function: result = ProcessFunction( (System.Xml.XPath.Function)root, qyInput, ref cache, ref position); break; case AstNode.QueryType.Group: _smart = 2; result = new GroupQuery(ProcessNode( ((System.Xml.XPath.Group)root).GroupNode, qyInput,Regular_D, Axis.AxisType.None, ref cache, ref position)); break; case AstNode.QueryType.Root: result = new AbsoluteQuery(); break; default: Debug.Assert(false, "Unknown QueryType encountered!!"); break; } return result; }
// this part is for parsing restricted xpath from grammar private static bool IsNameTest(Axis ast) { // Type = Element, abbrAxis = false // all are the same, has child:: or not return ((ast.TypeOfAxis == Axis.AxisType.Child) && (ast.Type == XPathNodeType.Element)); }
internal static bool IsAttribute(Axis ast) { return ((ast.TypeOfAxis == Axis.AxisType.Attribute) && (ast.Type == XPathNodeType.Attribute)); }
// recursive here internal static DoubleLinkAxis ConvertTree (Axis axis) { if (axis == null) { return null; } return ( new DoubleLinkAxis (axis, ConvertTree ((Axis) (axis.Input)))); }
//constructor internal DoubleLinkAxis (Axis axis, DoubleLinkAxis inputaxis) { this.next = null; this._input = inputaxis; this._urn = axis.URN; this._prefix = axis.Prefix; this._name = axis.Name; this._nodetype = axis.Type; this._axistype = axis.TypeOfAxis; this.abbrAxis = axis.abbrAxis; if (inputaxis != null) { inputaxis.Next = this; } }
//constructor // I can't recrusively call constructor -- "No overload for method 'Axis' takes '0' arguments" // or assign value to 'this' -- "Cannot assign to '<this>' because it is read-only" //constructor internal DoubleLinkAxis ( Axis input, Axis next, String urn, String prefix, String name, XPathNodeType nodetype, AxisType axistype, bool abbrAxis ) { this._input = input; this.next = next; this._urn = urn; this._prefix = prefix; this._name = name; this._nodetype = nodetype; this._axistype = axistype; this.abbrAxis = abbrAxis; }
private static void DecodeAxis(Axis node, StringBuilder expr) { string axis = String.Empty; switch (node.TypeOfAxis) { case Axis.AxisType.Ancestor: axis = s_Ancestor; break; case Axis.AxisType.AncestorOrSelf: axis = s_AncestorOrSelf; break; case Axis.AxisType.Attribute: axis = s_Attribute; break; case Axis.AxisType.Child: break; case Axis.AxisType.Descendant: axis = s_Descendant; break; case Axis.AxisType.DescendantOrSelf: if (node.abbrAxis) { return; } axis = s_DescendantOrSelf; break; case Axis.AxisType.Following: axis = s_Following; break; case Axis.AxisType.FollowingSibling: axis = s_FollowingSibling; break; case Axis.AxisType.Namespace: axis = s_Namespace; break; case Axis.AxisType.Parent: axis = s_Parent; break; case Axis.AxisType.Preceding: axis = s_Preceding; break; case Axis.AxisType.PrecedingSibling: axis = s_PrecedingSibling; break; case Axis.AxisType.Self: axis = s_Self; break; case Axis.AxisType.None: break; default: Debug.Fail("Unexpected Type Of Axis"); break; } expr.Append(axis); DecodeNodeTest(node, expr); }
internal static bool IsSelf(Axis ast) { return ((ast.TypeOfAxis == Axis.AxisType.Self) && (ast.Type == XPathNodeType.All) && (ast.abbrAxis)); }
private static void ComposeAxis(Axis node, StringBuilder expr) { if (node.Input != null) { ComposeExpression(node.Input, expr); if (node.Input.TypeOfAst == AstNode.QueryType.Axis) { expr.Append(s_Slash); } } DecodeAxis(node, expr); }
private IQuery ProcessAxis(Axis root , IQuery qyInput, int parent, Axis.AxisType parentaxis) { IQuery result = null; String URN = String.Empty; if ( root.Prefix.Length > 0) { _hasPrefix = true; } hasReverseAxis = false; switch (root.TypeOfAxis) { case Axis.AxisType.Ancestor: result = new XPathAncestorQuery( qyInput , false, root.Name, root.Prefix, URN, root.Type ); _specialAxis = hasReverseAxis = true; break; case Axis.AxisType.AncestorOrSelf: result = new XPathAncestorQuery( qyInput, true, root.Name, root.Prefix, URN, root.Type ); _specialAxis = hasReverseAxis = true; break; case Axis.AxisType.Child: if (_slashslash){ result = new XPathDescendantQuery( qyInput, false, root.Name, root.Prefix, URN, root.Type, abbrAxis); if (_specialAxis || (qyInput != null && (int)qyInput.getName() > (int) Querytype.Self)) { result = new CacheQuery(result); } _slashslash = false; _specialAxis = true; break; } if (_specialAxis || (qyInput != null && (int)qyInput.getName() > (int) Querytype.Self)) result = new CacheChildrenQuery( qyInput, root.Name, root.Prefix, URN, root.Type ); else result = new ChildrenQuery( qyInput, root.Name, root.Prefix, URN, root.Type ); break; case Axis.AxisType.Parent: result = new ParentQuery( qyInput, root.Name, root.Prefix, URN, root.Type ); break; case Axis.AxisType.Descendant: switch (parent) { case Smart_D : result = new SmartXPathDescendantQuery( qyInput, false, root.Name, root.Prefix, URN, root.Type); break; case Regular_D : result = new XPathDescendantQuery(qyInput, false, root.Name, root.Prefix, URN, root.Type); if (_specialAxis || (qyInput != null && (int)qyInput.getName() > (int) Querytype.Self)) result = new CacheQuery(result); _specialAxis = true; break; } break; case Axis.AxisType.DescendantOrSelf: switch (parent) { case Smart_D : result = new SmartXPathDescendantQuery(qyInput, true, root.Name, root.Prefix, URN, root.Type, root.abbrAxis); break; case Regular_D : if ( _smart <= 1 || root.Type != XPathNodeType.All || parentaxis != Axis.AxisType.Child) { result = new XPathDescendantQuery( qyInput, true, root.Name, root.Prefix, URN, root.Type, root.abbrAxis); if (_specialAxis || (qyInput != null && (int)qyInput.getName() > (int) Querytype.Self)) result = new CacheQuery(result); _specialAxis = true; } else { _slashslash = true; abbrAxis = root.abbrAxis; result = qyInput; } break; } break; case Axis.AxisType.Preceding: result = new PrecedingQuery( qyInput, root.Name, root.Prefix, URN, root.Type); _specialAxis = hasReverseAxis = true; break; case Axis.AxisType.Following : result = new FollowingQuery( qyInput, root.Name, root.Prefix, URN, root.Type); _specialAxis = true; break; case Axis.AxisType.FollowingSibling : result = new FollSiblingQuery( qyInput, root.Name, root.Prefix, URN, root.Type); if (_specialAxis || (qyInput != null && (int)qyInput.getName() > (int) Querytype.Self)) { result = new DocumentOrderQuery(result); } break; case Axis.AxisType.PrecedingSibling : result = new PreSiblingQuery( qyInput, root.Name, root.Prefix, URN, root.Type); hasReverseAxis = true; break; case Axis.AxisType.Attribute: result = new AttributeQuery( qyInput, root.Name, root.Prefix, URN, root.Type); break; case Axis.AxisType.Self: result = new XPathSelfQuery( qyInput, root.Name, root.Prefix, URN, root.Type); break; case Axis.AxisType.Namespace: if ( (root.Type == XPathNodeType.All || root.Type == XPathNodeType.Element || root.Type == XPathNodeType.Attribute) && root.Prefix == string.Empty ) { result = new NamespaceQuery(qyInput, root.Name, root.Prefix, URN, root.Type); } else { result = new EmptyNamespaceQuery(); } break; default: throw new XPathException(Res.Xp_NotSupported, _query); } return result; }