1 //------------------------------------------------------------------------------
2 // <copyright file="XPathDocumentIterator.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 using System.Xml.XPath;
10 using System.Diagnostics;
12 namespace MS.Internal.Xml.Cache {
15 /// Base internal class of all XPathDocument XPathNodeIterator implementations.
17 internal abstract class XPathDocumentBaseIterator : XPathNodeIterator {
18 protected XPathDocumentNavigator ctxt;
22 /// Create a new iterator that is initially positioned on the "ctxt" node.
24 protected XPathDocumentBaseIterator(XPathDocumentNavigator ctxt) {
25 this.ctxt = new XPathDocumentNavigator(ctxt);
29 /// Create a new iterator that is a copy of "iter".
31 protected XPathDocumentBaseIterator(XPathDocumentBaseIterator iter) {
32 this.ctxt = new XPathDocumentNavigator(iter.ctxt);
37 /// Return the current navigator.
39 public override XPathNavigator Current {
40 get { return this.ctxt; }
44 /// Return the iterator's current position.
46 public override int CurrentPosition {
47 get { return this.pos; }
53 /// Iterate over all element children with a particular QName.
55 internal class XPathDocumentElementChildIterator : XPathDocumentBaseIterator {
56 private string localName, namespaceUri;
59 /// Create an iterator that ranges over all element children of "parent" having the specified QName.
61 public XPathDocumentElementChildIterator(XPathDocumentNavigator parent, string name, string namespaceURI) : base(parent) {
62 if (namespaceURI == null) throw new ArgumentNullException("namespaceURI");
64 this.localName = parent.NameTable.Get(name);
65 this.namespaceUri = namespaceURI;
69 /// Create a new iterator that is a copy of "iter".
71 public XPathDocumentElementChildIterator(XPathDocumentElementChildIterator iter) : base(iter) {
72 this.localName = iter.localName;
73 this.namespaceUri = iter.namespaceUri;
77 /// Create a copy of this iterator.
79 public override XPathNodeIterator Clone() {
80 return new XPathDocumentElementChildIterator(this);
84 /// Position the iterator to the next matching child.
86 public override bool MoveNext() {
88 if (!this.ctxt.MoveToChild(this.localName, this.namespaceUri))
92 if (!this.ctxt.MoveToNext(this.localName, this.namespaceUri))
103 /// Iterate over all content children with a particular XPathNodeType.
105 internal class XPathDocumentKindChildIterator : XPathDocumentBaseIterator {
106 private XPathNodeType typ;
109 /// Create an iterator that ranges over all content children of "parent" having the specified XPathNodeType.
111 public XPathDocumentKindChildIterator(XPathDocumentNavigator parent, XPathNodeType typ) : base(parent) {
116 /// Create a new iterator that is a copy of "iter".
118 public XPathDocumentKindChildIterator(XPathDocumentKindChildIterator iter) : base(iter) {
123 /// Create a copy of this iterator.
125 public override XPathNodeIterator Clone() {
126 return new XPathDocumentKindChildIterator(this);
130 /// Position the iterator to the next descendant.
132 public override bool MoveNext() {
134 if (!this.ctxt.MoveToChild(this.typ))
138 if (!this.ctxt.MoveToNext(this.typ))
149 /// Iterate over all element descendants with a particular QName.
151 internal class XPathDocumentElementDescendantIterator : XPathDocumentBaseIterator {
152 private XPathDocumentNavigator end;
153 private string localName, namespaceUri;
154 private bool matchSelf;
157 /// Create an iterator that ranges over all element descendants of "root" having the specified QName.
159 public XPathDocumentElementDescendantIterator(XPathDocumentNavigator root, string name, string namespaceURI, bool matchSelf) : base(root) {
160 if (namespaceURI == null) throw new ArgumentNullException("namespaceURI");
162 this.localName = root.NameTable.Get(name);
163 this.namespaceUri = namespaceURI;
164 this.matchSelf = matchSelf;
166 // Find the next non-descendant node that follows "root" in document order
167 if (root.NodeType != XPathNodeType.Root) {
168 this.end = new XPathDocumentNavigator(root);
169 this.end.MoveToNonDescendant();
174 /// Create a new iterator that is a copy of "iter".
176 public XPathDocumentElementDescendantIterator(XPathDocumentElementDescendantIterator iter) : base(iter) {
178 this.localName = iter.localName;
179 this.namespaceUri = iter.namespaceUri;
180 this.matchSelf = iter.matchSelf;
184 /// Create a copy of this iterator.
186 public override XPathNodeIterator Clone() {
187 return new XPathDocumentElementDescendantIterator(this);
191 /// Position the iterator to the next descendant.
193 public override bool MoveNext() {
194 if (this.matchSelf) {
195 this.matchSelf = false;
197 if (this.ctxt.IsElementMatch(this.localName, this.namespaceUri)) {
203 if (!this.ctxt.MoveToFollowing(this.localName, this.namespaceUri, this.end))
213 /// Iterate over all content descendants with a particular XPathNodeType.
215 internal class XPathDocumentKindDescendantIterator : XPathDocumentBaseIterator {
216 private XPathDocumentNavigator end;
217 private XPathNodeType typ;
218 private bool matchSelf;
221 /// Create an iterator that ranges over all content descendants of "root" having the specified XPathNodeType.
223 public XPathDocumentKindDescendantIterator(XPathDocumentNavigator root, XPathNodeType typ, bool matchSelf) : base(root) {
225 this.matchSelf = matchSelf;
227 // Find the next non-descendant node that follows "root" in document order
228 if (root.NodeType != XPathNodeType.Root) {
229 this.end = new XPathDocumentNavigator(root);
230 this.end.MoveToNonDescendant();
235 /// Create a new iterator that is a copy of "iter".
237 public XPathDocumentKindDescendantIterator(XPathDocumentKindDescendantIterator iter) : base(iter) {
240 this.matchSelf = iter.matchSelf;
244 /// Create a copy of this iterator.
246 public override XPathNodeIterator Clone() {
247 return new XPathDocumentKindDescendantIterator(this);
251 /// Position the iterator to the next descendant.
253 public override bool MoveNext() {
254 if (this.matchSelf) {
255 this.matchSelf = false;
257 if (this.ctxt.IsKindMatch(this.typ)) {
263 if (!this.ctxt.MoveToFollowing(this.typ, this.end))