public virtual XmlNodeOrder ComparePosition (XPathNavigator nav) { if (IsSamePosition (nav)) return XmlNodeOrder.Same; // quick check for direct descendant if (IsDescendant (nav)) return XmlNodeOrder.Before; // quick check for direct ancestor if (nav.IsDescendant (this)) return XmlNodeOrder.After; XPathNavigator nav1 = Clone (); XPathNavigator nav2 = nav.Clone (); // check if document instance is the same. nav1.MoveToRoot (); nav2.MoveToRoot (); if (!nav1.IsSamePosition (nav2)) return XmlNodeOrder.Unknown; nav1.MoveTo (this); nav2.MoveTo (nav); int depth1 = 0; while (nav1.MoveToParent ()) depth1++; nav1.MoveTo (this); int depth2 = 0; while (nav2.MoveToParent ()) depth2++; nav2.MoveTo (nav); // find common parent depth int common = depth1; for (;common > depth2; common--) nav1.MoveToParent (); for (int i = depth2; i > common; i--) nav2.MoveToParent (); while (!nav1.IsSamePosition (nav2)) { nav1.MoveToParent (); nav2.MoveToParent (); common--; } // For each this and target, move to the node that is // ancestor of the node and child of the common parent. nav1.MoveTo (this); for (int i = depth1; i > common + 1; i--) nav1.MoveToParent (); nav2.MoveTo (nav); for (int i = depth2; i > common + 1; i--) nav2.MoveToParent (); // Those children of common parent are comparable. // namespace nodes precede to attributes, and they // precede to other nodes. if (nav1.NodeType == XPathNodeType.Namespace) { if (nav2.NodeType != XPathNodeType.Namespace) return XmlNodeOrder.Before; while (nav1.MoveToNextNamespace ()) if (nav1.IsSamePosition (nav2)) return XmlNodeOrder.Before; return XmlNodeOrder.After; } if (nav2.NodeType == XPathNodeType.Namespace) return XmlNodeOrder.After; if (nav1.NodeType == XPathNodeType.Attribute) { if (nav2.NodeType != XPathNodeType.Attribute) return XmlNodeOrder.Before; while (nav1.MoveToNextAttribute ()) if (nav1.IsSamePosition (nav2)) return XmlNodeOrder.Before; return XmlNodeOrder.After; } while (nav1.MoveToNext ()) if (nav1.IsSamePosition (nav2)) return XmlNodeOrder.Before; return XmlNodeOrder.After; }
public virtual XmlNodeOrder ComparePosition(XPathNavigator nav) { if (IsSamePosition(nav)) { return(XmlNodeOrder.Same); } // quick check for direct descendant if (IsDescendant(nav)) { return(XmlNodeOrder.Before); } // quick check for direct ancestor if (nav.IsDescendant(this)) { return(XmlNodeOrder.After); } XPathNavigator nav1 = Clone(); XPathNavigator nav2 = nav.Clone(); // check if document instance is the same. nav1.MoveToRoot(); nav2.MoveToRoot(); if (!nav1.IsSamePosition(nav2)) { return(XmlNodeOrder.Unknown); } nav1.MoveTo(this); nav2.MoveTo(nav); int depth1 = 0; while (nav1.MoveToParent()) { depth1++; } nav1.MoveTo(this); int depth2 = 0; while (nav2.MoveToParent()) { depth2++; } nav2.MoveTo(nav); // find common parent depth int common = depth1; for (; common > depth2; common--) { nav1.MoveToParent(); } for (int i = depth2; i > common; i--) { nav2.MoveToParent(); } while (!nav1.IsSamePosition(nav2)) { nav1.MoveToParent(); nav2.MoveToParent(); common--; } // For each this and target, move to the node that is // ancestor of the node and child of the common parent. nav1.MoveTo(this); for (int i = depth1; i > common + 1; i--) { nav1.MoveToParent(); } nav2.MoveTo(nav); for (int i = depth2; i > common + 1; i--) { nav2.MoveToParent(); } // Those children of common parent are comparable. // namespace nodes precede to attributes, and they // precede to other nodes. if (nav1.NodeType == XPathNodeType.Namespace) { if (nav2.NodeType != XPathNodeType.Namespace) { return(XmlNodeOrder.Before); } while (nav1.MoveToNextNamespace()) { if (nav1.IsSamePosition(nav2)) { return(XmlNodeOrder.Before); } } return(XmlNodeOrder.After); } if (nav2.NodeType == XPathNodeType.Namespace) { return(XmlNodeOrder.After); } if (nav1.NodeType == XPathNodeType.Attribute) { if (nav2.NodeType != XPathNodeType.Attribute) { return(XmlNodeOrder.Before); } while (nav1.MoveToNextAttribute()) { if (nav1.IsSamePosition(nav2)) { return(XmlNodeOrder.Before); } } return(XmlNodeOrder.After); } while (nav1.MoveToNext()) { if (nav1.IsSamePosition(nav2)) { return(XmlNodeOrder.Before); } } return(XmlNodeOrder.After); }
internal override XPathNavigator advance() { if (_eLast == null) { XPathNavigator temp = null; _eLast = m_qyInput.advance(); if (_eLast == null) { return(null); } while (_eLast != null) { _eLast = _eLast.Clone(); temp = _eLast; _eLast = m_qyInput.advance(); if (!temp.IsDescendant(_eLast)) { break; } } _eLast = temp; } while (true) { if (_first) { _first = false; if (_eLast.NodeType == XPathNodeType.Attribute || _eLast.NodeType == XPathNodeType.Namespace) { _eLast.MoveToParent(); if (_fMatchName) { _qy = _eLast.SelectDescendants(m_Name, m_URN, false); } else { _qy = _eLast.SelectDescendants(m_Type, false); } } else { while (true) { if (!_eLast.MoveToNext()) { if (!_eLast.MoveToParent()) { _first = true; return(null); } } else { break; } } if (_fMatchName) { _qy = _eLast.SelectDescendants(m_Name, m_URN, true); } else { _qy = _eLast.SelectDescendants(m_Type, true); } } } if (_qy.MoveNext()) { _position++; m_eNext = _qy.Current; return(m_eNext); } else { _first = true; } } }
/// <summary> /// Position this iterator to the next following node. Prune by finding the first input node in /// document order that has no other input nodes in its subtree. All other input nodes should be /// discarded. 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> public IteratorResult MoveNext(XPathNavigator input) { switch (_state) { case IteratorState.NeedCandidateCurrent: // If there are no more input nodes, then iteration is complete if (input == null) return IteratorResult.NoMoreNodes; // Save input node as current node _navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, input); // Still must check next input node to see if is a descendant of this one _state = IteratorState.HaveCandidateCurrent; return IteratorResult.NeedInputNode; case IteratorState.HaveCandidateCurrent: // If there are no more input nodes, if (input == null) { // Then candidate node has been selected, and there are no further input nodes _state = IteratorState.HaveCurrentNoNext; return MoveFirst(); } // If input node is in the subtree of the candidate node, then use the input node instead if (_navCurrent.IsDescendant(input)) goto case IteratorState.NeedCandidateCurrent; // Found node on which to perform following scan. Now skip past all input nodes in the same document. _state = IteratorState.HaveCurrentNeedNext; goto case IteratorState.HaveCurrentNeedNext; case IteratorState.HaveCurrentNeedNext: // If there are no more input nodes, if (input == null) { // Then candidate node has been selected, and there are no further input nodes _state = IteratorState.HaveCurrentNoNext; return MoveFirst(); } // Skip input node unless it's in a different document than the node on which the following scan was performed if (_navCurrent.ComparePosition(input) != XmlNodeOrder.Unknown) return IteratorResult.NeedInputNode; // Next node is in a different document, so save it _navNext = XmlQueryRuntime.SyncToNavigator(_navNext, input); _state = IteratorState.HaveCurrentHaveNext; return MoveFirst(); } if (!_filter.MoveToFollowing(_navCurrent, null)) return MoveFailed(); return IteratorResult.HaveCurrentNode; }
private void IsDescendant (XPathNavigator nav) { XPathNavigator tmp = nav.Clone (); XPathNodeIterator iter = nav.Select ("//e"); iter.MoveNext (); Assert.IsTrue (nav.MoveTo (iter.Current), "#1"); Assert.IsTrue (nav.MoveToFirstAttribute (), "#2"); Assert.AreEqual ("attr", nav.Name, "#3"); Assert.AreEqual ("", tmp.Name, "#4"); Assert.IsTrue (tmp.IsDescendant (nav), "#5"); Assert.IsTrue (!nav.IsDescendant (tmp), "#6"); tmp.MoveToFirstChild (); Assert.AreEqual ("a", tmp.Name, "#7"); Assert.IsTrue (tmp.IsDescendant (nav), "#8"); Assert.IsTrue (!nav.IsDescendant (tmp), "#9"); tmp.MoveTo (iter.Current); Assert.AreEqual ("e", tmp.Name, "#10"); Assert.IsTrue (tmp.IsDescendant (nav), "#11"); Assert.IsTrue (!nav.IsDescendant (tmp), "#12"); }
public virtual XmlNodeOrder ComparePosition(XPathNavigator nav) { if(IsSamePosition(nav)) { return XmlNodeOrder.Same; } if(IsDescendant(nav)) { return XmlNodeOrder.Before; } else if(nav.IsDescendant(this)) { return XmlNodeOrder.After; } XPathNavigator copy = this.Clone(); XPathNavigator other = nav.Clone(); /* now, it gets expensive - we find the closest common ancestor. But these two might be from totally different places. Someone should re-implement this somewhere, so that it is faster for XmlDocument. */ int common = 0; int otherDepth = 0; int copyDepth = 0; copy.MoveToRoot(); other.MoveToRoot(); if(!copy.IsSamePosition(other)) { return XmlNodeOrder.Unknown; } /* what do you think ? I'm made of GC space ? */ copy.MoveTo(this); other.MoveTo(nav); while(other.MoveToParent()) { otherDepth++; } while(copy.MoveToParent()) { copyDepth++; } common = (otherDepth > copyDepth) ? copyDepth : otherDepth; other.MoveTo(nav); copy.MoveTo(this); // traverse both till you get to depth == common for(;otherDepth > common; otherDepth--) { other.MoveToParent(); } for(;copyDepth > common; copyDepth--) { copy.MoveToParent(); } other.MoveTo(nav); copy.MoveTo(this); XPathNavigator copy1 = copy.Clone(); XPathNavigator other1 = other.Clone(); while(copy.IsSamePosition(other)) { copy1.MoveTo(copy); other1.MoveTo(other); copy.MoveToParent(); other.MoveToParent(); } copy.MoveTo(copy1); other.MoveTo(other1); // Now copy & other are siblings and can be compared while(copy.MoveToNext()) { if(copy.IsSamePosition(other)) { return XmlNodeOrder.Before; } } return XmlNodeOrder.After; }
private void IsDescendant (XPathNavigator nav) { XPathNavigator tmp = nav.Clone (); XPathNodeIterator iter = nav.Select ("//e"); iter.MoveNext (); Assert (nav.MoveTo (iter.Current)); Assert (nav.MoveToFirstAttribute ()); AssertEquals ("attr", nav.Name); AssertEquals ("", tmp.Name); Assert (tmp.IsDescendant (nav)); Assert (!nav.IsDescendant (tmp)); tmp.MoveToFirstChild (); AssertEquals ("a", tmp.Name); Assert (tmp.IsDescendant (nav)); Assert (!nav.IsDescendant (tmp)); tmp.MoveTo (iter.Current); AssertEquals ("e", tmp.Name); Assert (tmp.IsDescendant (nav)); Assert (!nav.IsDescendant (tmp)); }
public virtual XmlNodeOrder ComparePosition(XPathNavigator nav) { if (IsSamePosition(nav)) { return(XmlNodeOrder.Same); } if (IsDescendant(nav)) { return(XmlNodeOrder.Before); } else if (nav.IsDescendant(this)) { return(XmlNodeOrder.After); } XPathNavigator copy = this.Clone(); XPathNavigator other = nav.Clone(); /* now, it gets expensive - we find the * closest common ancestor. But these two * might be from totally different places. * * Someone should re-implement this somewhere, * so that it is faster for XmlDocument. */ int common = 0; int otherDepth = 0; int copyDepth = 0; copy.MoveToRoot(); other.MoveToRoot(); if (!copy.IsSamePosition(other)) { return(XmlNodeOrder.Unknown); } /* what do you think ? I'm made of GC space ? */ copy.MoveTo(this); other.MoveTo(nav); while (other.MoveToParent()) { otherDepth++; } while (copy.MoveToParent()) { copyDepth++; } common = (otherDepth > copyDepth) ? copyDepth : otherDepth; other.MoveTo(nav); copy.MoveTo(this); // traverse both till you get to depth == common for (; otherDepth > common; otherDepth--) { other.MoveToParent(); } for (; copyDepth > common; copyDepth--) { copy.MoveToParent(); } other.MoveTo(nav); copy.MoveTo(this); XPathNavigator copy1 = copy.Clone(); XPathNavigator other1 = other.Clone(); while (copy.IsSamePosition(other)) { copy1.MoveTo(copy); other1.MoveTo(other); copy.MoveToParent(); other.MoveToParent(); } copy.MoveTo(copy1); other.MoveTo(other1); // Now copy & other are siblings and can be compared while (copy.MoveToNext()) { if (copy.IsSamePosition(other)) { return(XmlNodeOrder.Before); } } return(XmlNodeOrder.After); }