XmlSerializer.Serialize Stripping the <xml> tag - c#

I am trying to get communicate to a payment processor. When I use XmlSerializer.Serialize
on my object I get
<?xml version=\"1.0\" encoding=\"utf-16\"?>
<txn xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<ssl_merchant_id>xxxxxx</ssl_merchant_id>
<ssl_user_id>xxxxxx</ssl_user_id>
<ssl_pin>xxxxxx</ssl_pin>
<ssl_test_mode>True</ssl_test_mode>
<ssl_transaction_type>ccavsonly</ssl_transaction_type>
<ssl_card_number>4111111111111111</ssl_card_number>
<ssl_exp_date>0612</ssl_exp_date>
<ssl_avs_address>101 Main St.</ssl_avs_address>
<ssl_avs_zip>90210</ssl_avs_zip>
</txn>
Prior to using that method, I manually built the XML for testing and this worked:
<txn>
<ssl_merchant_id>xxxxxx</ssl_merchant_id>
<ssl_user_id>xxxxxx</ssl_user_id>
<ssl_pin>xxxxxx</ssl_pin>
<ssl_test_mode>True</ssl_test_mode>
<ssl_transaction_type>ccavsonly</ssl_transaction_type>
<ssl_card_number>4111111111111111</ssl_card_number>
<ssl_exp_date>0612</ssl_exp_date>
<ssl_avs_address>101 Main St.</ssl_avs_address>
<ssl_avs_zip>90210</ssl_avs_zip>
</txn>
How would I go about stripping out the <?xml version=\"1.0\" encoding=\"utf-16\"?> and xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> from the XML or not have the serializer generate it to begin with?
My object looks like:
[XmlRoot(ElementName="txn")]
public class AvsTransmission
{
[XmlElement]
public string ssl_merchant_id { get; set; }
[XmlElement]
public string ssl_user_id { get; set; }
[XmlElement]
public string ssl_pin { get; set; }
[XmlElement]
public string ssl_test_mode { get; set; }
[XmlElement]
public string ssl_transaction_type { get; set; }
[XmlElement]
public string ssl_card_number { get; set; }
[XmlElement]
public string ssl_exp_date { get; set; }
[XmlElement]
public string ssl_avs_address { get; set; }
[XmlElement]
public string ssl_avs_zip { get; set; }
}

My first answer was only half of the problem, you also have to remove the declaration as has been mentioned.
Here is an example:
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer cs = new XmlSerializer(typeof(Cat));
cs.Serialize(writer, new Cat { Lives = 9 }, names);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
var xml = sr.ReadToEnd();
The string xml now contains:
<cat><Lives>9</Lives></cat>

First function convert object to xml string, the second one convert object and write xml to file simultaneously.
public static string Serialize<T>(T obj)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
var writer = new StringWriter();
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
var xml = writer.ToString();
return xml;
}
public static void Serialize<T>(T obj, string filepath)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
var writer = new StreamWriter(filepath);
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
}
Actually I realized that code repeat yourself. In these methods, change only one thing which is writer object, so the code must be like below. In these way, you can easily use code just by changing writer object type.
public static string Serialize<T>(T obj)
{
var writer = new StringWriter();
Serialize<T>(obj,writer);
var xml = writer.ToString();
return xml;
}
public static void Serialize<T>(T obj, string filepath)
{
var writer = new StreamWriter(filepath);
Serialize<T>(obj,writer);
}
public static void Serialize<T>(T obj, TextWriter writer)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, obj, names);
}

Very similar to #payo's orignal answer:
If you want to remove the namespace you may also want to remove the version, to save you searching I've added that functionality so the below code will do both.
I've also wrapped it in a generic method as I'm creating very large xml files which are too large to serialize in memory so I've broken my output file down and serialize it in smaller "chunks":
public string XmlSerialize<T>(T entity) where T : class
{
// removes version
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
StringWriter sw = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
// removes namespace
var xmlns = new XmlSerializerNamespaces();
xmlns.Add(string.Empty, string.Empty);
xsSubmit.Serialize(writer, entity, xmlns);
return sw.ToString(); // Your XML
}
}

If you use XmlWriter there is a setting to omit the declaration
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.omitxmldeclaration.aspx
I'll work on an example, but that might be enough to get you going.
EDIT: Here's a sample that runs in LinqPad
string test = "test";
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream strm = new MemoryStream();
XmlWriter writer = XmlWriter.Create(strm, settings);
XmlSerializer serializer = new XmlSerializer(typeof(string));
serializer.Serialize(writer, test);
strm.Position = 0;
StreamReader reader = new StreamReader(strm);
var x = reader.ReadToEnd();
x.Dump();
writer.Close();
reader.Close();
strm.Close();
Output
<string>test</string>
Comment out line 3 and the Output is
<?xml version="1.0" encoding="utf-8"?><string>test</string>

Just to simplify the soln. of the original problem of removing UTF encoding declaration
here is the code
StringBuilder sb = new StringBuilder();
var serializer = new System.Xml.Serialization.XmlSerializer(typeToSerialize.GetType());
serializer.Serialize(System.Xml.XmlWriter.Create(sb, new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent=true }), typeToSerialize);

Related

Read xml element while deserializing c#

I have an xml document, where i serialize data dinamically, appending new data if i have a new request. The object properties i serialize are like this
[XmlRoot("LogRecords")]
public class LogRecord
{
public string Message { get; set; }
public DateTime SendTime { get; set; }
public string Sender { get; set; }
public string Recipient { get; set; }
}
Serializing is done in this way :
var stringwriter = new StringWriter();
var serializer = new XmlSerializer(object.GetType());
serializer.Serialize(stringwriter, object);
var smsxmlStr = stringwriter.ToString();
var smsRecordDoc = new XmlDocument();
smsRecordDoc.LoadXml(smsxmlStr);
var smsElement = smsRecordDoc.DocumentElement;
var smsLogFile = new XmlDocument();
smsLogFile.Load("LogRecords.xml");
var serialize = smsLogFile.CreateElement("LogRecord");
serialize.InnerXml = smsElement.InnerXml;
smsLogFile.DocumentElement.AppendChild(serialize);
smsLogFile.Save("LogRecords.xml");
While serializing i use LogFile.CreateElement("LogRecord") and my xml file looks like this :
<LogRecords>
<LogRecord>
<Message>Some messagge</Message>
<SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime>
<Sender>Sender</Sender>
<Recipient>Name</Recipient>
</LogRecord>
<LogRecord>
<Message>Some message too</Message>
<SendTime>2017-12-13T22:05:08.5720173+01:00</SendTime>
<Sender>sender</Sender>
<Recipient>name</Recipient>
</LogRecord>
</LogRecords>
When i try to deserialize like this
XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));
TextReader reader = new StreamReader("LogRecords.xml");
object obj = deserializer.Deserialize(reader);
LogRecord records = (LogRecord)obj;
reader.Close();
I get null value for each property Message, Sender Recipient and a random value for SendTime, and i know it's because it doesn't recognise the XmlElement LogRecord i added while serializing..
Is there any way to read this xml element so i can take the right property values?
Ps. Sorry if i have messed up the variables, i tried to simplify the code when i added it here and i may have mixed some variables..
Thank you in advance.
You could try to generate POCO classes from XML in Visual Studio as it's described here.
You could serialize/deserialize those POCOs using with simple util methods like:
public static T DeserializeXML<T>(string content)
{
if (content == null)
return default(T);
XmlSerializer xs = new XmlSerializer(typeof(T));
byte[] byteArray = Encoding.ASCII.GetBytes(content);
var contentStream = new MemoryStream(byteArray);
var xml = xs.Deserialize(contentStream);
return (T)xml;
}
public static string SerializeAsXML(object item)
{
if (item == null)
return null;
XmlSerializer xs = new XmlSerializer(item.GetType());
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true }))
{
xs.Serialize(writer, item);
return sw.ToString();
}
}
}
LogRecords probably should be a collection (e.g. an array in this POCO):
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Log
{
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute("LogRecords")]
[System.Xml.Serialization.XmlArrayItemAttribute("LogRecord", IsNullable = false)]
public LogRecord[] LogRecords { get; set; }
}
for the next XML format:
<Log>
<LogRecords>
<LogRecord>
<Message>Some messagge</Message>
<SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime>
<Sender>Sender</Sender>
<Recipient>Name</Recipient>
</LogRecord>
<LogRecord>
<Message>Some message too</Message>
<SendTime>2017-12-13T22:05:08.5720173+01:00</SendTime>
<Sender>sender</Sender>
<Recipient>name</Recipient>
</LogRecord>
</LogRecords>
</Log>
You manually add the root element in the xml. Therefore, you must also manually skip it when reading.
XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));
using (var xmlReader = XmlReader.Create("LogRecords.xml"))
{
// Skip root element
xmlReader.ReadToFollowing("LogRecord");
LogRecord record = (LogRecord)deserializer.Deserialize(xmlReader);
}
Remove the [XmlRoot("LogRecords")] attribute to make it work.
Of course, you will always get the first element in the xml.
As already suggested in the comments, use the list.
List<LogRecord> logRecords = new List<LogRecord>();
var logRecord = new LogRecord { ... };
// Store each new logRecord to list
logRecords.Add(logRecord);
var serializer = new XmlSerializer(typeof(List<LogRecord>));
// Serialization is done with just a couple lines of code.
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Create))
{
serializer.Serialize(fileStream, logRecords);
}
// As well as deserialization
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Open))
{
logRecords = (List<LogRecord>)serializer.Deserialize(fileStream);
}
Thus become unnecessary manipulation using XmlDocument and fuss with manually adding-skipping the root node.

Why my serialized file has the word "ArrayOf" in it [duplicate]

I am serializing List of objects List<TestObject>
, and XmlSerializer generates <ArrayOfTestObject> attribute, I want rename it or remove it.
Can it be done with creating new class that encapsulated List as field?
[XmlRoot("Container")]
public class TestObject
{
public TestObject() { }
public string Str { get; set; }
}
List<TestObject> tmpList = new List<TestObject>();
TestObject TestObj = new TestObject();
TestObj.Str = "Test";
TestObject TestObj2 = new TestObject();
TestObj2.Str = "xcvxc";
tmpList.Add(TestObj);
tmpList.Add(TestObj2);
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>));
using (XmlWriter writer = XmlWriter.Create(#"C:\test.xml", settings))
{
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(writer, tmpList, namespaces);
}
<ArrayOfTestObject>
<TestObject>
<Str>Test</Str>
</TestObject>
<TestObject>
<Str>xcvxc</Str>
</TestObject>
</ArrayOfTestObject>
The most reliable way is to declare an outermost DTO class:
[XmlRoot("myOuterElement")]
public class MyOuterMessage {
[XmlElement("item")]
public List<TestObject> Items {get;set;}
}
and serialize that (i.e. put your list into another object).
You can avoid a wrapper class, but I wouldn't:
class Program
{
static void Main()
{
XmlSerializer ser = new XmlSerializer(typeof(List<Foo>),
new XmlRootAttribute("Flibble"));
List<Foo> foos = new List<Foo> {
new Foo {Bar = "abc"},
new Foo {Bar = "def"}
};
ser.Serialize(Console.Out, foos);
}
}
public class Foo
{
public string Bar { get; set; }
}
The problem with this is that when you use custom attributes you need to be very careful to store and re-use the serializer, otherwise you get lots of dynamic assemblies loaded into memory. This is avoided if you just use the XmlSerializer(Type) constructor, as it caches this internally automatically.
Change the following line from:
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>));
To:
XmlRootAttribute root = new XmlRootAttribute("TestObjects");
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>), root);
It should work.
You can add an additional parameter to the XmlSerializer constructor to essentially name the root element.
XmlSerializer xsSubmit = new XmlSerializer(typeof(List<DropDownOption>), new XmlRootAttribute("DropDownOptions"));
This would result in the following structure:
<DropDownOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DropDownOption>
<ID>1</ID>
<Description>foo</Description>
</DropDownOption>
<DropDownOption>
<ID>2</ID>
<Description>bar</Description>
</DropDownOption>
</DropDownOptions>
Create another class like :
[XmlRoot("TestObjects")]
public class TestObjects: List<TestObject>
{
}
Then apply below code while sealizing :
XmlSerializer serializer = new XmlSerializer(typeof(TestObjects));
MemoryStream memStream = new MemoryStream();
serializer.Serialize(memStream, tmpList);

Why is the XmlWriter always outputting utf-16 encoding?

I have this extension method
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
but whenever I call this it has an encoding of utf-16 specified, ie <?xml version="1.0" encoding="utf-16"?>. What am I doing wrong?
Strings are UTF-16, so writing to a StringWriter will always use UTF-16. If that's not what you want, then use some other TextWriter derived class, with the encoding you like.
As far as I know, StringWriter class will always use UTF 16 encoding when serializing to string. You can write your own override class that accepts a different encoding:
public class StringWriterWithEncoding : StringWriter
{
private readonly Encoding _encoding;
public StringWriterWithEncoding()
{
}
public StringWriterWithEncoding(IFormatProvider formatProvider)
: base(formatProvider)
{
}
public StringWriterWithEncoding(StringBuilder sb)
: base(sb)
{
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider)
: base(sb, formatProvider)
{
}
public StringWriterWithEncoding(Encoding encoding)
{
_encoding = encoding;
}
public StringWriterWithEncoding(IFormatProvider formatProvider, Encoding encoding)
: base(formatProvider)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, Encoding encoding)
: base(sb)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
: base(sb, formatProvider)
{
_encoding = encoding;
}
public override Encoding Encoding
{
get { return (null == _encoding) ? base.Encoding : _encoding; }
}
}
So you can use this instead:
using(var stringWriter = new StringWriterWithEncoding( Encoding.UTF8))
{
...
}
as #john-saunders mentioned in his answer:
StringWriter will always use UTF-16
So i used MemoryStream for this purposes.
In my case i using windows-1251 encoding.
var xmlSstring = "";
using (var ms = new MemoryStream())
{
var encoding = Encoding.GetEncoding(1251);
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = encoding
};
using (var xmlTextWriter = XmlWriter.Create(ms, settings))
{
doc.Save(xmlTextWriter);
xmlString = encoding.GetString(ms.ToArray());
}
}
As the accepted answer says, StringWriter is UTF-16 (Unicode) by default and design. If you want to do it by getting a UTF-8 string in the end, there are 2 ways I can give you to get it done:
Solution #1 (not very efficient, bad practice, but gets the job done): Dump it to a text file and read it back in, delete the file (probably only suitable for small files, if you even want to do this at all - just wanted to show it could be done!)
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var xmlWriter = XmlWriter.Create("MyFile.xml", settings))
{
serializer.Serialize(xmlWriter, value);
}
XmlDocument xml = new XmlDocument();
xml.Load("MyFile.xml");
byte[] bytes = Encoding.UTF8.GetBytes(xml.OuterXml);
File.Delete("MyFile.xml");
return Encoding.UTF8.GetString(bytes);
}
Solution #2 (better, easier, more elegant solution!): Do it like you have it, using StringWriter, but use its Encoding property to set it to UTF-8:
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new UTF8StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
public class UTF8StringWriter : StringWriter
{
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}
You should derive a new class from StringWriter which has an overriden encoding property.
If you do not want to use a class that derives from StringWriter, then in your case, you could simply set the OmitXmlDeclaration to false and declare your own, just as I do below:
public static string Serialize<T>(this T value, string xmlDeclaration = "<?xml version=\"1.0\"?>") where T : class, new()
{
if (value == null) return string.Empty;
using (var stringWriter = new StringWriter())
{
var settings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = xmlDeclaration != null,
};
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
var xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(xmlWriter, value);
var sb = new StringBuilder($"{Environment.NewLine}{stringWriter}");
sb.Insert(0, xmlDeclaration);
return sb.ToString();
}
}

How to rename <ArrayOf> XML attribute that generated after serializing List of objects

I am serializing List of objects List<TestObject>
, and XmlSerializer generates <ArrayOfTestObject> attribute, I want rename it or remove it.
Can it be done with creating new class that encapsulated List as field?
[XmlRoot("Container")]
public class TestObject
{
public TestObject() { }
public string Str { get; set; }
}
List<TestObject> tmpList = new List<TestObject>();
TestObject TestObj = new TestObject();
TestObj.Str = "Test";
TestObject TestObj2 = new TestObject();
TestObj2.Str = "xcvxc";
tmpList.Add(TestObj);
tmpList.Add(TestObj2);
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>));
using (XmlWriter writer = XmlWriter.Create(#"C:\test.xml", settings))
{
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(writer, tmpList, namespaces);
}
<ArrayOfTestObject>
<TestObject>
<Str>Test</Str>
</TestObject>
<TestObject>
<Str>xcvxc</Str>
</TestObject>
</ArrayOfTestObject>
The most reliable way is to declare an outermost DTO class:
[XmlRoot("myOuterElement")]
public class MyOuterMessage {
[XmlElement("item")]
public List<TestObject> Items {get;set;}
}
and serialize that (i.e. put your list into another object).
You can avoid a wrapper class, but I wouldn't:
class Program
{
static void Main()
{
XmlSerializer ser = new XmlSerializer(typeof(List<Foo>),
new XmlRootAttribute("Flibble"));
List<Foo> foos = new List<Foo> {
new Foo {Bar = "abc"},
new Foo {Bar = "def"}
};
ser.Serialize(Console.Out, foos);
}
}
public class Foo
{
public string Bar { get; set; }
}
The problem with this is that when you use custom attributes you need to be very careful to store and re-use the serializer, otherwise you get lots of dynamic assemblies loaded into memory. This is avoided if you just use the XmlSerializer(Type) constructor, as it caches this internally automatically.
Change the following line from:
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>));
To:
XmlRootAttribute root = new XmlRootAttribute("TestObjects");
XmlSerializer serializer = new XmlSerializer(typeof(List<TestObject>), root);
It should work.
You can add an additional parameter to the XmlSerializer constructor to essentially name the root element.
XmlSerializer xsSubmit = new XmlSerializer(typeof(List<DropDownOption>), new XmlRootAttribute("DropDownOptions"));
This would result in the following structure:
<DropDownOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DropDownOption>
<ID>1</ID>
<Description>foo</Description>
</DropDownOption>
<DropDownOption>
<ID>2</ID>
<Description>bar</Description>
</DropDownOption>
</DropDownOptions>
Create another class like :
[XmlRoot("TestObjects")]
public class TestObjects: List<TestObject>
{
}
Then apply below code while sealizing :
XmlSerializer serializer = new XmlSerializer(typeof(TestObjects));
MemoryStream memStream = new MemoryStream();
serializer.Serialize(memStream, tmpList);

XmlSerializer and controlling namespace in XmlAnyElement

using dotnet 2.0. Code to illustrate :
Class1 c1 = new Class1();
c1.SomeInt = 5;
XmlDocument doc = new XmlDocument();
doc.LoadXml("<anode xmlns=\"xyz\" ><id>123</id></anode>");
c1.Any = new XmlElement[1];
c1.Any[0] = (XmlElement)doc.DocumentElement;
XmlSerializer ser = new XmlSerializer(typeof(Class1));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "xyz");
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter writer = XmlWriter.Create(sb, settings);
writer.WriteStartElement("root");
ser.Serialize(writer, c1, ns);
writer.WriteEndElement();
writer.Close();
string str = sb.ToString();
MessageBox.Show(str);
where Class1 is defined like :
[System.Serializable()]
[System.Xml.Serialization.XmlRoot(Namespace="xyz")]
public class Class1
{
private int someInt;
public int SomeInt
{
get { return someInt; }
set { someInt = value; }
}
private System.Xml.XmlElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
This code displays the string :
<root><Class1 xmlns="xyz"><SomeInt>5</SomeInt><anode xmlns="xyz"><id>123</id></anode></Class1></root>
This is the correct xml, but I'm wondering if this can be simplified.
What I would like is to not have the redundant xmlns="xyz" part in the "anode" element.
i.e. I would like :
<root><Class1 xmlns="xyz"><SomeInt>5</SomeInt><anode><id>123</id></anode></Class1></root>
Is this possible ?
No, I don't believe you can. You could use an aliased namespace as described in this article: Prettification of XML Serialization within Web Services.
settings.NamespaceHandling = NamespaceHandling.OmitDuplicates

Categories

Resources