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

发布于 2024-12-12 17:55:02 字数 906 浏览 0 评论 0原文

我正在创建一个新的 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 文件中创建一个新的配置文件,它也不会自定义,因此问题出在保存文件中?

I'm creating a new XDocument and inserting a root element "profiles" in it, then saving.

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

And then later I wanna take users input and add profiles into the already created xml file:

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

But for some reason, it will never add any new profiles?

EDIT: Also, if I manually create a new profile into the xml file, it won't customize either, so the problem is within Saving the file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静待花开 2024-12-19 17:55:02

您实际上从未执行任何操作来更改 doc 引用的 XDocument 中的任何元素:

  • 如果您找到具有现有名称的元素,您'重新修改列表,但这不会修改文档。您可能想使用 XElement.ReplaceWith

    profiles[i].ReplaceWith(profile);
    

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

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

    doc.Root.Add(配置文件);
    

    换句话说,将新的配置文件元素添加为根元素的新最终子元素。

编辑:这里有一种不同的方法可以尝试 - 我假设任何一个名称只应该出现一次:

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();

You're never actually doing anything to change any of the elements within the XDocument that doc refers to:

  • If you find an element with the existing name, you're modifying the list, but that won't modify the document. You probably want to use XElement.ReplaceWith:

    profiles[i].ReplaceWith(profile);
    

    Note that in this case you're not even trying to save the XML file again (due to the return statement), so it's not really clear what you're trying to achieve in this case.

  • If you don't find the element, you're adding the profile element to itself, which certainly isn't going to modify the document. I suspect you want:

    doc.Root.Add(profile);
    

    In other words, add the new profile element as a new final child of the root element.

EDIT: Here's a different approach to try instead - I'm assuming any one name should only occur once:

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

Also, I would strongly advise you not to use the player name as the element name. Use it as an attribute value or text value instead, e.g.

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

That way you won't have problems if the player name has spaces etc. You'd then need to change your query to:

var existingElement = doc.Root
                         .Elements()
                         .Where(x => (string) x.Attribute("name)" == Player.name)
                         .FirstOrDefault();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文