在XDocument中编辑特定元素

39

我最近开始学习C#,在使用XML.Linq存储数据时遇到了问题。希望我的问题可以理解,因为我还不熟悉所有正确的术语,并且英语不是我的第一语言。

我阅读了很多问题/谷歌搜索,但我自己无法解决问题。

我想要更新一个现有的XDocument文件,它看起来像这样:

<Data>
  <IDCounter>2</IDCounter>
  <Highscores>
     .......
  </Highscores>
  <savegames>
    <savegame>
       <IdNumber>1</IdNumber>
       <salutation>Mr</salutation>
       <prename>Prename1</prename>
       <surname>Surname1</surname>
       <maximumbalance>100</maximumbalance>
       <balance>100</balance>
    </savegame>
    <savegame>
       <IdNumber>2</IdNumber>
       <salutation>Mr</salutation>
       <prename>Prename2</prename>
       <surname>Surname2</surname>
       <maximumbalance>100</maximumbalance>
       <balance>100</balance>
     </savegame>
   </savegames>
</Data> 

如何以最简单的方法更改特定元素中的值?

比方说我想改变一个特定“存档”的余额

我想通过IdNumber(这些数字是唯一的)访问存档。

然后我想更改余额的值(例如更改为50),并将这些更改保存到我的文档中。

4个回答

49

使用 System.Xml.Linq; 后,它变成了

 var doc = XElement.Load(fileName);
 var saveGame = doc
      .Element("savegames")
      .Elements("savegame")
      .Where(e => e.Element("IdNumber").Value == "2")
      .Single();

 saveGame.Element("balance").Value = "50";

 doc.Save(fileName);

1
出现了一个错误:"对象引用未设置为对象的实例...",然后我通过 XDocument.Load(fileName); 解决了它。 - newbieguy
我也遇到了“对象引用未设置为对象实例”的问题。我发现添加XNamespace可以解决这个问题:doc.Element(Ns + "Foo")... - ooXei1sh
一个XElement在几乎所有情况下都可以扮演文档的角色。Xml可能需要或不需要命名空间。 - H H

24

我认为最简洁的实现方式是使用XDocument(System.Xml.Linq)和XPath扩展(System.Xml.XPath):

var xdoc = XDocument.Load(file);
xdoc.XPathSelectElement("//savegame/IdNumber[text()='2']/../balance").Value = "50";
xdoc.Save(file);

一旦你学会XPath,你就不想再手动枚举节点了。

编辑:查询的含义是什么:

//savegame/IdNumber[text()='2']/../balance"
  |        |                    |  ^ balance element ...
  |        |                    ^ ... of parent ...
  |        ^ ... of IdNumber element with inner value '2' ...
  ^ ... of any savegame element in the doc

您可以在这里找到XPath帮助,以及此处更新的链接。


2
这是XPath帮助的更新链接:http://www.w3schools.com/xsl/xpath_intro.asp。 - Cooter
这是XPath帮助的更新链接:https://www.w3schools.com/xml/xpath_syntax.asp - Troy Witthoeft
修改一个值很容易,但如果我想要修改 100 个值呢?它需要“循环” 100 次来更新这些值。 - Paulo Guimarães

4
   UpdateGameAttr(id ,  bal);

   private void UpdateGameAttr(int id, int bal)
   {
       XDocument gmaes = XDocument.Load(@"D:\xxx\xxx\Game.xml");            

       XElement upd = (from games in games.Descendants("savegame")
                      where games.Element("IdNumber").Value == id.ToString()
                      select games).Single();
       upd.Element("balance").Value = bal.ToString();
       gmaes.Save(@"D:\xxxx\xxx\Game.xml");

   }

3
这里有一个简单的方法来实现这个目标:
     XmlDocument doc = new XmlDocument();
     doc.Load(@"d:\tmp.xml");
     XmlNode node = doc["Data"]["savegames"];

     foreach (XmlNode childNode in node.ChildNodes)
     {
        if (childNode["IdNumber"].InnerText.Equals("1"))
        {
           childNode["balance"].InnerText = "88";
        }

     }
     doc.Save(@"d:\tmp.xml");

这段代码仅仅改变了ID为“1”的余额。

它通过遍历“savegames”的子元素,并检查每个项目的“IdNumber”来实现这一目标。


6
XmlDocument不是“简单”的方式,而是老旧的方式。 - H H
2
@HenkHolterman(以及点赞者),你太过于追求细节了。并没有说“THE simple way”,只是A simple way。它仍然是简单的。 - Chris Marisic

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