我有一个非常大(~1GB)的 XML 文件。我需要解析它,找到特定节点,更改这些节点中的数据,然后将其全部写入新的 XML 文件。这里有一个问题——有很多我不关心的元素——我什至不知道它们都是什么——但它们也需要复制。
这篇SO 帖子建议我使用 XmlReader,这样我就不必将整个输入文件加载到内存中。该问题有这个答案,建议使用该ReadToDescendant方法。这几乎可以满足我的需要,但问题是我在“读取”节点之前丢失了所有 XML。不知何故,我需要将我刚刚阅读的所有内容复制到新文件中。我不在乎那里有什么,它只需要逐字复制。
这个SO 帖子会起作用(还有其他几个类似的帖子),除了它使用XmlDocument它,如果我没记错的话,它会首先将整个内容加载到内存中。虽然这对小文件没问题,但我想在这里避免这种情况。
对于您的视觉类型,这是我想要做的事情的想法:
<root>
<SomeNodeUndefinedAtDesignTime>
<ThisNodeHasSubNodes>
<WhichHasSubNodes_Etc/>
</ThisNodeHasSubNodes>
</SomeNodeUndefinedAtDesignTime>
<AnotherUndefinedNode>
<!--Similar to the first, who knows what all is in here-->
</AnotherUndefinedNode>
<!-- There may be dozens or even hundreds of these -->
<ANodeIAmInterestedIn>
Old data to be replaced
</ANodeIAmInterestedIn>
<ANodeIAmInterestedIn>
More data to be replaced
</ANodeIAmInterestedIn>
<YetAnotherUndefinedNode>
<!-- stuff -->
</YetAnotherUndefinedNode>
</root>
Run Code Online (Sandbox Code Playgroud)
我想接受那个输入然后输出这个:
<root>
<SomeNodeUndefinedAtDesignTime>
<ThisNodeHasSubNodes>
<WhichHasSubNodes_Etc/>
</ThisNodeHasSubNodes>
</SomeNodeUndefinedAtDesignTime>
<AnotherUndefinedNode>
<!--Similar to the first, who knows what all is in here-->
</AnotherUndefinedNode>
<!-- There may be dozens or even hundreds of these -->
<ANodeIAmInterestedIn>
Here is my new data
</ANodeIAmInterestedIn>
<ANodeIAmInterestedIn>
Here is more new data
</ANodeIAmInterestedIn>
<YetAnotherUndefinedNode>
<!-- stuff -->
</YetAnotherUndefinedNode>
</root>
Run Code Online (Sandbox Code Playgroud)
有没有办法
您可以使用XmlReader和创建一个方法,XmlWriter该方法将完全满足您的要求。
public void CopyTo(XmlReader reader, XmlWriter writer,
Dictionary<string, string> replacements)
{
var currentElementName = "";
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
currentElementName = reader.Name;
writer.WriteStartElement(reader.Name);
//Copy all attributes verbatim
if (reader.HasAttributes)
writer.WriteAttributes(reader, true);
//Handle empty elements by telling the writer to close right away
if (reader.IsEmptyElement)
writer.WriteEndElement();
break;
case XmlNodeType.EndElement:
currentElementName = "";
writer.WriteEndElement();
break;
case XmlNodeType.Text:
if (replacements.ContainsKey(currentElementName))
writer.WriteString(replacements[currentElementName]);
else
writer.WriteString(reader.Value);
break;
case XmlNodeType.Whitespace:
writer.WriteWhitespace(reader.Value);
break;
//Other cases. Attributes, comments etc.
}
writer.Flush();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的例子,它不会处理属性和其他一些人员,但它可以很好地处理元素。
它将复制 xml 结构和所有元素并替换innerText已知元素。
用法:
var xmlReader = XmlReader.Create(File.OpenRead("inputFilePath"));
var xmlWriter = XmlWriter.Create(File.OpenWrite("outputFilePath"));
var replacements = new Dictionary<string, string> { ... };
CopyTo(xmlReader, xmlWriter, replacements);
Run Code Online (Sandbox Code Playgroud)
此外,如果你想做一些有用的事情,当它读取大元素时,你可以使用方法的async版本XmlReader。