This question already has answers here:
Can't Load asset as XML file
(2 answers)
Closed 8 years ago.
i'm trying to Deserialize an Xml document to an array of object. I did it with Xna but for monogame i have to change my method.
this is how i deserialize :
public static XmlData[] DeserializeFromXml<XmlData>(string inputFile)
{
XmlSerializer s = new XmlSerializer(typeof(XmlData));
XmlData[] deserializedObject = default(XmlData[]);
byte[] byteArray = Encoding.UTF8.GetBytes(inputFile);
//byte[] byteArray = Encoding.ASCII.GetBytes(contents);
MemoryStream stream = new MemoryStream(byteArray);
using (TextReader textReader = new StreamReader(stream))
{
deserializedObject = (XmlData[])s.Deserialize(textReader);
}
return deserializedObject;
}
my class XmlData :
public class XmlData
{
public int id;
public int posx;
public int posy;
public int rot;
public int Width;
public int Height;
}
my xml file :
<?xml version="1.0" encoding="utf-8" ?>
<Asset Type="XmlData[]">
<Item>
<id>17</id>
<posx>54</posx>
<posy>30</posy>
<rot>90</rot>
<Width>184</Width>
<Height>5</Height>
</Item>
<Item>
<id>1</id>
<posx>200</posx>
<posy>120</posy>
<rot>0</rot>
<Width>100</Width>
<Height>90</Height>
</Item>
</Asset>
And i have the following error :
There is an error in XML document (1, 1). (i'm using monogame)
Encoding.UTF8.GetBytes(inputFile);
You are trying to decode the filename here not the filecontent.
Try something like
using (StreamReader reader = StreamReader(inputFile,Encoding.UTF8,true))
{
XmlSerializer serializer = new XmlSerializer(typeof(XmlData));
return (XmlData[])serializer.Deserialize(reader);
}
Ok This will work on your xml file:
public static List<XmlData> DeserializeFromXml(string inputFile)
{
List<XmlData> mydata = new List<XmlData>();
XmlSerializer s = new XmlSerializer(typeof(List<XmlData>),new XmlRootAttribute("Asset"));
//XmlData[] deserializedObject = default(XmlData[]);
//byte[] byteArray = Encoding.UTF8.GetBytes(inputFile);
//byte[] byteArray = Encoding.ASCII.GetBytes(contents);
//MemoryStream stream = new MemoryStream(byteArray);
using (TextReader txtReader = new StreamReader(inputFile))
{
mydata = (List<XmlData>)s.Deserialize(txtReader);
}
return mydata;
}
Change <Item> to <XmlData> and you are well, or, place this in your XmlData class declaration:
[XmlType("Item")]
public class XmlData
you can use this code !!
using (XmlTextReader xmlReader = new XmlTextReader(yourfile))
{
XDocument xdoc = XDocument.Load(xmlReader);
var programs= from programItem in xdoc.Root.Elements()
select new xmldata {
Id = Convert.ToInt32( programItem.Attribute("Id").Value),
posx = Convert.ToInt32( programItem.Attribute("posx").Value),
poxy = Convert.ToInt32( programItem.Attribute("poxy").Value),
};
result = programs.ToList();
}
Thanks to #terrybozzio i finally find a way to read my xml file, before i had to convert it to a stream. But With Monogame Framework not alll methods are implemented.
Way to do it :
public static List<XmlData> DeserializeFromXml(string inputFile)
{
List<XmlData> mydata = new List<XmlData>();
XmlSerializer s = new XmlSerializer(typeof(List<XmlData>), new XmlRootAttribute("Asset"));
//XmlData[] deserializedObject = default(XmlData[]);
// byte[] byteArray = Encoding.UTF8.GetBytes(inputFile);
// byte[] byteArray = Encoding.ASCII.GetBytes(inputfile);
// MemoryStream stream = new MemoryStream(byteArray);
Stream test = TitleContainer.OpenStream("pets.xml");
using (TextReader txtReader = new StreamReader(test))
{
mydata = (List<XmlData>)s.Deserialize(txtReader);
}
return mydata;
}
Related
I've this sample .NET 6 program printing out a serialised object to XML:
using System.Text;
using System.Xml.Serialization;
var serializer = new XmlSerializer(typeof(Order));
var order = new Order
{
Address = new Address
{
FirstName = "Name"
}
};
await using var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8);
serializer.Serialize(streamWriter, order);
var result = Encoding.UTF8.GetString(memoryStream.ToArray());
Console.WriteLine(result);
public class Order
{
public Address Address;
}
public class Address
{
public string FirstName;
}
This results in this output:
<?xml version="1.0" encoding="utf-8"?><Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Address><FirstName>Name</FirstName></Address></Order>
In .NET 5 and .NET Core 3 similar code results in pretty printed XML like below. How can I format this XML in .NET6?
<?xml version="1.0" encoding="utf-8"?>
<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Address>
<FirstName>Name</FirstName>
</Address>
</Order>
To write indented xml you can use XmlTextWriter (instead of just StreamWriter) with Formatting set to Formatting.Indented:
await using var memoryStream = new MemoryStream();
XmlTextWriter streamWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
streamWriter.Formatting = Formatting.Indented;
serializer.Serialize(streamWriter, order);
var result = Encoding.UTF8.GetString(memoryStream.ToArray());
UPD
As #sveinungf wrote in the comment - using XmlWriter.Create is recommended approach, so the code can look like this (also note that Create method can accept StringBuilder or file name which can be more convenient in some scenarios):
await using var memoryStream = new MemoryStream();
var streamWriter = XmlWriter.Create(memoryStream, new()
{
Encoding = Encoding.UTF8,
Indent = true
});
serializer.Serialize(streamWriter, order);
var result = Encoding.UTF8.GetString(memoryStream.ToArray());
I have an object in c# that needs to be saved as file and reused.
So basically what I am doing now is I am serializing a class to xml and I am saving it as a file. The file is aproximatelly 100MB.
Now the problem I am experiencing is when I want to deserialize file to class, I and up with OutOfMemoryException.
I am using the following code:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(file);
Deserialize<T>(xmlDocument.InnerXml);
public static T Deserialize<T>(string xmlContent)
{
var inStream = new StringReader(xmlContent);
var ser = new XmlSerializer(typeof(T));
return (T)ser.Deserialize(inStream);
}
Here's what my comment would look like in code:
public static T Deserialize<T>(string Filepath)
{
using (FileStream FStream = new FileStream(Filepath, FileMode.Open))
{
var Deserializer = new XmlSerializer(typeof(T));
return (T)Deserializer.Deserialize(FStream);
}
}
I have a situation where I am generating a XML file to be submitted to a webservice, sometimes due to the amount of data it exceeds 30mb or 50mb.
I need to compress the file, using c#, .net framework 4.0, rather one of the nodes which has most of the data.. I have no idea how i am going to do it .. is it possible if someone can give me a example of how I can get this done please.
the xml file looks like this
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HeaderTalk xmlns="http://www.w3schools.com/xml">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>CHAR-CLM</Class>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID>aaaaaa</SenderID>
<Authentication>
<Method>MD5</Method>
<Role>principal</Role>
<Value>a3MweCsv60kkAgzEpXeCqQ==</Value>
</Authentication>
</IDAuthentication>
<EmailAddress>Someone#somewhere.com</EmailAddress>
</SenderDetails>
</Header>
<TalkDetails>
<ChannelRouting>
<Channel>
<URI>1953</URI>
<Product>My product</Product>
<Version>2.0</Version>
</Channel>
</ChannelRouting>
</TalkDetails>
<Body>
<envelope xmlns="http://www.w3schools.com/xml/">
<PeriodEnd>2013-08-13</PeriodEnd>
<IRmark Type="generic">zZrxvJ7JmMNaOyrMs9ZOaRuihkg=</IRmark>
<Sender>Individual</Sender>
<Report>
<AuthOfficial>
<OffName>
<Fore>B</Fore>
<Sur>M</Sur>
</OffName>
<Phone>0123412345</Phone>
</AuthOfficial>
<DefaultCurrency>GBP</DefaultCurrency>
<Claim>
<OrgName>B</OrgName>
<ref>AB12345</ref>
<Repayment>
<Account>
<Donor>
<Fore>Barry</Fore>
</Donor>
<Total>7.00</Total>
</Account>
<Account>
<Donor>
<Fore>Anthony</Fore>
</Donor>
<Total>20.00</Total>
</Account>
</Repayment>
</Claim>
</Report>
</envelope>
</Body>
</HeaderTalk>
The CLAIM node is what I want to Compress , as it can be Millions of records that get included in the XML.
I am a novice in coding, it has taken a long time for me to get this XML generated, and been searching to find a way to compress the node but I just cant get it to work..
the Result needs to be exactly same till the DefaultCurrency node..
and then
</AuthOfficial>
<DefaultCurrency>GBP</DefaultCurrency>
<CompressedPart Type="zip">UEsDBBQAAAAIAFt690K1</CompressedPart>
</Report>
</envelope>
</Body>
</HeaderTalk>
or
</AuthOfficial>
<DefaultCurrency>GBP</DefaultCurrency>
<CompressedPart Type="gzip">UEsDBBQAAAAIAFt690K1</CompressedPart>
</Report>
</envelope>
</Body>
</HeaderTalk>
Thank you everyone in advance please. Or if someone can suggest where I can look and get some idea, on what I want to do.
to create the file , I am simple iterating through a Dataset and Writing the nodes using XmlElements and setting innertexts to my values ..
The Code I have used to write is ..
//claim
XmlElement GovtSenderClaim = xmldoc.CreateElement("Claim");
XmlElement GovtSenderOrgname = xmldoc.CreateElement("OrgName");
GovtSenderOrgname.InnerText = Charity_name;
GovtSenderClaim.AppendChild(GovtSenderOrgname);
XmlElement GovtSenderHMRCref = xmldoc.CreateElement("ref");
GovtSenderHMRCref.InnerText = strref ;
GovtSenderClaim.AppendChild(GovtSenderref);
XmlElement GovtSenderRepayments = xmldoc.CreateElement("Repayment");
while (reader.Read())
{
XmlElement GovtSenderAccount = xmldoc.CreateElement("Account");
XmlElement GovtSenderDonor = xmldoc.CreateElement("Donor");
XmlElement GovtSenderfore = xmldoc.CreateElement("Fore");
GovtSenderfore.InnerText = reader["EmployeeName_first_name"].ToString();
GovtSenderDonor.AppendChild(GovtSenderfore);
GovtSenderAccount .AppendChild(GovtSenderDonor);
XmlElement GovtSenderTotal = xmldoc.CreateElement("Total");
GovtSenderTotal.InnerText = reader["Total"].ToString();
GovtSenderAccount .AppendChild(GovtSenderTotal);
GovtSenderRepayments.AppendChild(GovtSenderAccount );
}
GovtSenderClaim.AppendChild(GovtSenderRepayments);
GovtSenderReport.AppendChild(GovtSenderClaim);
and the rest of the nodes to close..
You can try this: it will compress only the nodes you select. It's a little different from what you asked, because it will replace the content of the element, leaving the element + its attributes as they were.
{
// You are using a namespace!
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Parse(xml);
// Compress
{
// Will compress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
// Decompress
{
// Will decompress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
DecompressElementContent(el);
}
}
}
public static void CompressElementContent(XElement el)
{
string content;
using (var reader = el.CreateReader())
{
reader.MoveToContent();
content = reader.ReadInnerXml();
}
using (var ms = new MemoryStream())
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Compress))
{
// So that the BOM isn't written we use build manually the encoder.
// See for example http://stackoverflow.com/a/2437780/613130
// But note that false is implicit in the parameterless constructor
using (StreamWriter sw = new StreamWriter(defl, new UTF8Encoding()))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
el.ReplaceAll(new XText(base64));
}
}
public static void DecompressElementContent(XElement el)
{
var reader = el.CreateReader();
reader.MoveToContent();
var content = reader.ReadInnerXml();
var bytes = Convert.FromBase64String(content);
using (var ms = new MemoryStream(bytes))
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(defl, Encoding.UTF8))
{
el.ReplaceAll(ParseXmlFragment(sr));
}
}
}
}
public static IEnumerable<XNode> ParseXmlFragment(StreamReader sr)
{
var settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var xmlReader = XmlReader.Create(sr, settings))
{
xmlReader.MoveToContent();
while (xmlReader.ReadState != ReadState.EndOfFile)
{
yield return XNode.ReadFrom(xmlReader);
}
}
}
The decompress is quite complex, because it's difficult to replace the content of an Xml. In the end I split the content XNode by Xnode in ParseXmlFragment and ReplaceAll in DecompressElementContent.
As a sidenote, you have two similar-but-different namespaces in you XML: http://www.w3schools.com/xml and http://www.w3schools.com/xml/
This other variant will do exactly what you asked (so it will create a CompressedPart node) minus the attribute with the type of compression.
{
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Parse(xml);
// Compress
{
// Here the ToList() is necessary, because we will replace the selected elements
var nodes = (from p in xml2.Descendants(ns + "Claim") select p).ToList();
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
// Decompress
{
// Here the ToList() is necessary, because we will replace the selected elements
var nodes = (from p in xml2.Descendants("CompressedPart") select p).ToList();
foreach (XElement el in nodes)
{
DecompressElementContent(el);
}
}
}
public static void CompressElementContent(XElement el)
{
string content = el.ToString();
using (var ms = new MemoryStream())
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Compress))
{
// So that the BOM isn't written we use build manually the encoder.
using (StreamWriter sw = new StreamWriter(defl, new UTF8Encoding()))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
var newEl = new XElement("CompressedPart", new XText(base64));
el.ReplaceWith(newEl);
}
}
public static void DecompressElementContent(XElement el)
{
var reader = el.CreateReader();
reader.MoveToContent();
var content = reader.ReadInnerXml();
var bytes = Convert.FromBase64String(content);
using (var ms = new MemoryStream(bytes))
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(defl, Encoding.UTF8))
{
var newEl = XElement.Parse(sr.ReadToEnd());
el.ReplaceWith(newEl);
}
}
}
}
I need to compress the file, using c#, .net framework 4.0, rather one of the nodes
You can use GZip compression. Something like
public static void Compress(FileInfo fileToCompress)
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fileToCompress.Name, fileToCompress.Length.ToString(), compressedFileStream.Length.ToString());
}
}
}
}
}
public static void Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
}
}
}
}
Another possible way of doing is by Deflate. See here. The major difference between GZipStream and Deflate stream will be that GZipStream will add CRC to ensure the data has no error.
What you're asking is possible, but somewhat involved. You'll need to create the compressed node in memory and then write it. I don't know how you're writing your XML, so I'll assume that you have something like:
open xml writer
write <MessageDetails>
write <SenderDetails>
write other nodes
write Claim node
write other stuff
close file
To write your claim node, you'll want to write to an in-memory stream and then base64 encode it. The resulting string is what you write to the file as your <CompressedPart>.
string compressedData;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gz = new GZipStream(CompressionMode.Compress, true))
{
using (XmlWriter writer = XmlWriter.Create(gz))
{
writer.WriteStartElement("Claim");
// write claim stuff here
writer.WriteEndElement();
}
}
// now base64 encode the memory stream buffer
byte[] buff = ms.GetBuffer();
compressedData = Convert.ToBase64String(buff, 0, buff.Length);
}
Your data is then in the compressedData string, which you can write as element data.
As I said in my comment, GZip will typically take 80% off your raw XML size, so that 50 MB becomes 10 MB. But base64 encoding will add 33% to the compressed size. I'd expect the result to be approximately 13.5 MB.
Update
Based on your additional code, what you're trying to do doesn't look too difficult. I think what you want to do is:
// do a bunch of stuff
GovtSenderClaim.AppendChild(GovtSenderRepayments);
// start of added code
// compress the GovtSenderClaim element
// This code writes the GovtSenderClaim element to a compressed MemoryStream.
// We then read the MemoryStream and create a base64 encoded representation.
string compressedData;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gz = new GZipStream(CompressionMode.Compress, true))
{
using (StreamWriter writer = StreamWriter(gz))
{
GovtSenderClaim.Save(writer);
}
}
// now base64 encode the memory stream buffer
byte[] buff = ms.ToArray();
compressedData = Convert.ToBase64String(buff, 0, buff.Length);
}
// compressedData now contains the compressed Claim node, encoded in base64.
// create the CompressedPart element
XElement CompressedPart = xmldoc.CreateElement("CompressedPart");
CompressedPart.SetAttributeValue("Type", "gzip");
CompressedPart.SetValue(compressedData);
GovtSenderReport.AppendChild(CompressedPart);
// GovtSenderReport.AppendChild(GovtSenderClaim);
This is what I have done to make it work ..
public void compressTheData(string xml)
{
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Load(xml);
// Compress
{
var nodes = (from p in xml2.Descendants(ns + "Claim") select p).ToList();
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
xml2.Save(xml);
}
public static void CompressElementContent(XElement el)
{
string content = el.ToString();
using (var ms = new MemoryStream())
{
using (GZipStream defl = new GZipStream(ms, CompressionMode.Compress))
{
using (StreamWriter sw = new StreamWriter(defl))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
XElement newEl = new XElement("CompressedPart", new XText(base64));
XAttribute attrib = new XAttribute("Type", "gzip");
newEl.Add(attrib);
el.ReplaceWith(newEl);
}
}
Thank you everyone for your inputs.
I was given a XSD file and sample XML file, and asked to post the XML file to a URL.
Sample XML file
<?xml version="1.0"?>
<pingRequest>
<elt></elt>
...
</pingRequest>
I'm familiar with SOAP and REST, but I have never done posting pure XML file directly. Here is what I got so far.
1) Generate C# class from XSD file
xsd.exe Test.xsd /c
2) Serialize from C# class to XML using XmlSerializer
public string SerializeObject(object obj, Type type)
{
string xml;
var xs = new XmlSerializer(type);
using (var ms = new MemoryStream())
{
xs.Serialize(ms, obj, null);
ms.Position = 0;
using (var sr = new StreamReader(memoryStream))
{
xml = sr.ReadToEnd();
}
}
return xml;
}
OR Should I use LINQ to XML to generate XML file?
3) Post XML to URL using WebClient
var client = new WebClient();
var uri = new Uri("http://www.site.com/");
string responseXML = client.UploadString(uri, requestXML);
Am I at the right track? If not, could you please point me to a right direction? Thanks in advance.
Here is my partial code so that other can use it.
First, created two classes based on XML tags using xsd.exe Test.xsd /c (for both request and response), so that I do not have to prase the XML files manually.
public pingResponse Send()
{
var pingRequest = new pingRequest
{
myelement = "test"
};
// Serialize pingRequest class to xml
var serializer = new Serializer();
string requestXml = serializer.SerializeObject(pingRequest, typeof(pingRequest));
// Post xml
var client = new WebClient();
var uri = new Uri("http://www.site.com/");
string responseXML = client.UploadString(uri, requestXML);
return (pingResponse)serializer.DeserializeObject(xml, typeof(Response));
}
public class Serializer
{
public string SerializeObject(object obj, Type type)
{
var setting = new XmlWriterSettings() {OmitXmlDeclaration = true, Indent = true};
var xml = new StringBuilder();
using (var writer = XmlWriter.Create(xml, setting))
{
var nsSerializer = new XmlSerializerNamespaces();
nsSerializer.Add(string.Empty, string.Empty);
var xmlSerializer = new XmlSerializer(type);
xmlSerializer.Serialize(writer, obj, nsSerializer);
}
return xml.ToString();
}
public object DeserializeObject(string xml, Type type)
{
var xs = new XmlSerializer(type);
var stringReader = new StringReader(xml);
var obj = xs.Deserialize(stringReader);
stringReader.Close();
return obj;
}
}
Note: I do not include the PingRequest and PingResponse classes since my member variables will not be same as yours.
I have the following variable that accepts a file name:
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
I would like to change it so that I can pass in an object. I don't want to have to serialize the object to file first.
Is this possible?
Update:
My original intentions were to take an xml document, merge some xslt (stored in a file), then output and return html... like this:
public string TransformXml(string xmlFileName, string xslFileName)
{
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
var xslt = new System.Xml.Xsl.XslCompiledTransform();
xslt.Load(xslFileName);
var stm = new MemoryStream();
xslt.Transform(xd, null, stm);
stm.Position = 1;
var sr = new StreamReader(stm);
xtr.Close();
return sr.ReadToEnd();
}
In the above code I am reading in the xml from a file. Now what I would like to do is just work with the object, before it was serialized to the file.
So let me illustrate my problem using code
public string TransformXMLFromObject(myObjType myobj , string xsltFileName)
{
// Notice the xslt stays the same.
// Its in these next few lines that I can't figure out how to load the xml document (xd) from an object, and not from a file....
var xtr = new XmlTextReader(xmlFileName) { WhitespaceHandling = WhitespaceHandling.None };
var xd = new XmlDocument();
xd.Load(xtr);
}
You want to turn an arbitrary .NET object into a serialized XML string? Nothing simpler than that!! :-)
public string SerializeToXml(object input)
{
XmlSerializer ser = new XmlSerializer(input.GetType(), "http://schemas.yournamespace.com");
string result = string.Empty;
using(MemoryStream memStm = new MemoryStream())
{
ser.Serialize(memStm, input);
memStm.Position = 0;
result = new StreamReader(memStm).ReadToEnd();
}
return result;
}
That should to it :-) Of course you might want to make the default XML namespace configurable as a parameter, too.
Or do you want to be able to create an XmlDocument on top of an existing object?
public XmlDocument SerializeToXmlDocument(object input)
{
XmlSerializer ser = new XmlSerializer(input.GetType(), "http://schemas.yournamespace.com");
XmlDocument xd = null;
using(MemoryStream memStm = new MemoryStream())
{
ser.Serialize(memStm, input);
memStm.Position = 0;
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
using(var xtr = XmlReader.Create(memStm, settings))
{
xd = new XmlDocument();
xd.Load(xtr);
}
}
return xd;
}
You can serialize directly into the XmlDocument:
XmlDocument doc = new XmlDocument();
XPathNavigator nav = doc.CreateNavigator();
using (XmlWriter w = nav.AppendChild())
{
XmlSerializer ser = new XmlSerializer(typeof(MyType));
ser.Serialize(w, myObject);
}
Expanding on #JohnSaunders solution I wrote the following generic function:
public XmlDocument SerializeToXml<T>(T source) {
var document = new XmlDocument();
var navigator = document.CreateNavigator();
using (var writer = navigator.AppendChild()) {
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, source);
}
return document;
}