when programming with old school .net XPath (not this fancy linq :) ) you may have a instance of a XmlNode/XmlElement, and require its ABSOLUTE path. well here is a possible solution:
Sample Xml
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Default</Configuration>
<Name>"DatabaseProject"</Name>
.....
things to note are
1. there is a namespace
2. the Configuration has attributes. (I will use this to Identify the node)
now lets say you have a reference to the Configuration node for example (I used xpath here just to demonstrate the concept very quickly)
//requires a XmlNamespace Manager
XmlNamespaceManager nsMgr =
new XmlNamespaceManager(ce.DocProject.NameTable);
nsMgr.AddNamespace("ns",
"http://schemas.microsoft.com/developer/msbuild/2003");
//get the reference of the Configuration
XmlNode find = ce.DocProject.SelectSingleNode("//ns:Configuration", nsMgr);
the above allowed me to quickly get a reference, things to note, I have added the namespace and called it ns. from this settings the Xpath i will need will look like this:
/ns:Project/ns:PropertyGroup/ns:Configuration[@Condition=" '$(Configuration)' == '' "]
to get the node name + the ns prefix (ns:PropertyGroup) I use this function:
/// <summary>
/// This will create the required node name for a Xpath query, including the
/// NameSpace prefix
/// </summary>
/// <param name="current">Node to get name</param>
/// <param name="ns">Name space manager</param>
/// <returns>ns:NodeName</returns>
private static string GetNodeWithPrefix(XmlNode current, XmlNamespaceManager ns)
{
string prefix = ns.LookupPrefix(current.NamespaceURI);
if (prefix != string.Empty)
prefix += ":";
else
prefix = "";
return prefix + current.Name;
}
As i mentioned before this will use the Attribute to select the correct node. so now we will need to create a function which will create Xpath >[@Attribute="value" and ......]. Also we need to be careful not to include any attributes from the document (root) element. for this example it will create the [@Condition=" '$(Configuration)' == '' "] of the Xpath
/// <summary>
/// This generates the attribute part for a Xpath
/// </summary>
/// <param name="current">node to get attribtes for</param>
/// <returns>[@Attribute="value" and ......]</returns>
private static string GetXPathAttributes(XmlNode current)
{
//do not get the attributes for the Document element.
if (current == current.OwnerDocument.DocumentElement)
return "";
StringBuilder attrs = new StringBuilder("[");
foreach (XmlAttribute attr in current.Attributes)
{
if (attrs.Length > 1)
attrs.Append(" and ");
attrs.AppendFormat("@{0}=\"{1}\"", attr.LocalName, attr.Value);
}
attrs.Append("]");
if (attrs.Length > 2)
return attrs.ToString();
else
return "";
}
Now its taking shape, the last part is a function which will use the other 2 and actually create the Xpath
/// <summary>
/// this will generate an absolute Xpath for a node. requires the node and a NS mgr
/// </summary>
/// <returns>the XPATH for that node.</returns>
public static string GetXPath(XmlNode current, XmlNamespaceManager ns)
{
//XmlDocument doc = current.OwnerDocument;
string path = "";
XmlNode NodePointer = current;
//this is used as a pointer.
while (NodePointer.Name != "#document")
{
string nodeName = GetNodeWithPrefix(NodePointer, ns);
string attributes = GetXPathAttributes(NodePointer);
path =
"/" + nodeName + attributes + path;
NodePointer =
NodePointer.ParentNode;
}
return path;
}
The above, will start at the current XmlNode (in the sample it will be find) and move its way up the Xml tree creating the Xpath as it goes along. The following is sample usage:
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5