Get a Stream from an XmlReader
As a result of a stored procedure I get a SqlXml
object, from which I can call CreateReader
to get a standard XmlReader
so as I can handle it in my dll.
In the business layer of the application, I have an XMySerializer
that could read the xml and instantiate the business object.
However the XMySerializer.Deserialize
function takes a System.IO.Stream as an input.
So, the question is how could I get a System.开发者_开发问答IO.Stream
from a System.Xml.XmlReader
?
Counterwise would be easier...
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
.
You cannot. XmlReader
is an abstract class that has many implementations (including some that read from streams but others have nothing to do with streams). However you can write the data in this XML reader to a System.IO.MemoryStream
and then provide this stream to your XMySerializer.Deserialize
function.
精彩评论