Monday 23 July 2007

How do i find the xpath of an XmlNode in c#?

I came across this problem today where I was trying to find the xpath of the current node, so i could access the parent and remove that node from the collection. I knocked together some useful code to remove this. It basically works out the position of that node in the document and then which child it is on the child node.


/// <summary>
/// Gets an xpath to a node
/// </summary>
/// <param name="node">Node to get xpath for</param>
/// <returns>Xpath for node</returns>
private static string GetXPathToNode(XmlNode node)
{
if (node.NodeType == XmlNodeType.Attribute)
{
// attributes have an OwnerElement, not a ParentNode; also they have
// to be matched by name, not found by position
return String.Format(
"{0}/@{1}",
GetXPathToNode(((XmlAttribute)node).OwnerElement),
node.Name
);
}
if (node.ParentNode == null)
{
//Have root node - so return empty path
return "";
}

// the path to a node is the path to its parent, plus "/node()[n]", where
// n is its position among its siblings.
return String.Format(
"{0}/node()[{1}]",
GetXPathToNode(node.ParentNode),
GetNodePosition(node)
);
}

/// <summary>
/// Gets node position in relation to the child
/// </summary>
/// <param name="child">Child</param>
/// <returns>Position on parent</returns>
private static int GetNodePosition(XmlNode childNode)
{
for (int position = 0; position < childNode.ParentNode.ChildNodes.Count; position++)
{
if (childNode.ParentNode.ChildNodes[position] == childNode)
{
// need to add one as xpath index starts not at zero
return position + 1;
}
}
throw new InvalidOperationException("Missing Child Node");
}

No comments: