c# -无法保存包含新元素的自定义linq-to-xml文件

本文关键字:自定义 linq-to-xml 文件 元素 包含新 保存 | 更新日期: 2023-09-27 18:12:48

我正在创建一个新的XDocument并插入一个根元素"profiles",然后保存。

if (!System.IO.File.Exists("profiles.xml"))
{
    XDocument doc = new XDocument(
        new XElement("profiles")
    );
    doc.Save("profiles.xml", SaveOptions.None);
}

然后我想让用户输入并将配置文件添加到已经创建的xml文件中:

XElement profile =
        new XElement(Player.Name,
            new XElement("level", Player.Level),
            new XElement("cash", Player.Cash)
        );
XDocument doc = XDocument.Load("profiles.xml");
List<XElement> profiles = doc.Root.Elements().ToList();
for (int i = 0; i < profiles.Count; i++)
{
    if (profiles[i].Name.ToString() == Player.name)
    {
        profiles[i] = profile;
        return;
    }
}
profile.Add(profile);
doc.Save("profiles.xml", SaveOptions.None);

但是由于某些原因,它永远不会添加任何新的配置文件?

编辑:另外,如果我手动创建一个新的配置文件到xml文件中,它也不会自定义,所以问题是在保存文件?

c# -无法保存包含新元素的自定义linq-to-xml文件

您实际上从未做过任何事情来改变doc所指的XDocument中的任何元素:

  • 如果您发现一个元素具有现有的名称,您正在修改列表,但这不会修改文档。您可能想使用XElement.ReplaceWith:

    profiles[i].ReplaceWith(profile);
    

    请注意,在这种情况下,您甚至没有尝试再次保存XML文件(由于return语句),因此在这种情况下,您试图实现的目的并不清楚。

  • 如果没有找到元素,则将profile元素添加到其本身,这当然不会修改文档。我怀疑你想要:

    doc.Root.Add(profile);
    

    也就是说,添加新的profile元素作为根元素的最后一个子元素。

编辑:这里有一个不同的方法来尝试代替-我假设任何一个名字应该只出现一次:

XDocument doc = XDocument.Load("profiles.xml");
var existingElement = doc.Root
                         .Elements()
                         .Where(x => x.Name.ToString() == Player.name)
                         .FirstOrDefault();
if (existingElement != null)
{
    existingElement.ReplaceWith(profile);
}
else
{
    doc.Root.Add(profile);
}
doc.Save("profiles.xml", SaveOptions.None);

另外,我强烈建议你不要使用玩家名作为元素。将其用作属性值或文本值,例如

XElement profile =
        new XElement("player",
            new XAttribute("name", Player.Name),
            new Attribute("level", Player.Level),
            new XAttribute("cash", Player.Cash)
        );

这样你就不会有问题,如果玩家的名字有空格等。然后您需要将查询更改为:

var existingElement = doc.Root
                         .Elements()
                         .Where(x => (string) x.Attribute("name)" == Player.name)
                         .FirstOrDefault();