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;
}