2 // System.Xml.XPath.XPathNavigator
5 // Jason Diamond (jason@injektilo.org)
6 // Atsushi Enomoto (atsushi@ximian.com)
8 // (C) 2002 Jason Diamond http://injektilo.org/
9 // (C) 2004 Novell Inc.
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
36 using System.Xml.Schema;
40 using NSResolver = System.Xml.IXmlNamespaceResolver;
42 using NSResolver = System.Xml.XmlNamespaceManager;
45 namespace System.Xml.XPath
48 public abstract class XPathNavigator : XPathItem,
49 ICloneable, IXPathNavigable, IXmlNamespaceResolver
51 public abstract class XPathNavigator : ICloneable
56 protected XPathNavigator ()
64 public abstract string BaseURI { get; }
66 public abstract bool HasAttributes { get; }
68 public abstract bool HasChildren { get; }
70 public abstract bool IsEmptyElement { get; }
72 public abstract string LocalName { get; }
74 public abstract string Name { get; }
76 public abstract string NamespaceURI { get; }
78 public abstract XmlNameTable NameTable { get; }
80 public abstract XPathNodeType NodeType { get; }
82 public abstract string Prefix { get; }
86 public abstract string Value { get; }
89 public abstract string XmlLang { get; }
96 XPathNavigator nav = Clone ();
97 while (nav.MoveToParent ())
107 public abstract XPathNavigator Clone ();
109 public virtual XmlNodeOrder ComparePosition (XPathNavigator nav)
111 if (IsSamePosition (nav))
112 return XmlNodeOrder.Same;
114 XPathNavigator nav1 = Clone ();
115 XPathNavigator nav2 = nav.Clone ();
117 int nDepth1 = nav1.Depth;
118 int nDepth2 = nav2.Depth;
120 if (nDepth1 > nDepth2)
122 while (nDepth1 > nDepth2)
124 if (!nav1.MoveToParent ())
128 if (nav1.IsSamePosition (nav2))
129 return XmlNodeOrder.After;
131 else if (nDepth1 < nDepth2)
133 while (nDepth1 < nDepth2)
135 if (!nav2.MoveToParent ())
139 if (nav1.IsSamePosition (nav2))
140 return XmlNodeOrder.Before;
143 XPathNavigator parent1 = nav1.Clone ();
144 XPathNavigator parent2 = nav2.Clone ();
145 while (parent1.MoveToParent () && parent2.MoveToParent ())
147 if (parent1.IsSamePosition (parent2))
149 // the ordering is namespace, attribute, children
150 // assume that nav1 is before nav2, find counter-example
151 if (nav1.NodeType == XPathNodeType.Namespace)
153 if (nav2.NodeType == XPathNodeType.Namespace)
156 while (nav2.MoveToNextNamespace ())
157 if (nav2.IsSamePosition (nav1))
158 return XmlNodeOrder.After;
161 else if (nav1.NodeType == XPathNodeType.Attribute)
163 if (nav2.NodeType == XPathNodeType.Namespace)
164 return XmlNodeOrder.After;
165 else if (nav2.NodeType == XPathNodeType.Attribute)
168 while (nav2.MoveToNextAttribute ())
169 if (nav2.IsSamePosition (nav1))
170 return XmlNodeOrder.After;
175 switch (nav2.NodeType) {
176 case XPathNodeType.Namespace:
177 case XPathNodeType.Attribute:
178 return XmlNodeOrder.After;
181 while (nav2.MoveToNext ())
182 if (nav2.IsSamePosition (nav1))
183 return XmlNodeOrder.After;
185 return XmlNodeOrder.Before;
187 nav1.MoveToParent ();
188 nav2.MoveToParent ();
190 return XmlNodeOrder.Unknown;
193 public virtual XPathExpression Compile (string xpath)
195 XPathParser parser = new XPathParser ();
196 return new CompiledExpression (parser.Compile (xpath));
199 internal virtual XPathExpression Compile (string xpath, System.Xml.Xsl.IStaticXsltContext ctx)
201 XPathParser parser = new XPathParser (ctx);
202 return new CompiledExpression (parser.Compile (xpath));
205 public virtual object Evaluate (string xpath)
207 return Evaluate (Compile (xpath));
210 public virtual object Evaluate (XPathExpression expr)
212 return Evaluate (expr, null);
215 public virtual object Evaluate (XPathExpression expr, XPathNodeIterator context)
217 return Evaluate (expr, context, null);
220 internal virtual object Evaluate (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
222 CompiledExpression cexpr = (CompiledExpression) expr;
224 ctx = cexpr.NamespaceManager;
227 context = new NullIterator (this, ctx);
228 BaseIterator iterContext = (BaseIterator) context;
229 iterContext.NamespaceManager = ctx;
230 return cexpr.Evaluate (iterContext);
233 internal XPathNodeIterator EvaluateNodeSet (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
235 CompiledExpression cexpr = (CompiledExpression) expr;
237 ctx = cexpr.NamespaceManager;
240 context = new NullIterator (this, cexpr.NamespaceManager);
241 BaseIterator iterContext = (BaseIterator) context;
242 iterContext.NamespaceManager = ctx;
243 return cexpr.EvaluateNodeSet (iterContext);
246 internal string EvaluateString (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
248 CompiledExpression cexpr = (CompiledExpression) expr;
250 ctx = cexpr.NamespaceManager;
253 context = new NullIterator (this, cexpr.NamespaceManager);
254 BaseIterator iterContext = (BaseIterator) context;
255 iterContext.NamespaceManager = ctx;
256 return cexpr.EvaluateString (iterContext);
259 internal double EvaluateNumber (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
261 CompiledExpression cexpr = (CompiledExpression) expr;
263 ctx = cexpr.NamespaceManager;
266 context = new NullIterator (this, cexpr.NamespaceManager);
267 BaseIterator iterContext = (BaseIterator) context;
268 iterContext.NamespaceManager = ctx;
269 return cexpr.EvaluateNumber (iterContext);
272 internal bool EvaluateBoolean (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
274 CompiledExpression cexpr = (CompiledExpression) expr;
276 ctx = cexpr.NamespaceManager;
279 context = new NullIterator (this, cexpr.NamespaceManager);
280 BaseIterator iterContext = (BaseIterator) context;
281 iterContext.NamespaceManager = ctx;
282 return cexpr.EvaluateBoolean (iterContext);
285 public abstract string GetAttribute (string localName, string namespaceURI);
287 public abstract string GetNamespace (string name);
289 object ICloneable.Clone ()
294 public virtual bool IsDescendant (XPathNavigator nav)
299 while (nav.MoveToParent ())
301 if (IsSamePosition (nav))
308 public abstract bool IsSamePosition (XPathNavigator other);
310 public virtual bool Matches (string xpath)
312 return Matches (Compile (xpath));
315 public virtual bool Matches (XPathExpression expr)
317 Expression e = ((CompiledExpression) expr).ExpressionNode;
319 return NodeType == XPathNodeType.Root;
321 NodeTest nt = e as NodeTest;
323 switch (nt.Axis.Axis) {
328 throw new XPathException ("Only child and attribute pattern are allowed for a pattern.");
330 return nt.Match (((CompiledExpression)expr).NamespaceManager, this);
332 if (e is ExprFilter) {
334 e = ((ExprFilter) e).LeftHandSide;
335 } while (e is ExprFilter);
337 if (e is NodeTest && !((NodeTest) e).Match (((CompiledExpression) expr).NamespaceManager, this))
341 XPathResultType resultType = e.ReturnType;
342 switch (resultType) {
343 case XPathResultType.Any:
344 case XPathResultType.NodeSet:
350 switch (e.EvaluatedNodeType) {
351 case XPathNodeType.Attribute:
352 case XPathNodeType.Namespace:
353 if (NodeType != e.EvaluatedNodeType)
358 XPathNodeIterator nodes;
359 nodes = this.Select (expr);
360 while (nodes.MoveNext ()) {
361 if (IsSamePosition (nodes.Current))
365 // ancestors might select this node.
367 XPathNavigator navigator = Clone ();
369 while (navigator.MoveToParent ()) {
370 nodes = navigator.Select (expr);
372 while (nodes.MoveNext ()) {
373 if (IsSamePosition (nodes.Current))
381 public abstract bool MoveTo (XPathNavigator other);
383 public abstract bool MoveToAttribute (string localName, string namespaceURI);
385 public abstract bool MoveToFirst ();
387 public abstract bool MoveToFirstAttribute ();
389 public abstract bool MoveToFirstChild ();
391 public bool MoveToFirstNamespace ()
393 return MoveToFirstNamespace (XPathNamespaceScope.All);
396 public abstract bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope);
398 public abstract bool MoveToId (string id);
400 public abstract bool MoveToNamespace (string name);
402 public abstract bool MoveToNext ();
404 public abstract bool MoveToNextAttribute ();
406 public bool MoveToNextNamespace ()
408 return MoveToNextNamespace (XPathNamespaceScope.All);
411 public abstract bool MoveToNextNamespace (XPathNamespaceScope namespaceScope);
413 public abstract bool MoveToParent ();
415 public abstract bool MoveToPrevious ();
417 public abstract void MoveToRoot ();
419 public virtual XPathNodeIterator Select (string xpath)
421 return Select (Compile (xpath));
424 public virtual XPathNodeIterator Select (XPathExpression expr)
426 return Select (expr, null);
429 internal virtual XPathNodeIterator Select (XPathExpression expr, NSResolver ctx)
431 CompiledExpression cexpr = (CompiledExpression) expr;
433 ctx = cexpr.NamespaceManager;
435 BaseIterator iter = new NullIterator (this, ctx);
436 return cexpr.EvaluateNodeSet (iter);
439 public virtual XPathNodeIterator SelectAncestors (XPathNodeType type, bool matchSelf)
441 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
442 return SelectTest (new NodeTypeTest (axis, type));
445 public virtual XPathNodeIterator SelectAncestors (string name, string namespaceURI, bool matchSelf)
448 throw new ArgumentNullException ("name");
449 if (namespaceURI == null)
450 throw new ArgumentNullException ("namespaceURI");
452 Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
453 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
454 return SelectTest (new NodeNameTest (axis, qname, true));
457 public virtual XPathNodeIterator SelectChildren (XPathNodeType type)
459 return SelectTest (new NodeTypeTest (Axes.Child, type));
462 public virtual XPathNodeIterator SelectChildren (string name, string namespaceURI)
465 throw new ArgumentNullException ("name");
466 if (namespaceURI == null)
467 throw new ArgumentNullException ("namespaceURI");
469 Axes axis = Axes.Child;
470 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
471 return SelectTest (new NodeNameTest (axis, qname, true));
474 public virtual XPathNodeIterator SelectDescendants (XPathNodeType type, bool matchSelf)
476 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
477 return SelectTest (new NodeTypeTest (axis, type));
480 public virtual XPathNodeIterator SelectDescendants (string name, string namespaceURI, bool matchSelf)
483 throw new ArgumentNullException ("name");
484 if (namespaceURI == null)
485 throw new ArgumentNullException ("namespaceURI");
488 Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
489 XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
490 return SelectTest (new NodeNameTest (axis, qname, true));
493 internal XPathNodeIterator SelectTest (NodeTest test)
495 return test.EvaluateNodeSet (new NullIterator (this));
498 public override string ToString ()
508 public virtual bool CheckValidity (XmlSchemaSet schemas, ValidationEventHandler handler)
510 throw new NotImplementedException ();
514 public virtual object CopyAsObject (Type targetType)
516 throw new NotImplementedException ();
519 public virtual XPathNavigator CreateNavigator ()
525 public virtual object Evaluate (string xpath, IXmlNamespaceResolver nsResolver)
527 return Evaluate (Compile (xpath), null, nsResolver);
531 public virtual IDictionary GetNamespacesInScope (XmlNamespaceScope scope)
533 throw new NotImplementedException ();
536 public virtual string LookupNamespace (string prefix)
538 return LookupNamespace (prefix, false);
542 public virtual string LookupNamespace (string prefix, bool atomizedNames)
544 throw new NotImplementedException ();
547 public virtual string LookupPrefix (string namespaceUri)
549 return LookupPrefix (namespaceUri, false);
553 public virtual string LookupPrefix (string namespaceUri, bool atomizedNames)
555 throw new NotImplementedException ();
559 public virtual XmlReader ReadSubtree ()
561 throw new NotImplementedException ();
564 public virtual XPathNavigator SelectSingleNode (string xpath)
566 return SelectSingleNode (xpath, null);
570 public virtual XPathNavigator SelectSingleNode (string xpath, IXmlNamespaceResolver nsResolver)
572 throw new NotImplementedException ();
575 public override object ValueAs (Type type)
577 return ValueAs (type, this);
581 public override object ValueAs (Type type, IXmlNamespaceResolver nsResolver)
583 throw new NotImplementedException ();
587 public virtual XmlWriter WriteSubtree ()
589 throw new NotImplementedException ();
593 public virtual string InnerXml {
594 get { throw new NotImplementedException (); }
598 public override bool IsNode {
599 get { throw new NotImplementedException (); }
603 public virtual IKeyComparer NavigatorComparer {
604 get { throw new NotImplementedException (); }
608 public virtual string OuterXml {
609 get { throw new NotImplementedException (); }
613 public virtual IXmlSchemaInfo SchemaInfo {
614 get { throw new NotImplementedException (); }
618 public virtual object TypedValue {
619 get { throw new NotImplementedException (); }
623 public virtual object UnderlyingObject {
624 get { throw new NotImplementedException (); }
628 public override bool ValueAsBoolean {
629 get { throw new NotImplementedException (); }
633 public override DateTime ValueAsDateTime {
634 get { throw new NotImplementedException (); }
638 public override decimal ValueAsDecimal {
639 get { throw new NotImplementedException (); }
643 public override double ValueAsDouble {
644 get { throw new NotImplementedException (); }
648 public override int ValueAsInt32 {
649 get { throw new NotImplementedException (); }
653 public override long ValueAsInt64 {
654 get { throw new NotImplementedException (); }
658 public override ICollection ValueAsList {
659 get { throw new NotImplementedException (); }
663 public override float ValueAsSingle {
664 get { throw new NotImplementedException (); }
668 public virtual Type ValueType {
669 get { throw new NotImplementedException (); }
673 public virtual XmlSchemaType XmlType {
674 get { throw new NotImplementedException (); }
678 protected XmlReader GetValidatingReader (XmlSchemaSet schemas, ValidationEventHandler handler)
680 throw new NotImplementedException ();