Get a Stream from an XmlReader

Actually, you can.
It just requires some libraries that not everyone uses, because they're part of BizTalk.
If you have access to the BizTalk runtime, you can utilize an XmlTranslatorStream to provide a Stream instance from an XmlReader instance:

var xmlStream = new XmlTranslatorStream(xmlReader);

There are 3 constructors you can use.

Yeah, extremely hefty requirements to get a Stream from an XmlReader, so you can see why most answers equate to "you can't get there from here!"

Hope that helps,
Jay


The XmlReader may or may not be backed by a Stream. I've fooled around with some methods using reflection to try to get the Stream or TextWriter backing the XmlReader, but in the end I think it's probably most straightforward to write the object to a new stream; I'd recommend this method over the accepted answer because the accepted answer won't perform very well on large documents, and this is basically a simplified version of what the BizTalk version in Jay's answer will do (BizTalk does some automatic detection of whether it should use a FileStream or MemoryStream and has some other special handling for the XML):

public static class XmlExtensions
{
    public static MemoryStream ToStream(this XmlReader reader)
    {
        MemoryStream ms = new MemoryStream();
        reader.CopyTo(ms);
        return ms;
    }

    public static FileStream ToStream(this XmlReader reader, string fileName)
    {
        FileStream fs = new FileStream(fileName, FileMode.Create);
        reader.CopyTo(fs);
        return fs;
    }

    public static void CopyTo(this XmlReader reader, Stream s)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.CheckCharacters = false; // don't get hung up on technically invalid XML characters
        settings.CloseOutput = false; // leave the stream open
        using (XmlWriter writer = XmlWriter.Create(s, settings))
        {
            writer.WriteNode(reader, true);
        }
    }
}

CopyTo would allow you to set your stream up however you like; ToStream gives you a couple helpful common cases where you just want to quickly get a regular MemoryStream (for smaller XML files) or use a FileStream (for larger ones).

Of course, in the end, if you're really doing this for serialization purposes, it'd be good to just add an overload to your serialization class like:

XMySerializer.Deserialize(XmlReader reader, object graph)

Both XmlSerializer and DataContractSerializer in the BCL follow that idea...


I think there is no way, getting the stream, the XmlReader uses. The Workaround would be to use XmlReader.ReadOuterXml() to get the whole XML as a string and put it in a MemoryStream.

Tags:

C#

.Net