【问题标题】:Read xml, update it and write to stream again without loading it all读取 xml,更新它并再次写入流而不加载它
【发布时间】:2015-02-05 22:30:03
【问题描述】:
var stream = response.GetResponseStream();
var outStream = body.GetStream();

XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.IgnoreWhitespace = false;
var reader = XmlReader.Create(stream, readerSettings);

Func<XML,XML?> updateCallback = (xml) => {
    //Read xml, maybe update it and return new element.

}

鉴于上述情况,我目前只是await stream.copyToAsync(outstream) 我想创建一个解决方案,在下面的 xml 中的每个电影元素上调用 updateCallback,并将回调中所做的任何更改写出到 outstream。

它应该将 xml 文件镜像到 update 函数什么都不做的地方,并在它输出新值时注入新的 xml。 xml 文件是无限长的,不能在内存中。如何才能做到这一点? c#/.net 输入和输出都是分块的网络流,所以它只需要尽可能快地推送它。

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Movies>
        <Movie>
            <... attributes ...>
        </Movie>
        <Movie>
            <... attributes ...>
        </Movie>
    </Movies>
</Root>

【问题讨论】:

标签: c# xml


【解决方案1】:

感谢您的链接。我想出了这个。

class Program
{
    static void WriteShallowNode(XmlReader reader, XmlWriter writer)
    {
        if (reader == null)
        {
            throw new ArgumentNullException("reader");
        }
        if (writer == null)
        {
            throw new ArgumentNullException("writer");
        }

        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                writer.WriteAttributes(reader, true);
                if (reader.IsEmptyElement)
                {
                    writer.WriteEndElement();
                }
                break;
            case XmlNodeType.Text:
                writer.WriteString(reader.Value);
                break;
            case XmlNodeType.Whitespace:
            case XmlNodeType.SignificantWhitespace:
                writer.WriteWhitespace(reader.Value);
                break;
            case XmlNodeType.CDATA:
                writer.WriteCData(reader.Value);
                break;
            case XmlNodeType.EntityReference:
                writer.WriteEntityRef(reader.Name);
                break;
            case XmlNodeType.XmlDeclaration:
            case XmlNodeType.ProcessingInstruction:
                writer.WriteProcessingInstruction(reader.Name, reader.Value);
                break;
            case XmlNodeType.DocumentType:
                writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value);
                break;
            case XmlNodeType.Comment:
                writer.WriteComment(reader.Value);
                break;
            case XmlNodeType.EndElement:
                writer.WriteFullEndElement();
                break;
        }
    }
    public static bool Transform(XElement el)
    {

        el.Name = "a";

        return true;
    }
    static void Main(string[] args)
    {
        XmlReaderSettings readerSettings = new XmlReaderSettings();
        readerSettings.IgnoreWhitespace = false;
        var writer = XmlWriter.Create(File.OpenWrite(@"C:\dev\testout.xml"));
        var reader = XmlReader.Create(File.OpenRead(@"C:\dev\test.xml"), readerSettings);

        var flag = false;
        while (reader.Read())
        {
            if (reader.Name == "Movie")
            {
                var el = (XElement)XNode.ReadFrom(reader);
                if (Transform(el))
                    el.WriteTo(writer);
            }
            else
            {
                WriteShallowNode(reader, writer);
            }               
        }

}

【讨论】:

  • 啊,你打败了我。
  • 对不起 :) 我只是倾向于在知道我是否能解决之前问这个问题。这样其他人也可以在找到答案时得到答案。
猜你喜欢
  • 2014-09-04
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多