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 ();
70 public virtual XmlNodeOrder ComparePosition (XPathNavigator nav)
72 if (IsSamePosition (nav))
73 return XmlNodeOrder.Same;
75 XPathNavigator nav1 = Clone ();
76 XPathNavigator nav2 = nav.Clone ();
78 int nDepth1 = nav1.Depth;
79 int nDepth2 = nav2.Depth;
81 if (nDepth1 > nDepth2)
83 while (nDepth1 > nDepth2)
88 if (nav1.IsSamePosition (nav2))
89 return XmlNodeOrder.After;
91 else if (nDepth1 < nDepth2)
93 while (nDepth1 < nDepth2)
98 if (nav1.IsSamePosition (nav2))
99 return XmlNodeOrder.Before;
102 XPathNavigator parent1 = nav1.Clone ();
103 XPathNavigator parent2 = nav2.Clone ();
104 while (parent1.MoveToParent () && parent2.MoveToParent ())
106 if (parent1.IsSamePosition (parent2))
108 // the ordering is namespace, attribute, children
109 // assume that nav1 is before nav2, find counter-example
110 if (nav1.NodeType == XPathNodeType.Namespace)
112 if (nav2.NodeType == XPathNodeType.Namespace)
115 while (nav2.MoveToNextNamespace ())
116 if (nav2.IsSamePosition (nav1))
117 return XmlNodeOrder.After;
120 else if (nav1.NodeType == XPathNodeType.Attribute)
122 if (nav2.NodeType == XPathNodeType.Namespace)
123 return XmlNodeOrder.After;
124 else if (nav2.NodeType == XPathNodeType.Attribute)
127 while (nav2.MoveToNextAttribute ())
128 if (nav2.IsSamePosition (nav1))
129 return XmlNodeOrder.After;
135 while (nav2.MoveToNext ())
136 if (nav2.IsSamePosition (nav1))
137 return XmlNodeOrder.After;
139 return XmlNodeOrder.Before;
141 nav1.MoveToParent ();
142 nav2.MoveToParent ();
144 return XmlNodeOrder.Unknown;
147 public virtual XPathExpression Compile (string xpath)
149 Tokenizer tokenizer = new Tokenizer (xpath);
150 XPathParser parser = new XPathParser ();
151 Expression expr = (Expression) parser.yyparseSafe (tokenizer);
152 // Expression expr = (Expression) parser.yyparseDebug (tokenizer);
153 return new CompiledExpression (expr);
156 public virtual object Evaluate (string xpath)
158 return Evaluate (Compile (xpath));
161 public virtual object Evaluate (XPathExpression expr)
163 return Evaluate (expr, null);
166 public virtual object Evaluate (XPathExpression expr, XPathNodeIterator context)
168 CompiledExpression cexpr = (CompiledExpression) expr;
170 context = new NullIterator (this, cexpr.NamespaceManager);
171 BaseIterator iterContext = (BaseIterator) context;
172 iterContext.NamespaceManager = cexpr.NamespaceManager;
173 return cexpr.Evaluate (iterContext);
176 internal XPathNodeIterator EvaluateNodeSet (XPathExpression expr, XPathNodeIterator context)
178 CompiledExpression cexpr = (CompiledExpression) expr;
180 context = new NullIterator (this, cexpr.NamespaceManager);
181 BaseIterator iterContext = (BaseIterator) context;
182 iterContext.NamespaceManager = cexpr.NamespaceManager;
183 return cexpr.EvaluateNodeSet (iterContext);
186 internal string EvaluateString (XPathExpression expr, XPathNodeIterator context)
188 CompiledExpression cexpr = (CompiledExpression) expr;
190 context = new NullIterator (this, cexpr.NamespaceManager);
191 BaseIterator iterContext = (BaseIterator) context;
192 iterContext.NamespaceManager = cexpr.NamespaceManager;
193 return cexpr.EvaluateString (iterContext);
196 internal double EvaluateNumber (XPathExpression expr, XPathNodeIterator context)
198 CompiledExpression cexpr = (CompiledExpression) expr;
200 context = new NullIterator (this, cexpr.NamespaceManager);
201 BaseIterator iterContext = (BaseIterator) context;
202 iterContext.NamespaceManager = cexpr.NamespaceManager;
203 return cexpr.EvaluateNumber (iterContext);
206 internal bool EvaluateBoolean (XPathExpression expr, XPathNodeIterator context)
208 CompiledExpression cexpr = (CompiledExpression) expr;
210 context = new NullIterator (this, cexpr.NamespaceManager);
211 BaseIterator iterContext = (BaseIterator) context;
212 iterContext.NamespaceManager = cexpr.NamespaceManager;
213 return cexpr.EvaluateBoolean (iterContext);
216 public abstract string GetAttribute (string localName, string namespaceURI);
218 public abstract string GetNamespace (string name);
220 object ICloneable.Clone ()
225 public virtual bool IsDescendant (XPathNavigator nav)
230 while (nav.MoveToParent ())
232 if (IsSamePosition (nav))
239 public abstract bool IsSamePosition (XPathNavigator other);
241 public virtual bool Matches (string xpath)
243 return Matches (Compile (xpath));
246 public virtual bool Matches (XPathExpression expr)
248 XPathNodeIterator nodes = Select (expr);
250 while (nodes.MoveNext ()) {
251 if (IsSamePosition (nodes.Current))
255 XPathNavigator navigator = Clone ();
257 while (navigator.MoveToParent ()) {
258 nodes = navigator.Select (expr);
260 while (nodes.MoveNext ()) {
261 if (IsSamePosition (nodes.Current))
269 public abstract bool MoveTo (XPathNavigator other);
271 public abstract bool MoveToAttribute (string localName, string namespaceURI);
273 public abstract bool MoveToFirst ();
275 public abstract bool MoveToFirstAttribute ();
277 public abstract bool MoveToFirstChild ();
279 public bool MoveToFirstNamespace ()
281 return MoveToFirstNamespace (XPathNamespaceScope.All);
284 public abstract bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope);
286 public abstract bool MoveToId (string id);
288 public abstract bool MoveToNamespace (string name);
290 public abstract bool MoveToNext ();
292 public abstract bool MoveToNextAttribute ();
294 public bool MoveToNextNamespace ()
296 return MoveToNextNamespace (XPathNamespaceScope.All);
299 public abstract bool MoveToNextNamespace (XPathNamespaceScope namespaceScope);
301 public abstract bool MoveToParent ();
303 public abstract bool MoveToPrevious ();
305 public abstract void MoveToRoot ();
307 public virtual XPathNodeIterator Select (string xpath)
309 return Select (Compile (xpath));
312 public virtual XPathNodeIterator Select (XPathExpression expr)
314 CompiledExpression cexpr = (CompiledExpression) expr;
315 BaseIterator iter = new NullIterator (this, cexpr.NamespaceManager);
316 return cexpr.EvaluateNodeSet (iter);
319 public virtual XPathNodeIterator SelectAncestors (XPathNodeType type, bool matchSelf)
321 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
322 NodeTest test = new NodeTypeTest (axis, type);
323 return SelectTest (test);
327 public virtual XPathNodeIterator SelectAncestors (string name, string namespaceURI, bool matchSelf)
329 if (namespaceURI != null && namespaceURI != "")
330 throw new NotImplementedException ();
332 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
333 XmlQualifiedName qname = new XmlQualifiedName (name);
334 NodeTest test = new NodeNameTest (axis, qname);
335 return SelectTest (test);
338 public virtual XPathNodeIterator SelectChildren (XPathNodeType type)
340 NodeTest test = new NodeTypeTest (Axes.Child, type);
341 return SelectTest (test);
345 public virtual XPathNodeIterator SelectChildren (string name, string namespaceURI)
347 if (namespaceURI != null && namespaceURI != "")
348 throw new NotImplementedException ();
350 Axes axis = Axes.Child;
351 XmlQualifiedName qname = new XmlQualifiedName (name);
352 NodeTest test = new NodeNameTest (axis, qname);
353 return SelectTest (test);
356 public virtual XPathNodeIterator SelectDescendants (XPathNodeType type, bool matchSelf)
358 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
359 NodeTest test = new NodeTypeTest (axis, type);
360 return SelectTest (test);
364 public virtual XPathNodeIterator SelectDescendants (string name, string namespaceURI, bool matchSelf)
366 if (namespaceURI != null && namespaceURI != "")
367 throw new NotImplementedException ();
369 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
370 XmlQualifiedName qname = new XmlQualifiedName (name);
371 NodeTest test = new NodeNameTest (axis, qname);
372 return SelectTest (test);
375 internal XPathNodeIterator SelectTest (NodeTest test)
377 Expression expr = new ExprStep (test, null);
378 BaseIterator iter = new NullIterator (this, null);
379 return expr.EvaluateNodeSet (iter);
382 public override string ToString ()