2 // System.Xml.XPath.XPathNavigator
5 // Jason Diamond (jason@injektilo.org)
7 // (C) 2002 Jason Diamond http://injektilo.org/
13 namespace System.Xml.XPath
15 public abstract class XPathNavigator : ICloneable
19 protected XPathNavigator ()
27 public abstract string BaseURI { get; }
29 public abstract bool HasAttributes { get; }
31 public abstract bool HasChildren { get; }
33 public abstract bool IsEmptyElement { get; }
35 public abstract string LocalName { get; }
37 public abstract string Name { get; }
39 public abstract string NamespaceURI { get; }
41 public abstract XmlNameTable NameTable { get; }
43 public abstract XPathNodeType NodeType { get; }
45 public abstract string Prefix { get; }
47 public abstract string Value { get; }
49 public abstract string XmlLang { get; }
56 XPathNavigator nav = Clone ();
57 while (nav.MoveToParent ())
67 public abstract XPathNavigator Clone ();
69 public virtual XmlNodeOrder ComparePosition (XPathNavigator nav)
71 if (IsSamePosition (nav))
72 return XmlNodeOrder.Same;
74 XPathNavigator nav1 = Clone ();
75 XPathNavigator nav2 = nav.Clone ();
77 int nDepth1 = nav1.Depth;
78 int nDepth2 = nav2.Depth;
80 if (nDepth1 > nDepth2)
82 while (nDepth1 > nDepth2)
87 if (nav1.IsSamePosition (nav2))
88 return XmlNodeOrder.After;
90 else if (nDepth1 < nDepth2)
92 while (nDepth1 < nDepth2)
97 if (nav1.IsSamePosition (nav2))
98 return XmlNodeOrder.Before;
101 XPathNavigator parent1 = nav1.Clone ();
102 XPathNavigator parent2 = nav2.Clone ();
103 while (parent1.MoveToParent () && parent2.MoveToParent ())
105 if (parent1.IsSamePosition (parent2))
107 // the ordering is namespace, attribute, children
108 // assume that nav1 is before nav2, find counter-example
109 if (nav1.NodeType == XPathNodeType.Namespace)
111 if (nav2.NodeType == XPathNodeType.Namespace)
114 while (nav2.MoveToNextNamespace ())
115 if (nav2.IsSamePosition (nav1))
116 return XmlNodeOrder.After;
119 else if (nav1.NodeType == XPathNodeType.Attribute)
121 if (nav2.NodeType == XPathNodeType.Namespace)
122 return XmlNodeOrder.After;
123 else if (nav2.NodeType == XPathNodeType.Attribute)
126 while (nav2.MoveToNextAttribute ())
127 if (nav2.IsSamePosition (nav1))
128 return XmlNodeOrder.After;
133 switch (nav2.NodeType) {
134 case XPathNodeType.Namespace:
135 case XPathNodeType.Attribute:
136 return XmlNodeOrder.After;
139 while (nav2.MoveToNext ())
140 if (nav2.IsSamePosition (nav1))
141 return XmlNodeOrder.After;
143 return XmlNodeOrder.Before;
145 nav1.MoveToParent ();
146 nav2.MoveToParent ();
148 return XmlNodeOrder.Unknown;
151 public virtual XPathExpression Compile (string xpath)
153 XPathParser parser = new XPathParser ();
154 return new CompiledExpression (parser.Compile (xpath));
157 internal virtual XPathExpression Compile (string xpath, System.Xml.Xsl.IStaticXsltContext ctx)
159 XPathParser parser = new XPathParser (ctx);
160 return new CompiledExpression (parser.Compile (xpath));
163 public virtual object Evaluate (string xpath)
165 return Evaluate (Compile (xpath));
168 public virtual object Evaluate (XPathExpression expr)
170 return Evaluate (expr, null);
173 public virtual object Evaluate (XPathExpression expr, XPathNodeIterator context)
175 return Evaluate (expr, context, null);
178 internal virtual object Evaluate (XPathExpression expr, XPathNodeIterator context, XmlNamespaceManager ctx)
180 CompiledExpression cexpr = (CompiledExpression) expr;
182 ctx = cexpr.NamespaceManager;
185 context = new NullIterator (this, ctx);
186 BaseIterator iterContext = (BaseIterator) context;
187 iterContext.NamespaceManager = ctx;
188 return cexpr.Evaluate (iterContext);
191 internal XPathNodeIterator EvaluateNodeSet (XPathExpression expr, XPathNodeIterator context, XmlNamespaceManager ctx)
193 CompiledExpression cexpr = (CompiledExpression) expr;
195 ctx = cexpr.NamespaceManager;
198 context = new NullIterator (this, cexpr.NamespaceManager);
199 BaseIterator iterContext = (BaseIterator) context;
200 iterContext.NamespaceManager = ctx;
201 return cexpr.EvaluateNodeSet (iterContext);
204 internal string EvaluateString (XPathExpression expr, XPathNodeIterator context, XmlNamespaceManager ctx)
206 CompiledExpression cexpr = (CompiledExpression) expr;
208 ctx = cexpr.NamespaceManager;
211 context = new NullIterator (this, cexpr.NamespaceManager);
212 BaseIterator iterContext = (BaseIterator) context;
213 iterContext.NamespaceManager = ctx;
214 return cexpr.EvaluateString (iterContext);
217 internal double EvaluateNumber (XPathExpression expr, XPathNodeIterator context, XmlNamespaceManager ctx)
219 CompiledExpression cexpr = (CompiledExpression) expr;
221 ctx = cexpr.NamespaceManager;
224 context = new NullIterator (this, cexpr.NamespaceManager);
225 BaseIterator iterContext = (BaseIterator) context;
226 iterContext.NamespaceManager = ctx;
227 return cexpr.EvaluateNumber (iterContext);
230 internal bool EvaluateBoolean (XPathExpression expr, XPathNodeIterator context, XmlNamespaceManager ctx)
232 CompiledExpression cexpr = (CompiledExpression) expr;
234 ctx = cexpr.NamespaceManager;
237 context = new NullIterator (this, cexpr.NamespaceManager);
238 BaseIterator iterContext = (BaseIterator) context;
239 iterContext.NamespaceManager = ctx;
240 return cexpr.EvaluateBoolean (iterContext);
243 public abstract string GetAttribute (string localName, string namespaceURI);
245 public abstract string GetNamespace (string name);
247 object ICloneable.Clone ()
252 public virtual bool IsDescendant (XPathNavigator nav)
257 while (nav.MoveToParent ())
259 if (IsSamePosition (nav))
266 public abstract bool IsSamePosition (XPathNavigator other);
268 public virtual bool Matches (string xpath)
270 return Matches (Compile (xpath));
273 [MonoTODO] // optimize...
274 public virtual bool Matches (XPathExpression expr)
276 Expression e = ((CompiledExpression)expr).ExpressionNode;
279 return ((NodeTest)e).Match (((CompiledExpression)expr).NamespaceManager, this);
280 if (e is ExprFilter) {
282 e = ((ExprFilter)e).LeftHandSide;
283 } while (e is ExprFilter);
285 if (e is NodeTest && !((NodeTest)e).Match (((CompiledExpression)expr).NamespaceManager, this))
289 //e = ((CompiledExpression)expr).ExpressionNode;
290 //Console.WriteLine ("Didnt filter : " + e.GetType ().ToString () + " " + e.ToString ());
292 XPathNodeIterator nodes = Select (expr);
294 while (nodes.MoveNext ()) {
295 if (IsSamePosition (nodes.Current))
299 XPathNavigator navigator = Clone ();
301 while (navigator.MoveToParent ()) {
302 nodes = navigator.Select (expr);
304 while (nodes.MoveNext ()) {
305 if (IsSamePosition (nodes.Current))
313 public abstract bool MoveTo (XPathNavigator other);
315 public abstract bool MoveToAttribute (string localName, string namespaceURI);
317 public abstract bool MoveToFirst ();
319 public abstract bool MoveToFirstAttribute ();
321 public abstract bool MoveToFirstChild ();
323 public bool MoveToFirstNamespace ()
325 return MoveToFirstNamespace (XPathNamespaceScope.All);
328 public abstract bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope);
330 public abstract bool MoveToId (string id);
332 public abstract bool MoveToNamespace (string name);
334 public abstract bool MoveToNext ();
336 public abstract bool MoveToNextAttribute ();
338 public bool MoveToNextNamespace ()
340 return MoveToNextNamespace (XPathNamespaceScope.All);
343 public abstract bool MoveToNextNamespace (XPathNamespaceScope namespaceScope);
345 public abstract bool MoveToParent ();
347 public abstract bool MoveToPrevious ();
349 public abstract void MoveToRoot ();
351 public virtual XPathNodeIterator Select (string xpath)
353 return Select (Compile (xpath));
356 public virtual XPathNodeIterator Select (XPathExpression expr)
358 return Select (expr, null);
361 internal virtual XPathNodeIterator Select (XPathExpression expr, XmlNamespaceManager ctx)
363 CompiledExpression cexpr = (CompiledExpression) expr;
365 ctx = cexpr.NamespaceManager;
367 BaseIterator iter = new NullIterator (this, ctx);
368 return cexpr.EvaluateNodeSet (iter);
371 public virtual XPathNodeIterator SelectAncestors (XPathNodeType type, bool matchSelf)
373 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
374 return SelectTest (new NodeTypeTest (axis, type));
377 public virtual XPathNodeIterator SelectAncestors (string name, string namespaceURI, bool matchSelf)
380 throw new ArgumentNullException ("name");
381 if (namespaceURI == null)
382 throw new ArgumentNullException ("namespaceURI");
384 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
385 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
386 return SelectTest (new NodeNameTest (axis, qname, true));
389 public virtual XPathNodeIterator SelectChildren (XPathNodeType type)
391 return SelectTest (new NodeTypeTest (Axes.Child, type));
394 public virtual XPathNodeIterator SelectChildren (string name, string namespaceURI)
397 throw new ArgumentNullException ("name");
398 if (namespaceURI == null)
399 throw new ArgumentNullException ("namespaceURI");
401 Axes axis = Axes.Child;
402 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
403 return SelectTest (new NodeNameTest (axis, qname, true));
406 public virtual XPathNodeIterator SelectDescendants (XPathNodeType type, bool matchSelf)
408 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
409 return SelectTest (new NodeTypeTest (axis, type));
412 public virtual XPathNodeIterator SelectDescendants (string name, string namespaceURI, bool matchSelf)
415 throw new ArgumentNullException ("name");
416 if (namespaceURI == null)
417 throw new ArgumentNullException ("namespaceURI");
420 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
421 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
422 return SelectTest (new NodeNameTest (axis, qname, true));
425 internal XPathNodeIterator SelectTest (NodeTest test)
427 return test.EvaluateNodeSet (new NullIterator (this));
430 public override string ToString ()