【问题标题】:How to format a Xml-Stream for writing into file如何格式化 Xml-Stream 以写入文件
【发布时间】:2013-09-03 18:42:08
【问题描述】:

我从 Web 服务请求一个非常大 (>500mb) 的 xml 文件,并将ResponseStream 的内容直接写入FileStream。但是当我打开生成的 xml 文件时,内容如下所示:

<Changes requestChangeTrackingId="-1" resultChangeTrackingId="2387">
<Selectors>
<Selector selectorId="1"><DateValidFrom>2000-01-01T00:00:00</DateValidFrom><DateValidTo>2099-12-31T00:00:00</DateValidTo><Code20Z>01A</Code20Z><CodeNUM/><CodeENT>1</CodeENT><ShortName>01A</ShortName></Selector>
<Selector selectorId="2"><DateValidFrom>2000-01-01T00:00:00</DateValidFrom><DateValidTo>2099-12-31T00:00:00</DateValidTo><Code20Z>01B</Code20Z><CodeNUM/><CodeENT>2</CodeENT><ShortName>01B</ShortName></Selector>

如何格式化流,使其看起来像这样:

<Changes requestChangeTrackingId="-1" resultChangeTrackingId="2387">
<Selectors>
<Selector selectorId="1">
   <DateValidFrom>2000-01-01T00:00:00</DateValidFrom>
   <DateValidTo>2099-12-31T00:00:00</DateValidTo>
   <Code20Z>01A</Code20Z>
   <CodeNUM/>
   <CodeENT>1</CodeENT>
   <ShortName>01A</ShortName>
</Selector>
[...]

我无法将整个文件加载到内存中,因此无法使用类似的解决方案

XDocument.Load( responseStream ).Save( "somefile.xml" );

有没有办法将流传递到某种 XmlStreamFormatter 并将流直接写入文件系统?要存储的文件可能非常大,以至于不可能总是将整个流加载到内存中并在那里格式化。

【问题讨论】:

  • 要么您需要创建足够多的 XML 解析器来执行格式化(这是个坏主意)。或者,您需要解析 XML(例如,通过 XmlReader)足以输入到最小 XSLT 转换中,该转换在 &lt;xsl:output&gt; 元素中包含 indent="yes"。 (第三种选择是自定义XmlWriter 来实现它...不像第一种选择那么难,但如果您知道 XSTL,则比 XSLT 更难。注意。任何涉及到内存的完整 500MB XML 文件的选项最好有足够的要运行的内存!
  • 附加:为什么要格式化。 500MB XML 太大,无法以任何有用的方式手动处理。
  • @Richard 我只是想格式化它,因为它将为需要验证通过 Web 服务发送的数据类型的人提供更好的可读性。对于自动化处理,无需这样做。
  • 原来我忘了XmlWriterSettings.Indent...

标签: xml stream


【解决方案1】:

XmlWriterSettings.Indent 在这里提供了一种机制的核心,因此需要确保不需要加载整个内容(但在运行性能计数器的情况下进行一些仔细的测试绝对是可取的。只是一个组件太急于阅读数据输入可能会导致大的地址空间和提交使用。因此,对于大约 500MB 的数据大小,我将确保它仅针对 x64 构建——没有 AnyCPU 构建。

比如:

void FormatXmlToFile(FileStream input, string outputFile) {
    using (var output = new FileStream(outputFile, FileMode.CreateNew)) {
        var reader = XmlReader.Create(input);
        var writerSettings = new XmlWriterSettings {
            Indent = true
        };

        using (var writer = XmlWriter.Create(output, writerSettings)) {
            writer.WriteNode(reader, true);
        }
    }
}

【讨论】:

  • 如果您想在 UI 线程上运行它,请将 WriteNode 替换为 WriteNodeAsync,转换为 async 方法并在返回的 Task 完成时更新 UI 以完成。
猜你喜欢
  • 1970-01-01
  • 2011-08-05
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 2016-11-12
相关资源
最近更新 更多