来自另一个大型 XML 文件的新 XML 文件,使用未知元素更改内部数据

Dav*_*vid 4 c# xml

我有一个非常大(~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)

有没有办法

  1. 将文件作为流读取,这样我就不必一次将整个文件加载到内存中
  2. 复制设计时未定义的元素
  3. 更改特定元素中的数据
  4. 将结果写入新文件

Kot*_*ote 5

您可以使用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