| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- //------------------------------------------------------------------------------
- // <copyright file="XPathDocumentIterator.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">Microsoft</owner>
- //------------------------------------------------------------------------------
- using System;
- using System.Xml;
- using System.Xml.XPath;
- using System.Diagnostics;
- namespace MS.Internal.Xml.Cache {
- /// <summary>
- /// Base internal class of all XPathDocument XPathNodeIterator implementations.
- /// </summary>
- internal abstract class XPathDocumentBaseIterator : XPathNodeIterator {
- protected XPathDocumentNavigator ctxt;
- protected int pos;
- /// <summary>
- /// Create a new iterator that is initially positioned on the "ctxt" node.
- /// </summary>
- protected XPathDocumentBaseIterator(XPathDocumentNavigator ctxt) {
- this.ctxt = new XPathDocumentNavigator(ctxt);
- }
- /// <summary>
- /// Create a new iterator that is a copy of "iter".
- /// </summary>
- protected XPathDocumentBaseIterator(XPathDocumentBaseIterator iter) {
- this.ctxt = new XPathDocumentNavigator(iter.ctxt);
- this.pos = iter.pos;
- }
- /// <summary>
- /// Return the current navigator.
- /// </summary>
- public override XPathNavigator Current {
- get { return this.ctxt; }
- }
- /// <summary>
- /// Return the iterator's current position.
- /// </summary>
- public override int CurrentPosition {
- get { return this.pos; }
- }
- }
- /// <summary>
- /// Iterate over all element children with a particular QName.
- /// </summary>
- internal class XPathDocumentElementChildIterator : XPathDocumentBaseIterator {
- private string localName, namespaceUri;
- /// <summary>
- /// Create an iterator that ranges over all element children of "parent" having the specified QName.
- /// </summary>
- public XPathDocumentElementChildIterator(XPathDocumentNavigator parent, string name, string namespaceURI) : base(parent) {
- if (namespaceURI == null) throw new ArgumentNullException("namespaceURI");
- this.localName = parent.NameTable.Get(name);
- this.namespaceUri = namespaceURI;
- }
- /// <summary>
- /// Create a new iterator that is a copy of "iter".
- /// </summary>
- public XPathDocumentElementChildIterator(XPathDocumentElementChildIterator iter) : base(iter) {
- this.localName = iter.localName;
- this.namespaceUri = iter.namespaceUri;
- }
- /// <summary>
- /// Create a copy of this iterator.
- /// </summary>
- public override XPathNodeIterator Clone() {
- return new XPathDocumentElementChildIterator(this);
- }
- /// <summary>
- /// Position the iterator to the next matching child.
- /// </summary>
- public override bool MoveNext() {
- if (this.pos == 0) {
- if (!this.ctxt.MoveToChild(this.localName, this.namespaceUri))
- return false;
- }
- else {
- if (!this.ctxt.MoveToNext(this.localName, this.namespaceUri))
- return false;
- }
- this.pos++;
- return true;
- }
- }
- /// <summary>
- /// Iterate over all content children with a particular XPathNodeType.
- /// </summary>
- internal class XPathDocumentKindChildIterator : XPathDocumentBaseIterator {
- private XPathNodeType typ;
- /// <summary>
- /// Create an iterator that ranges over all content children of "parent" having the specified XPathNodeType.
- /// </summary>
- public XPathDocumentKindChildIterator(XPathDocumentNavigator parent, XPathNodeType typ) : base(parent) {
- this.typ = typ;
- }
- /// <summary>
- /// Create a new iterator that is a copy of "iter".
- /// </summary>
- public XPathDocumentKindChildIterator(XPathDocumentKindChildIterator iter) : base(iter) {
- this.typ = iter.typ;
- }
- /// <summary>
- /// Create a copy of this iterator.
- /// </summary>
- public override XPathNodeIterator Clone() {
- return new XPathDocumentKindChildIterator(this);
- }
- /// <summary>
- /// Position the iterator to the next descendant.
- /// </summary>
- public override bool MoveNext() {
- if (this.pos == 0) {
- if (!this.ctxt.MoveToChild(this.typ))
- return false;
- }
- else {
- if (!this.ctxt.MoveToNext(this.typ))
- return false;
- }
- this.pos++;
- return true;
- }
- }
- /// <summary>
- /// Iterate over all element descendants with a particular QName.
- /// </summary>
- internal class XPathDocumentElementDescendantIterator : XPathDocumentBaseIterator {
- private XPathDocumentNavigator end;
- private string localName, namespaceUri;
- private bool matchSelf;
- /// <summary>
- /// Create an iterator that ranges over all element descendants of "root" having the specified QName.
- /// </summary>
- public XPathDocumentElementDescendantIterator(XPathDocumentNavigator root, string name, string namespaceURI, bool matchSelf) : base(root) {
- if (namespaceURI == null) throw new ArgumentNullException("namespaceURI");
- this.localName = root.NameTable.Get(name);
- this.namespaceUri = namespaceURI;
- this.matchSelf = matchSelf;
- // Find the next non-descendant node that follows "root" in document order
- if (root.NodeType != XPathNodeType.Root) {
- this.end = new XPathDocumentNavigator(root);
- this.end.MoveToNonDescendant();
- }
- }
- /// <summary>
- /// Create a new iterator that is a copy of "iter".
- /// </summary>
- public XPathDocumentElementDescendantIterator(XPathDocumentElementDescendantIterator iter) : base(iter) {
- this.end = iter.end;
- this.localName = iter.localName;
- this.namespaceUri = iter.namespaceUri;
- this.matchSelf = iter.matchSelf;
- }
- /// <summary>
- /// Create a copy of this iterator.
- /// </summary>
- public override XPathNodeIterator Clone() {
- return new XPathDocumentElementDescendantIterator(this);
- }
- /// <summary>
- /// Position the iterator to the next descendant.
- /// </summary>
- public override bool MoveNext() {
- if (this.matchSelf) {
- this.matchSelf = false;
- if (this.ctxt.IsElementMatch(this.localName, this.namespaceUri)) {
- this.pos++;
- return true;
- }
- }
- if (!this.ctxt.MoveToFollowing(this.localName, this.namespaceUri, this.end))
- return false;
- this.pos++;
- return true;
- }
- }
- /// <summary>
- /// Iterate over all content descendants with a particular XPathNodeType.
- /// </summary>
- internal class XPathDocumentKindDescendantIterator : XPathDocumentBaseIterator {
- private XPathDocumentNavigator end;
- private XPathNodeType typ;
- private bool matchSelf;
- /// <summary>
- /// Create an iterator that ranges over all content descendants of "root" having the specified XPathNodeType.
- /// </summary>
- public XPathDocumentKindDescendantIterator(XPathDocumentNavigator root, XPathNodeType typ, bool matchSelf) : base(root) {
- this.typ = typ;
- this.matchSelf = matchSelf;
- // Find the next non-descendant node that follows "root" in document order
- if (root.NodeType != XPathNodeType.Root) {
- this.end = new XPathDocumentNavigator(root);
- this.end.MoveToNonDescendant();
- }
- }
- /// <summary>
- /// Create a new iterator that is a copy of "iter".
- /// </summary>
- public XPathDocumentKindDescendantIterator(XPathDocumentKindDescendantIterator iter) : base(iter) {
- this.end = iter.end;
- this.typ = iter.typ;
- this.matchSelf = iter.matchSelf;
- }
- /// <summary>
- /// Create a copy of this iterator.
- /// </summary>
- public override XPathNodeIterator Clone() {
- return new XPathDocumentKindDescendantIterator(this);
- }
- /// <summary>
- /// Position the iterator to the next descendant.
- /// </summary>
- public override bool MoveNext() {
- if (this.matchSelf) {
- this.matchSelf = false;
- if (this.ctxt.IsKindMatch(this.typ)) {
- this.pos++;
- return true;
- }
- }
- if (!this.ctxt.MoveToFollowing(this.typ, this.end))
- return false;
- this.pos++;
- return true;
- }
- }
- }
|