How do I add a default namespace with no prefix using XMLSerializer - c#

I am trying to generate an XML document that contains the default namespace without a prefix using XmlSerializer, e.g.
<?xml version="1.0" encoding="utf-8" ?>
<MyRecord ID="9266" xmlns="http://www.website.com/MyRecord">
<List>
<SpecificItem>
Using the following code ...
string xmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(ExportMyRecord));
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
xmlnsEmpty.Add(string.Empty, string.Empty);
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, myRecord, xmlnsEmpty);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
xmlizedString = this.UTF8ByteArrayToString(memoryStream.ToArray());
and class structure ...
[Serializable]
[XmlRoot("MyRecord")]
public class ExportMyRecord
{
[XmlAttribute("ID")]
public int ID { get; set; }
Now, I've tried various options ...
XmlSerializer xs = new XmlSerializer
(typeof(ExportMyRecord),"http://www.website.com/MyRecord");
or ...
[XmlRoot(Namespace = "http://www.website.com/MyRecord", ElementName="MyRecord")]
gives me ...
<?xml version="1.0" encoding="utf-8"?>
<q1:MylRecord ID="9266" xmlns:q1="http://www.website.com/MyRecord">
<q1:List>
<q1:SpecificItem>
I need the XML to have the namespace without the prefix as it's going to a third party provider and they reject all other alternatives.

There you go:
ExportMyRecord instance = GetInstanceToSerializeFromSomewhere();
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
xmlnsEmpty.Add(string.Empty, "http://www.website.com/MyRecord");
var serializer = new XmlSerializer(
instance.GetType(),
"http://www.website.com/MyRecord"
);

Here's a generic implementation that can be used for any type:
public static void Serialize<T>(T instance, string defaultNamespace, Stream stream)
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, defaultNamespace);
var serializer = new XmlSerializer(typeof(T), defaultNamespace);
serializer.Serialize(stream, instance, namespaces);
}

Related

How to serialize an UTF 8 xml string

I had this code to create an xml. It used to work as expected, but in the first xml row, the encoding was set as utf-16.
The code was:
public static string SerializeObject<T>(this T toSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
Since I need to encode it in UTF-8, I edit it as follows:
public static string SerializeObject<T>(this T toSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = new UTF8Encoding(),
Indent = false,
OmitXmlDeclaration = false
};
using (StringWriter textWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
{
xmlSerializer.Serialize(xmlWriter, toSerialize);
}
return textWriter.ToString();
}
}
The code seems good, but the generated xml has still the row
<?xml version="1.0" encoding="utf-16"?>
and not
<?xml version="1.0" encoding="utf-8"?>
Why? How can I create an utf-8 xml?

XML Deserialization encoding issue

I already searched a lot and unable to find a solution and unable to determine the correct approach
I am serializing an object to xml string and deserializing it back to an object using c#. XML string after serialization adds a leading ?. When I dezerialize it back to the object I am getting an error There is an error in XML document (1, 1)
?<?xml version="1.0" encoding="utf-16"?>
Serialization code:
string xmlString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(T));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("abc", "http://example.com/abc/");
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream,Encoding.Unicode);
xs.Serialize(xmlTextWriter, obj, ns);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
xmlString = ConvertByteArrayToString(memoryStream.ToArray());
ConvertByteArrayToString:
UnicodeEncoding encoding = new UnicodeEncoding();
string constructedString = encoding.GetString(characters);
Deserialization Code:
XmlSerializer ser = new XmlSerializer(typeof(T));
StringReader stringReader = new StringReader(xml);
XmlTextReader xmlReader = new XmlTextReader(stringReader);
object obj = ser.Deserialize(xmlReader);
xmlReader.Close();
stringReader.Close();
return (T)obj;
I would like to know what I am doing wrong with encoding and I need a solution that works for most cases. Thanks
Use following function for serialization and Deserialization
public static string Serialize<T>(T dataToSerialize)
{
try
{
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringwriter, dataToSerialize);
return stringwriter.ToString();
}
catch
{
throw;
}
}
public static T Deserialize<T>(string xmlText)
{
try
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
catch
{
throw;
}
}
Your serialized XML contains a Unicode byte-order mark in the beginning, and this is where the deserializer fails.
To remove the BOM you need to create a different version of encoding suppressing BOM instead of using default Encoding.Unicode:
new XmlTextWriter(memoryStream, new UnicodeEncoding(false, false))
Here the second false prevents BOM being prepended to the string.

Steps to create XML using XSD and post to URL

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.

XmllSerializer.Serialize and returning raw xml

I am using an XmlSerializer to serialize an object to xml. After the object gets serialized, I end up with something like...
<?xml version="1.0" encoding="utf-8"?>
<xml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</xml>
I need to have it return simply...
<xml></xml>
Is there a way to serialize xml without the extra information? I realize strictly proper xml requires these additional elements, but I need the simpler form as I am appending these xml strings together to form a larger xml blob.
UPDATE
I was able to get the following code to work...
public static string Serialize(object o)
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Indent = true;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(String.Empty, String.Empty);
StringBuilder sb = new StringBuilder();
XmlWriter xmlw = XmlWriter.Create(sb, xws);
XmlSerializer serializer = new XmlSerializer(o.GetType());
serializer.Serialize(xmlw, o, ns);
xmlw.Flush();
return sb.ToString();
}
In C#, you can do something like this:
XmlSerializer serializer = new XmlSerializer(typeof(object));
StringWriter stringWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(stringWriter, new XmlWriterSettings() { OmitXmlDeclaration = true }))
{
serializer.Serialize(writer, this, new XmlSerializerNamespaces() { "",""});
}
string xmlText = stringWriter.ToString();
Explanation:
OmitXmlDeclaration = true makes it remove the declaration.
new XmlSerializerNamespaces() { "",""} removes the namespaces.

XmlSerializer Producing XML With No Namespace Prefix

I have to create an XML file with all the elements prefixed, like this:
<ps:Request num="123" xmlns:ps="www.ladieda.com">
<ps:ClientId>5566</ps:ClientId>
<ps:Request>
When i serialize my object, c# is smart and does this:
<Request num="123" xmlns="www.ladieda.com">
<ClientId>5566</ClientId>
<Request>
That is good, because the ps: is not necessary.
But is there a way to force C# to serialize all the prefixes?
My serialize code is this (for incoming object pObject):
String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(pObject.GetType());
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, pObject);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
private String UTF8ByteArrayToString(Byte[] characters)
{
UTF8Encoding encoding = new UTF8Encoding();
String constructedString = encoding.GetString(characters);
return (constructedString);
}
First of all, if the consumer of your string were processing XML, then they wouldn't care about the prefix, since it doesn't matter (to XML). Perhaps they don't understand XML, and think they're processing a string (which might need to have the string "ps:" on every element).
Second of all, you should change your code a bit:
XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.UTF8
};
using (XmlWriter writer = XmlWriter.Create(memoryStream, settings))
{
xs.Serialize(writer, pObject);
}
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
This will properly dispose of the stream and XmlWriter if an exception is thrown, stops using the deprecated XmlTextWriter class, and yet still returns a string containing XML written for UTF-8.
Finally, to control the prefix, see "How to: Qualify XML Element and XML Attribute Names":
XmlSerializerNamespaces myNamespaces = new XmlSerializerNamespaces();
myNamespaces.Add("ps", "www.ladieda.com");
XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.UTF8
};
using (XmlWriter writer = XmlWriter.Create(memoryStream, settings))
{
xs.Serialize(writer, pObject, myNamespaces);
}
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
Also check out XmlNamespaceDeclarationsAttribute. Caveat: when deserializing it will only give you namespaces defined by that element, it won't have namespaces defined in parent elements. If you don't have a consistent root type then use the XmlSerializer.Serialize() overload from #John Saunders.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlnamespacedeclarationsattribute.aspx
In another question #John Saunders suggests using this attribute in regards to controlling xmlns in WSDL: Namespace Prefixes in Wsdl (.net)
From MSDN Sample:
// C#
using System;
using System.IO;
using System.Xml.Serialization;
[XmlRoot("select")]
public class Select {
[XmlAttribute] public string xpath;
[XmlNamespaceDeclarations] public XmlSerializerNamespaces xmlns;
}
public class Test {
public static void Main(string[] args) {
Select mySelect = new Select();
mySelect.xpath = "myNS:ref/#common:y";
mySelect.xmlns = new XmlSerializerNamespaces();
mySelect.xmlns.Add("MyNS", "myNS.tempuri.org");
mySelect.xmlns.Add("common", "common.tempuri.org");
XmlSerializer ser = new XmlSerializer(typeof(Select));
ser.Serialize(Console.Out, mySelect);
}
}
// Output:
// <?xml version="1.0" encoding="IBM437"?>
// <select xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmln:xsi="http://www.w3.org/2001/XMLSchema-instance"
// xmlns:common="common.tempuri.org" xmlns:MyNS="myNS.tempuri.org" xpath="myNS:ref/#common:y" />

Categories