/// <summary> /// Construct a secondary location for this navigator. This location should only be used if /// primary locations previously compared equal. /// </summary> private int GetSecondaryLocation() { // Is the current node virtualized? if (_idxParent == 0) { // No, so secondary location is int.MinValue (always first) return(int.MinValue); } // Yes, so secondary location should be derived from current node // This happens with attributes nodes, namespace nodes, collapsed text nodes, and atomic values return(_pageCurrent[_idxCurrent].NodeType switch { // Namespace nodes come first (make location negative, but greater than int.MinValue) XPathNodeType.Namespace => int.MinValue + 1 + XPathNodeHelper.GetLocation(_pageCurrent, _idxCurrent), // Attribute nodes come next (location is always positive) XPathNodeType.Attribute => XPathNodeHelper.GetLocation(_pageCurrent, _idxCurrent), // Collapsed text nodes are always last _ => int.MaxValue, });
public override bool MoveToFollowing(string localName, string namespaceURI, XPathNavigator end) { XPathNode[] nodeArray; if (localName != this.atomizedLocalName) { this.atomizedLocalName = (localName != null) ? this.NameTable.Get(localName) : null; } int idxEnd = this.GetFollowingEnd(end as XPathDocumentNavigator, false, out nodeArray); if (this.idxParent == 0) { return(XPathNodeHelper.GetElementFollowing(ref this.pageCurrent, ref this.idxCurrent, nodeArray, idxEnd, this.atomizedLocalName, namespaceURI)); } if (!XPathNodeHelper.GetElementFollowing(ref this.pageParent, ref this.idxParent, nodeArray, idxEnd, this.atomizedLocalName, namespaceURI)) { return(false); } this.pageCurrent = this.pageParent; this.idxCurrent = this.idxParent; this.pageParent = null; this.idxParent = 0; return(true); }
public override int GetHashCode() { return(XPathNodeHelper.GetLocation(_page, _idx)); }
/// <summary> /// Move to the next node that: /// 1. Follows the current node in document order (includes descendants, unlike XPath following axis) /// 2. Precedes "end" in document order (if end is null, then all following nodes in the document are considered) /// 3. Has the specified XPathNodeType /// Return false if the current node has no matching following nodes. /// </summary> public override bool MoveToFollowing(XPathNodeType type, XPathNavigator end) { XPathDocumentNavigator endTiny = end as XPathDocumentNavigator; XPathNode[] page, pageEnd; int idx, idxEnd; // If searching for text, make sure to handle collapsed text nodes correctly if (type == XPathNodeType.Text || type == XPathNodeType.All) { if (_pageCurrent[_idxCurrent].HasCollapsedText) { // Positioned on an element with collapsed text, so return the virtual text node, assuming it's before "end" if (endTiny != null && _idxCurrent == endTiny._idxParent && _pageCurrent == endTiny._pageParent) { // "end" is positioned to a virtual attribute, namespace, or text node return(false); } _pageParent = _pageCurrent; _idxParent = _idxCurrent; _idxCurrent = _pageCurrent[_idxCurrent].Document.GetCollapsedTextNode(out _pageCurrent); return(true); } if (type == XPathNodeType.Text) { // Get node on which scan ends (null if rest of document should be scanned, parent if positioned on virtual node) idxEnd = GetFollowingEnd(endTiny, true, out pageEnd); // If this navigator is positioned on a virtual node, then compute following of parent if (_idxParent != 0) { page = _pageParent; idx = _idxParent; } else { page = _pageCurrent; idx = _idxCurrent; } // If ending node is a virtual node, and current node is its parent, then we're done if (endTiny != null && endTiny._idxParent != 0 && idx == idxEnd && page == pageEnd) { return(false); } // Get all virtual (collapsed) and physical text nodes which follow the current node if (!XPathNodeHelper.GetTextFollowing(ref page, ref idx, pageEnd, idxEnd)) { return(false); } if (page[idx].NodeType == XPathNodeType.Element) { // Virtualize collapsed text nodes Debug.Assert(page[idx].HasCollapsedText); _idxCurrent = page[idx].Document.GetCollapsedTextNode(out _pageCurrent); _pageParent = page; _idxParent = idx; } else { // Physical text node Debug.Assert(page[idx].IsText); _pageCurrent = page; _idxCurrent = idx; _pageParent = null; _idxParent = 0; } return(true); } } // Get node on which scan ends (null if rest of document should be scanned, parent + 1 if positioned on virtual node) idxEnd = GetFollowingEnd(endTiny, false, out pageEnd); // If this navigator is positioned on a virtual node, then compute following of parent if (_idxParent != 0) { if (!XPathNodeHelper.GetContentFollowing(ref _pageParent, ref _idxParent, pageEnd, idxEnd, type)) { return(false); } _pageCurrent = _pageParent; _idxCurrent = _idxParent; _pageParent = null; _idxParent = 0; return(true); } return(XPathNodeHelper.GetContentFollowing(ref _pageCurrent, ref _idxCurrent, pageEnd, idxEnd, type)); }
/// <summary> /// Move to the first content sibling of the current node with the specified type. Return false /// if the current node has no matching siblings. /// </summary> public override bool MoveToNext(XPathNodeType type) { return(XPathNodeHelper.GetContentSibling(ref _pageCurrent, ref _idxCurrent, type)); }
/// <summary> /// If positioned on an attribute, move to its next sibling attribute. If no attributes can be found, /// return false. /// </summary> public override bool MoveToNextAttribute() { return(XPathNodeHelper.GetNextAttribute(ref _pageCurrent, ref _idxCurrent)); }
/// <summary> /// If the current node is an attribute or namespace (not content), return false. Otherwise, /// move to the next content node. Return false if there are no more content nodes. /// </summary> public override bool MoveToNext() { return(XPathNodeHelper.GetContentSibling(ref this.pageCurrent, ref this.idxCurrent)); }
/// <summary> /// If the current node is an attribute or namespace (not content), return false. Otherwise, /// move to the next content node. Return false if there are no more content nodes. /// </summary> public override bool MoveToNext() { return XPathNodeHelper.GetContentSibling(ref _pageCurrent, ref _idxCurrent); }
public override bool MoveToFollowing(XPathNodeType type, XPathNavigator end) { XPathNode[] nodeArray2; int num2; XPathDocumentNavigator navigator = end as XPathDocumentNavigator; if ((type == XPathNodeType.Text) || (type == XPathNodeType.All)) { if (this.pageCurrent[this.idxCurrent].HasCollapsedText) { if (((navigator != null) && (this.idxCurrent == navigator.idxParent)) && (this.pageCurrent == navigator.pageParent)) { return(false); } this.pageParent = this.pageCurrent; this.idxParent = this.idxCurrent; this.idxCurrent = this.pageCurrent[this.idxCurrent].Document.GetCollapsedTextNode(out this.pageCurrent); return(true); } if (type == XPathNodeType.Text) { XPathNode[] pageParent; int idxParent; num2 = this.GetFollowingEnd(navigator, true, out nodeArray2); if (this.idxParent != 0) { pageParent = this.pageParent; idxParent = this.idxParent; } else { pageParent = this.pageCurrent; idxParent = this.idxCurrent; } if (((navigator != null) && (navigator.idxParent != 0)) && ((idxParent == num2) && (pageParent == nodeArray2))) { return(false); } if (!XPathNodeHelper.GetTextFollowing(ref pageParent, ref idxParent, nodeArray2, num2)) { return(false); } if (pageParent[idxParent].NodeType == XPathNodeType.Element) { this.idxCurrent = pageParent[idxParent].Document.GetCollapsedTextNode(out this.pageCurrent); this.pageParent = pageParent; this.idxParent = idxParent; } else { this.pageCurrent = pageParent; this.idxCurrent = idxParent; this.pageParent = null; this.idxParent = 0; } return(true); } } num2 = this.GetFollowingEnd(navigator, false, out nodeArray2); if (this.idxParent == 0) { return(XPathNodeHelper.GetContentFollowing(ref this.pageCurrent, ref this.idxCurrent, nodeArray2, num2, type)); } if (!XPathNodeHelper.GetContentFollowing(ref this.pageParent, ref this.idxParent, nodeArray2, num2, type)) { return(false); } this.pageCurrent = this.pageParent; this.idxCurrent = this.idxParent; this.pageParent = null; this.idxParent = 0; return(true); }