Create XML Nodes based on XPath?

后端 未结 12 630
囚心锁ツ
囚心锁ツ 2020-11-27 15:36

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:

12条回答
  •  隐瞒了意图╮
    2020-11-27 16:05

    • For XDocument
    • Supports attribute creation

    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;
    }
    

提交回复
热议问题