如果XML文档中不存在节点,则使用linq to XML在该文档中创建节点

本文关键字:节点 文档 XML to 创建 linq 不存在 如果 | 更新日期: 2023-09-27 18:06:15

我正在使用XPathSelectElement方法查询xml文档。

如果节点不存在,我想在同一文档中插入具有该路径的节点。如果父节点不存在,也应该创建它们。有没有一种简单的方法可以做到这一点,而不用遍历父节点检查它们是否存在?(使用XPath添加新节点)

如果XML文档中不存在节点,则使用linq to XML在该文档中创建节点

不,没有…这与您在文件系统中查找一个目录,并且必须确保所有父目录都在那里。

的例子:

if (Directory.Exists(@":c:'test1'test2'blah blah'blah blah2")) ...

这是真的,目录。CreateDirectory方法将创建所有需要在那里让子元素显示的父元素,但是在XML中没有等效的(使用。net类,包括LINQ-to-XML)。

你必须手动遍历每一个。我建议您创建一个名为"EnsureNodeExists"的助手方法,为您完成此操作:)

static private XmlNode makeXPath(XmlDocument doc, string xpath)
{
   return makeXPath(doc, doc as XmlNode, xpath);
}
static private XmlNode makeXPath(XmlDocument doc, XmlNode parent, string   xpath)
{
// grab the next node name in the xpath; or return parent if empty
string[] partsOfXPath = xpath.Trim('/').Split('/');
string nextNodeInXPath = partsOfXPath.First();
if (string.IsNullOrEmpty(nextNodeInXPath))
    return parent;
// get or create the node from the name
XmlNode node = parent.SelectSingleNode(nextNodeInXPath);
if (node == null)
    node = parent.AppendChild(doc.CreateElement(nextNodeInXPath));
// rejoin the remainder of the array as an xpath expression and recurse
string rest = String.Join("/", partsOfXPath.Skip(1).ToArray());
return makeXPath(doc, node, rest);
}
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<feed />");
makeXPath(doc, "/feed/entry/data");
XmlElement contentElement =   (XmlElement)makeXPath(doc,"/feed/entry/content");
contentElement.SetAttribute("source", "");
Console.WriteLine(doc.OuterXml);
}

这有点晚了,但对于下一个可怜的灵魂来这里找不到帮助,这里是我最后写的静态方法。它不是完美无缺的,但应该可以处理各种用例。实际上,我只是从XPath的底部开始,一直切断部分,直到找到匹配,然后沿着路径返回并创建缺少的部分。如果您使用/root/test//someenode这样的路径,如果someenode不存在,它将失败,但是对于路径…/someenode//foo/bar/zot, if ../someenode//如果存在,应该可以正常工作

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

你可以在签名中将XDocument换成XElement或者XNode之类的东西,我只是在处理docs所以我使用了docs.