读取xml,更新它并再次写入流而不加载所有内容

时间:2015-02-05 22:30:03

标签: c# xml

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文件精确地镜像到更新函数什么都不做的地方,并在输出新值时注入新的xml。 xml文件无限长,无法在内存中。如何才能做到这一点? c#/ .net输入和输出都是分块的网络流,所以它只需要尽可能快地读取它。

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

1 个答案:

答案 0 :(得分:0)

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

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);
            }               
        }

}

相关问题