使用LINQ-to-XML通过xpath查找或创建元素

7

有没有一种简洁的方法,可以使用XPath表达式查找或创建XObject。

我遇到的问题是需要在一个元素上设置值(我已经有了它的XPath),但这个元素可能存在也可能不存在。如果它不存在,我希望它能被创建出来。

非常感谢任何提示或链接。

谢谢大家。


1
XPath 选择节点,它不会序列化新文档,也不会更新节点的值。除此之外,这个问题定义得很糟糕:正如 @C. Lawrence Wenham 所指出的那样,当 //element 被评估为一个空节点集时,你认为应该在哪里创建该元素? - user357812
@Alejandro。这个问题的措辞可以更好。同意。我正在寻找类似于Java世界中JXPath提供的功能。请参见http://commons.apache.org/jxpath/users-guide.html#Creating_Objects。使用此API,可以通过xpath定义要更新或创建的节点。在此API中,“将路径创建与设置叶子值相结合是常见的:用于此的createPathAndSetValue(path,value)方法。” - mileyd
2个回答

1
你可以使用 System.Xml.XPath.Extensions 类在 XDocument 上评估 XPath 表达式。

http://msdn.microsoft.com/en-us/library/system.xml.xpath.extensions.aspx

例如:

using System.Xml.XPath;
...
XDocument doc = XDocument.Load("sample.xml");
var matching = doc.XPathEvaluate("//Book[@Title='Great Expectations']");  
// 'matching' could be an IEnumerable of XElements, depending on the query

谢谢大家的迅速回复,但我想要的是能够根据xpath创建一个节点的能力。例如,我可以这样做:var matching = doc.XPathSelectElement("//Book[@Title='Great Expectations']"); 如果元素不存在,它会自动为我创建。 - mileyd
2
我认为这在.Net或一般情况下都无法完成,因为XPath是一种查询语言,你无法推断出必须创建哪个单一节点链来满足其条件,因为可能有无限多个有效的层次结构。在这个例子中,“//Book”表示“文档中任何位置的Book元素”,所以如果你要创建节点,那么你会把它放在哪里呢? - Chris Wenham
点子收到了,@C. Lawrence Wenham。我有点懒,只是用你的例子作为参考。当可以推导出单个节点链时(请参见我对@Alejandro的回复中的示例),在Java世界中,我可以使用commons JXPath API来实现这一点。这就是我想要在.NET中复制的内容。 - mileyd

1
假设有一个简单的路径,你只想在其末尾添加一些数据。
从以下示例数据开始:
var xml = XDocument.Parse(@"<?xml version=""1.0""?>
<messages>
  <request type=""MSG"">
    <header>
      <datestamp>2019-02-26T14:49:41+00:00</datestamp>
      <source>1</source>
    </header>
    <body>
      <title>Hi there</title>
    </body>
  </request>
</messages>
");

这不起作用,因为产品节点不存在:
xml.XPathSelectElement("/messages/request/body/product")
    ?.Add(new XElement("description", "A new product"));

要做到这一点,您可以定义自己的扩展方法:

public static class extensionMethods
{
    public static XElement FindOrAddElement(this XContainer xml, string nodeName)
    {
        var node = xml.Descendants().FirstOrDefault(x => x.Name == nodeName);
        if (node == null)
            xml.Add(new XElement(nodeName));
        return xml.Descendants().FirstOrDefault(x => x.Name == nodeName);
    }
}

将它们链接在一起以创建您的新路径。
xml.FindOrAddElement("messages")
   .FindOrAddElement("request")
   .FindOrAddElement("body")
   .FindOrAddElement("product")
   ?.Add(new XElement("description", "A new product"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接