Edit:我决定采用推荐的 LINQ to XML 方法(请参阅下面的答案),并且一切正常,只是我无法用增量文件中的记录替换更改的记录。我设法通过删除完整文件节点然后添加增量节点来使程序正常运行。有没有办法直接交换它们?另外,虽然这个解决方案非常好,但是有没有办法在不丢失 LINQ 代码的情况下减少内存使用量?这个解决方案可能仍然有效,但我愿意牺牲时间来降低内存使用量。
我正在尝试获取两个 XML 文件(一个完整文件和一个增量文件)并将它们合并在一起。 XML 文件如下所示:
<List>
<Records>
<Person id="001" recordaction="add">
...
</Person>
</Records>
</List>
recordaction 属性还可以是“chg”(表示更改)或“del”(表示删除)。我的程序的基本逻辑是:
1) 将完整文件读入 XmlDocument。
2)将增量文件读入XmlDocument,使用XmlDocument.SelectNodes()选择节点,将这些节点放入字典中以便于搜索。
3) 选择完整文件中的所有节点,循环遍历并对照包含增量记录的字典检查每个节点。如果 recordaction="chg" 或 "del" 将节点添加到列表中,则从 XmlNodeList 中删除该列表中的所有节点。最后,将增量文件中的 recordaction="chg" 或“add”记录添加到完整文件中。
4) 保存 XML 文件。
我在执行第 3 步时遇到了一些严重问题。以下是该函数的代码:
private void ProcessChanges(XmlNodeList nodeList, Dictionary<string, XmlNode> dictNodes)
{
XmlNode lastNode = null;
XmlNode currentNode = null;
List<XmlNode> nodesToBeDeleted = new List<XmlNode>();
// If node from full file matches to incremental record and is change or delete,
// mark full record to be deleted.
foreach (XmlNode fullNode in fullDocument.SelectNodes("/List/Records/Person"))
{
dictNodes.TryGetValue(fullNode.Attributes[0].Value, out currentNode);
if (currentNode != null)
{
if (currentNode.Attributes["recordaction"].Value == "chg"
|| currentNode.Attributes["recordaction"].Value == "del")
{
nodesToBeDeleted.Add(currentNode);
}
}
lastNode = fullNode;
}
// Delete marked records
for (int i = nodeList.Count - 1; i >= 0; i--)
{
if(nodesToBeDeleted.Contains(nodeList[i]))
{
nodeList[i].ParentNode.RemoveChild(nodesToBeDeleted[i]);
}
}
// Add in the incremental records to the new full file for records marked add or change.
foreach (XmlNode weeklyNode in nodeList)
{
if (weeklyNode.Attributes["recordaction"].Value == "add"
|| weeklyNode.Attributes["recordaction"].Value == "chg")
{
fullDocument.InsertAfter(weeklyNode, lastNode);
lastNode = weeklyNode;
}
}
}
传入的 XmlNodeList 只是从增量文件中选择的所有增量记录,字典只是那些相同的节点,但在 id 上键入,因此我不必循环遍历所有增量记录每一次。现在,由于索引越界,程序正在“删除标记记录”阶段死亡。我很确定“添加增量记录”也不起作用。有任何想法吗?另外,一些关于提高效率的建议也很好。我可能会遇到一个问题,因为它正在读取一个 250MB 的文件,而该文件在内存中会膨胀到 750MB,所以我想知道是否有一种更简单的方法可以在完整文件中逐节点读取。谢谢!