需要使用linq c#将xml元素添加到最后一个父元素

时间:2014-01-07 22:13:41

标签: c# xml linq

我对Linq和C#真的很陌生,而且我仍然坚持可能是一个明显的问题。

我有一个现有的XML文件

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<books>
  <book>
    <title>This is Title 1</title>
    <author>John Doe</author>
    <categories>
      <category>How to</category>
      <category>Technical</category>       
  </book>
  <book>
    <title>This is Title 2</title>
    <author>Jane Brown</author>
    <categories>
      <category>Fantasy</category>
    </categories>
  </book>
</books>

我想在此文件的第二本书中添加第二类。

我已经走到这一步了:

var thiscat = doc.Root
  .Element("book")
  .Element("categories");

thiscat.Add(new XElement("category", "novel"));

但这为第一本书增加了第三类。我需要学习如何在最后一个类别元素而不是第一个元素中指出'thiscat'。我一直在嗅探LastNode,但还没有设法使语法正确。

这是我的第一个问题。如果我不清楚或者我做错了什么,请告诉我。

4 个答案:

答案 0 :(得分:1)

皮特,

以下是按标题This is Title 2搜索图书并添加其他类别的示例。

var elem = doc.Root.Elements("book").FirstOrDefault(x => x.Element("title").Value.Equals("This is Title 2"));
if (elem != null)
{
    var category = elem.Element("categories");
    category.Add(new XElement("category", "novel"));
}

编辑:更多解释。

我们首先搜索文档book元素以匹配title This is Title 2(实际上是您的第二个条目)。通过执行FirstOrDefault扩展方法,我们可以获取第一个匹配元素(XElement)或null

因为我们'可以'获得null值,所以我们必须检查值是null,否则我们会进入定位categories元素的下一步。这可以简单地调用elem.Element()方法,因为我们只需要一个元素。

最后,我们向XElement元素添加了新的category

希望这有帮助。

干杯。

答案 1 :(得分:0)

要完全回答您的问题,您可以按如下方式修改语句:

var thiscat = doc.Root
.Elements("book")
.Skip(1)
.First()
.Element("categories");

“Element”函数返回找到的那个类型的第一个元素。在这种情况下,我们使用“Elements”来返回包含名为“book”的所有元素的IEnumerable,然后我们使用LINQ“skip”函数跳过第一个(返回所有剩余元素的另一个IEnumerable),并且然后我们只获取IEnumerable中的第一个元素(返回单个XElement)。

你可以得到答案的另一种方法如下:

var thiscat = doc.Root
.Element("book")
.ElementsAfterSelf()
.First()
.Element("categories");

ElementsAfterSelf返回调用对象之后所有兄弟元素的IEnumerable。

LINQ是C#中编程的一个非常关键的部分,很高兴看到你从一开始就学习它。虽然你在这里以编程方式将特定元素添加到特定位置的方法是值得怀疑的(显然这是一个人为的例子),但在这样的游戏中你可能会学到一些关于LINQ的知识,这总是很好。

答案 2 :(得分:0)

首先,您应该获得第二个图书元素。根据您的代码:

var thiscat = doc.Root
                 .Element("book")
                 .Element("categories");

此语句只返回属于您第一本书的一个类别元素。因为您使用的是Element而不是Elements。让我们一步一步走。

获取第二个元素的正确方法是使用Descendants,如下所示:

var secondBook = doc.Descendants("book")[1];

后代返回你的书籍集合。我们正在使用indexer获得第二个元素。现在我们需要在book元素下选择你的categories元素。

var categories = secondBook.Element("categories");

现在我们有了category元素,我们可以添加新的category并保存Xml Document

categories.Add(new XElement("category", "novel"));
doc.Save(path);

就是这样。如果你理解了这个逻辑,你可以随意修改你的html文件。除此之外,你可以在一行中完成所有这些:

doc.Descendants("book")[1]
            .Element("categories")
            .Add(new XElement("category", "novel"));

答案 3 :(得分:0)

这应该有效(稍微冗长的解决方案,因为它有助于更​​好地理解基本面):

            XmlElement rootNode = xd.DocumentElement;  //gives <books> the root node
            XmlNodeList cnodes= rootNode.ChildNodes; //gets the childnodes of <books>
            XmlNode secondBook= cnodes.Item(1); //second child of <books> i.e., the <book> you want
            XmlNodeList bnodes= secondBook.ChildNodes; //gets the childnodes of that <book>
            XmlNode categories= bnodes.Item(2); //gets the third child i.e.,<categories>
//making the new <category> node
            string xmlContent = "<category>novel</category>";
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlContent);
            XmlNode newNode = doc.DocumentElement;
//making the new node completes

            categories.AppendChild(newNode);  //append the new node to <categories> as a child