public bool MoveNext() { if (_needFirst) { // Get first matching preceding-sibling node if (!_navCurrent.MoveToParent()) { return(false); } if (!_filter.MoveToContent(_navCurrent)) { return(false); } _needFirst = false; } else { // Get next matching preceding-sibling node if (!_filter.MoveToFollowingSibling(_navCurrent)) { return(false); } } // Accept matching sibling only if it precedes navEnd in document order if (_useCompPos) { return(_navCurrent.ComparePosition(_navEnd) == XmlNodeOrder.Before); } if (_navCurrent.IsSamePosition(_navEnd)) { // Found the original context node, so iteration is complete. If MoveNext // is called again, use ComparePosition so that false will continue to be // returned. _useCompPos = true; return(false); } return(true); }
/// <summary> /// Position this iterator to the next content or sibling node. Return IteratorResult.NoMoreNodes if there are /// no more content or sibling nodes. Return IteratorResult.NeedInputNode if the next input node needs to be /// fetched first. Return IteratorResult.HaveCurrent if the Current property is set to the next node in the /// iteration. /// </summary> internal IteratorResult MoveNext(XPathNavigator input, bool isContent) { switch (_state) { case IteratorState.NeedCurrent: // If there are no more input nodes, then iteration is complete if (input == null) { return(IteratorResult.NoMoreNodes); } // Save the input node as the current node _navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, input); // If matching child or sibling is found, then we have a current node if (isContent ? _filter.MoveToContent(_navCurrent) : _filter.MoveToFollowingSibling(_navCurrent)) { _state = IteratorState.HaveCurrentNeedNext; } return(IteratorResult.NeedInputNode); case IteratorState.HaveCurrentNeedNext: if (input == null) { // There are no more input nodes, so enter HaveCurrentNoNext state and return Current _state = IteratorState.HaveCurrentNoNext; return(IteratorResult.HaveCurrentNode); } // Save the input node as the next node _navNext = XmlQueryRuntime.SyncToNavigator(_navNext, input); // If matching child or sibling is found, if (isContent ? _filter.MoveToContent(_navNext) : _filter.MoveToFollowingSibling(_navNext)) { // Then compare position of current and next nodes _state = IteratorState.HaveCurrentHaveNext; return(DocOrderMerge()); } // Input node does not result in matching child or sibling, so get next input node return(IteratorResult.NeedInputNode); case IteratorState.HaveCurrentNoNext: case IteratorState.HaveCurrentHaveNext: // If the current node has no more matching siblings, if (isContent ? !_filter.MoveToNextContent(_navCurrent) : !_filter.MoveToFollowingSibling(_navCurrent)) { if (_navStack.IsEmpty) { if (_state == IteratorState.HaveCurrentNoNext) { // No more input nodes, so iteration is complete return(IteratorResult.NoMoreNodes); } // Make navNext the new current node and fetch a new navNext _navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, _navNext); _state = IteratorState.HaveCurrentNeedNext; return(IteratorResult.NeedInputNode); } // Pop new current node from the stack _navCurrent = _navStack.Pop(); } // If there is no next node, then no need to call DocOrderMerge; just return the current node if (_state == IteratorState.HaveCurrentNoNext) { return(IteratorResult.HaveCurrentNode); } // Compare positions of current and next nodes return(DocOrderMerge()); } Debug.Assert(false, "Invalid IteratorState " + _state); return(IteratorResult.NoMoreNodes); }