Does anyone know of an existing means of creating an XML hierarchy programatically from an XPath expression?
For example if I have an XML fragment such as:
Use
var xDoc = new XDocument(new XElement("root",
new XElement("child1"),
new XElement("child2")));
CreateElement(xDoc, "/root/child3");
CreateElement(xDoc, "/root/child4[@year=32][@month=44]");
CreateElement(xDoc, "/root/child4[@year=32][@month=44]/subchild1");
CreateElement(xDoc, "/root/child4[@year=32][@month=44]/subchild1/subchild[@name='jon']");
CreateElement(xDoc, "/root/child1");
define
public static XDocument CreateElement(XDocument document, string xpath)
{
if (string.IsNullOrEmpty(xpath))
throw new InvalidOperationException("Xpath must not be empty");
var xNodes = Regex.Matches(xpath, @"\/[^\/]+").Cast().Select(it => it.Value).ToList();
if (!xNodes.Any())
throw new InvalidOperationException("Invalid xPath");
var parent = document.Root;
var currentNodeXPath = "";
foreach (var xNode in xNodes)
{
currentNodeXPath += xNode;
var nodeName = Regex.Match(xNode, @"(?<=\/)[^\[]+").Value;
var existingNode = parent.XPathSelectElement(currentNodeXPath);
if (existingNode != null)
{
parent = existingNode;
continue;
}
var attributeNames =
Regex.Matches(xNode, @"(?<=@)([^=]+)\=([^]]+)")
.Cast()
.Select(it =>
{
var groups = it.Groups.Cast().ToList();
return new { AttributeName = groups[1].Value, AttributeValue = groups[2].Value };
});
parent.Add(new XElement(nodeName, attributeNames.Select(it => new XAttribute(it.AttributeName, it.AttributeValue)).ToArray()));
parent = parent.Descendants().Last();
}
return document;
}