Library of XPathNode helper routines.
        /// <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,
            });
Example #2
0
        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);
        }
Example #3
0
 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));
 }
Example #7
0
 /// <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));
 }
Example #8
0
 /// <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);
 }
Example #9
0
        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);
        }