编辑大型XML文件

时间:2018-02-02 02:00:07

标签: c# xml

我有一个3GB的XML文件。我需要将节点作为另一个节点的子节点移动。将大文件加载为XmlDocument效率不高。我看到XmlReader是另一种方法,但不确定它在我的场景中究竟是如何工作的,以及我应该使用哪些其他类来实现这一点。

我需要将所有别名节点移动到其相关客户>名称节点。

<customer>
<name><first>Robert</first></name>
<alias>Rob</alias>
</customer>

2 个答案:

答案 0 :(得分:1)

我真的不明白你想要执行什么转换,但假设@ dbc的猜测是正确的,你可以使用像这样的流式XSLT 3.0处理器:

<xsl:transform version="3.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:mode streamable="yes" on-no-match="shallow-copy">

<xsl:template match="customer">
  <xsl:apply-templates select="copy-of(.)" mode="local"/>
</xsl:template>

<xsl:mode name="local" streamable="no" on-no-match="shallow-copy"/>

<xsl:template match="name" mode="local">
  <name>
    <xsl:apply-templates mode="local"/>
    <xsl:copy-of select="../alias"/>
  </name>
</xsl:template>

<xsl:template match="alias" mode="local"/>

</xsl:transform>

这里发生的事情是,在我们点击客户元素之前,所有内容都会以纯流模式(标记标记)进行复制。当我们遇到客户元素时,我们制作元素的内存副本,并使用传统的非流转换在本地转换它。因此,所需的内存量足以容纳最大的客户元素。

答案 1 :(得分:0)

您可以采取的措施是将来自Mark Fussell的文章Combining the XmlReader and XmlWriter classes for simple streaming transformationsXmlReader流式传输到XmlWriter的基本逻辑,将您的3GB文件转换为修改后的文件其中<alias>个节点已重定位到<name>个节点。 this answer Automating replacing tables from external files 中提供了使用此类流式转换的示例。

以该答案为基础,从中抓取课程XmlReaderExtensionsXmlWriterExtensionsXmlStreamingEditorBaseXmlStreamingEditor以及XmlStreamingEditor子类以创建{{1}如下:

CustomerAliasXmlEditor

然后,如果class CustomerAliasXmlEditor : XmlStreamingEditor { // Confirm that the <customer> element is not in any namespace. static readonly XNamespace customerNamespace = ""; public static void TransformFromTo(string fromFilePath, XmlReaderSettings readerSettings, string toFilePath, XmlWriterSettings writerSettings) { using (var xmlReader = XmlReader.Create(fromFilePath, readerSettings)) using (var xmlWriter = XmlWriter.Create(toFilePath, writerSettings)) { new CustomerAliasXmlEditor(xmlReader, xmlWriter).Process(); } } public CustomerAliasXmlEditor(XmlReader reader, XmlWriter writer) : base(reader, writer, ShouldTransform, Transform) { } static bool ShouldTransform(XmlReader reader) { return reader.GetElementName() == customerNamespace + "customer"; } static void Transform(XmlReader from, XmlWriter to) { var customer = XElement.Load(from); var alias = customer.Element(customerNamespace + "alias"); if (alias != null) { var name = customer.Element(customerNamespace + "name"); if (name == null) { name = new XElement(customerNamespace + "name"); customer.Add(name); } alias.Remove(); name.Add(alias); } customer.WriteTo(to); } } 是您当前3GB XML文件的名称,而fromFileName是要将转换后的XML输出到的文件的名称,则可以执行以下操作:

toFileName

示例工作.Net fiddle显示XML

var readerSettings = new XmlReaderSettings { IgnoreWhitespace = true };
var writerSettings = new XmlWriterSettings { Indent = false}; // Or true if you prefer.

CustomerAliasXmlEditor.TransformFromTo(fromFileName, readerSettings, toFileName, writerSettings);

转换为

<Root>
<Item>
<SubItem>
<customer>
<name><first>Robert</first></name>
<alias>Rob</alias>
</customer>
</SubItem>
</Item>
<Item>
</Root>