in src/Model/XPathGenerator.cs [141:228]
string GetPathInParent(XmlNode node, XmlNamespaceManager nsmgr)
{
XmlNodeType nt = node.NodeType;
if (nt == XmlNodeType.Attribute)
{
if (node.NamespaceURI == "http://www.w3.org/2000/xmlns/")
{
if (string.IsNullOrEmpty(node.Prefix) &&
node.LocalName == "xmlns")
{
return "namespace::*[local-name()='']";// and .='" + node.Value + "']";
}
else
{
return "namespace::" + node.LocalName;
}
}
// attributes are unique by definition, so no indices are
// required.
return string.Format("@{0}", GetQualifiedPath(node, nsmgr));
}
XmlNode parent = node.ParentNode;
if (parent != null)
{
int count = 0;
int index = 0;
bool wasText = false;
XmlNode child = parent.FirstChild;
while (child != null)
{
if (child == node)
{
index = count;
}
XmlNodeType ct = child.NodeType;
if (IsTextNode(ct))
{
if (IsTextNode(nt))
{
// Adjacent text nodes are merged in XPath model.
if (!wasText) count++;
}
wasText = true;
}
else
{
wasText = false;
if (ct == nt && child.Name == node.Name)
{
count++;
}
}
child = child.NextSibling;
}
string selector = null;
switch (node.NodeType)
{
case XmlNodeType.CDATA:
case XmlNodeType.Text:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
selector = "text()";
break;
case XmlNodeType.Comment:
selector = "comment()";
break;
case XmlNodeType.Element:
selector = GetQualifiedPath(node, nsmgr);
break;
case XmlNodeType.ProcessingInstruction:
selector = "processing-instruction('" + node.Name + "')";
break;
}
if (!this._useIndices && count < 2)
{ // it's unique already, so no need for indices.
return selector;
}
index++; // XPath indices are 1-based
return string.Format("{0}[{1}]", selector, index.ToString());
}
else
{
return null;
}
}