This is a bit late, but for the next poor soul to come here and find no help here's the static method I ended up writing. It's not flawless, but should handle a variety of use cases. Essentially I just go from the bottom of the XPath and keep cutting off sections until I find a match, then go back down the path and create what's missing. It will fail if you use a path like /root/test//someNode if someNode doesn't exist, but for a path ../someNode//foo/bar/zoot, if ../someNode//foo exists it should work fine.
public static XElement GetOrCreateNodeAtXPath(XDocument doc, string key)
{
//you don't really need this, but it makes throwing errors easier when you're 10 levels deep in the recursion
return GetOrCreateNodeAtXPath(doc, key, key);
}
private static XElement GetOrCreateNodeAtXPath(XDocument doc, string key, string originalKey)
{
var node = doc.XPathSelectElement(key);
if (node != null)
return node;
if (!key.Contains('/')) //we've reached the root, and couldn't find anything
throw new Exception($"Could not create node at path {originalKey}, no part of path matches document");
var slashIndex = key.LastIndexOf('/');
var newKey = key.Substring(0, slashIndex);
var newNodeName = key.Substring(slashIndex + 1);
var parentNode = GetOrCreateNodeAtXPath(doc, newKey, originalKey);
var childNode = new XElement(newNodeName);
parentNode.Add(childNode);
return childNode;
}
You may wanna swap XDocument with XElement or XNode or something in the signature, I was just dealign with docs so I used docs.