通过使用 C# 添加节点来更新存储文件夹中的 xml 文件

Update an xml file in a storage folder by adding nodes using C#

我正在用 C# 制作一个通用应用程序,我正在尝试通过向其添加一些节点来更新存储文件夹中的 xml 文件。理想情况下,从这样的文件开始

<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
</MyRoot>

我想添加其他节点以获得

<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
<ParentNode>
<myNode1>value3</myNode1>
<myNode2>value4</myNode2>
</ParentNode>
</MyRoot>

我得到的是一个无效的 xml 文件,其中包含我想要附加到以前内容的内容,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
</MyRoot><?xml version="1.0" encoding="utf-8"?>
<MyRoot>
  <ParentNode>
    <myNode1>value1</myNode1>
    <myNode2>value2</myNode2>
  </ParentNode>
  <ParentNode>
    <myNode1>value3</myNode1>
    <myNode2>value4</myNode2>
  </ParentNode>
</MyRoot>

这是代码

StorageFile myFile = await ApplicationData.Current.LocalFolder.GetFileAsync("myFile.xml");
using (IRandomAccessStream writeStream = await myFile.OpenAsync(FileAccessMode.ReadWrite))
{
    // convert IRandomAccessStream to IO.Stream
    Stream s = writeStream.AsStreamForWrite();

    //xml
    XDocument document = XDocument.Load(s);
    document.Root.Add(
        new XElement("ParentNode",
        new XElement("myNode1", "value3"),
        new XElement("myNode2", "value4"))
        );
    document.Save(s);
} 

尝试以下方法:

        XmlDocument doc = new XmlDocument();
        doc.Load("yourfile.xml");

        var root = doc.DocumentElement;

        var parentNode = doc.CreateElement("ParentNode");
        root.AppendChild(parentNode);

        var myNode1 = doc.CreateElement("myNode1");
        myNode1.Value = "value3";
        parentNode.AppendChild(myNode1);

        // ...add more nodes etc...

        doc.Save("yourfile.xml");

调用 XDocument.Load 后,您位于流的末尾,因此调用 document.Save 会将新内容附加到流的末尾。

只要您只是将节点添加到现有的 XML 中,从而使每次保存的文件变长,您可以通过在调用 [=13= 之前移动到流的开头来解决问题]:

document.Root.Add(
    new XElement("ParentNode",
    new XElement("myNode1", "value3"),
    new XElement("myNode2", "value4"))
    );
s.Seek(0, SeekOrigin.Begin); // <-- add this line
document.Save(s);

如果您开始删除节点,这将不起作用,因为并不是所有的旧文件都会被覆盖,一些遗留的文件会留在最后。在这种情况下,您需要在加载后关闭流并创建一个新文件以通过覆盖现有文件来保存:

StorageFile newFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myFile.xml",
    CreationCollisionOption.ReplaceExisting);