You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C#创建XML文档时出现重复空song节点,求解决方案

为什么我的C# XmlDocument代码生成重复的空<song>节点?

我使用以下C#代码创建XML文档:

XmlDocument finalDoc = new XmlDocument(); 
//(1) the xml declaration is recommended, but not mandatory
XmlDeclaration xmlDeclaration = finalDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = finalDoc.DocumentElement;
finalDoc.InsertBefore(xmlDeclaration, root);
//(2) string.Empty makes cleaner code
XmlElement element1 = finalDoc.CreateElement(string.Empty, "root", string.Empty);
finalDoc.AppendChild(element1);
for (int i = 0; i < 5; i++) {
    XmlElement element2 = finalDoc.CreateElement(string.Empty,"song", string.Empty);
    element2.SetAttribute("title", "title" + i);
    element1.AppendChild(element2);
    for (int k=0; k<5;k++) {
        XmlElement element3 = finalDoc.CreateElement(string.Empty, "line", string.Empty);
        element3.InnerText = "text " + k;
        element2.AppendChild(element3);
    }
    element1.AppendChild(element2);
}
finalDoc.Save("C:\\Users\\adm\\Downloads\\finalDoc.xml");

得到的输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <song title="title 0" />
  <song title="title 0">
    <line>text 0</line>
    <line>text 1</line>
    <line>text 2</line>
    <line>text 3</line>
    <line>text 4</line>
  </song>
  <song title="title 1" />
  <song title="title 1">
    ...
  </song>
  ...
</root>

如您所见,我得到了重复的空“song”节点,请问我忽略了什么?

问题的根源很明确:你针对同一个<song>节点调用了两次element1.AppendChild(element2)。

来拆解下代码的执行逻辑:

  1. 第一次调用element1.AppendChild(element2)时,<song>节点还没有任何<line>子节点,所以它被加入到<root>中,呈现为空节点的样子。
  2. 接着你给这个<song>节点添加所有<line>子节点,此时<root>中已存在的那个<song>节点会自动更新(因为它们是同一个对象引用)。
  3. 第二次调用element1.AppendChild(element2)时,由于XML DOM不允许同一个节点同时存在于树的两个位置,它会把这个<song>节点从原来的位置移除,再重新添加到<root>的末尾。这就导致你看到了看似重复的节点——实际上是同一个节点被移动了位置,但你的输出模拟可能放大了这个问题。

解决方法非常简单:只在完成所有<line>子节点的添加后,调用一次AppendChild。修改后的循环代码如下:

for (int i = 0; i < 5; i++) {
    XmlElement element2 = finalDoc.CreateElement(string.Empty,"song", string.Empty);
    element2.SetAttribute("title", "title" + i);
    // 移除第一次的AppendChild调用
    for (int k=0; k<5;k++) {
        XmlElement element3 = finalDoc.CreateElement(string.Empty, "line", string.Empty);
        element3.InnerText = "text " + k;
        element2.AppendChild(element3);
    }
    element1.AppendChild(element2); // 只在这里添加一次
}

这样每个<song>节点都会在包含所有<line>子节点后,被添加到<root>中一次,不会出现重复或空节点的问题。

内容的提问来源于stack exchange,提问作者Felipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:24:34