使用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)。
来拆解下代码的执行逻辑:
- 第一次调用
element1.AppendChild(element2)时,<song>节点还没有任何<line>子节点,所以它被加入到<root>中,呈现为空节点的样子。 - 接着你给这个
<song>节点添加所有<line>子节点,此时<root>中已存在的那个<song>节点会自动更新(因为它们是同一个对象引用)。 - 第二次调用
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
相关产品推荐
相关产品推荐

