Reputation: 4183
I am deserializing a xml-configuration file using the following code:
// Create object by deserializing the given xml document
var serializer = new XmlSerializer(typeof(ConfigurationFile));
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var configFile = serializer.Deserialize(stream);
In the configuration I have some floating numbers defined as following:
DailyThreshold="41.9"
As the decimal separator "." is culture dependent I am wondering how I can define the culture the serializer uses to parse these numbers?
Upvotes: 6
Views: 7556
Reputation: 152
I had a case where I needed to deserialize an xml node and the input xml had number values with both comma and dot as the decimal separator for some reason. Also for the boolean the values were both with upper and lower case for the initial letter. The xml file was created by an application and then updated by another, but when updating it was updating only specific nodes, not checking the culture of the entire document.
To get it to work I looped through each node's attributes and made sure the value is in invariant culture. Also for each child node recursively. If the datatype of the attribute is specified, the value can be changed accordingly. Instead of always changing "True" into "true", to change it ony when datatype is boolean for example. In my case the type was not specified.
public static readonly Regex CommaNumber = new Regex("^[-+]?(\\d+\\,?\\d+)$");
public static string ToInvariantCulture(this string value, string dataType = null)
{
var invariantValue = value;
if(dataType == "decimal" || string.IsNullOrWhiteSpace(dataType))
{
var isCommaNumber = CommaNumber.IsMatch(value);
if (isCommaNumber && double.TryParse(value, out double number))
{
invariantValue = number.ToString(CultureInfo.InvariantCulture);
}
}
if(dataType == "boolean" || string.IsNullOrWhiteSpace(dataType))
{
if (value == "True")
{
invariantValue = "true";
}
if (value == "False")
{
invariantValue = "false";
}
}
return invariantValue;
}
public static XmlNode ToInvariantCulture(this XmlNode node)
{
node.Attributes.Cast<XmlAttribute>().ForEach(attribute => attribute.Value = attribute.Value?.ToInvariantCulture());
node.ChildNodes.Cast<XmlNode>().ForEach(childNode => childNode.ToInvariantCulture());
return node;
}
Upvotes: 0
Reputation: 114
XmlSerializer class use the format configuration of your OS, it is configured in region section, in order your program uses a specific format, you could assign directly to the Thread, somenthing like below. For example if you live in a country of Latinoamerica is pretty common to use , insted of . that it is the standar representation.
//Write this code at the begining of the program
CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
culture.NumberFormat.NumberDecimalSeparator = "."; //Force use . insted of ,
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
Upvotes: 1
Reputation: 39025
If you use XmlSerializer
for both serializing and deserializing you have no reason to worry about culture: the serializer doesn't care about culture, neither it changes the serialized data in any way.
The data is alwasy serialized with the same format, which has nothing to do with any culture settings (nor UI culture, nor thread culture, nor any kind of culture).
I wrote this without looking for evidences simply because XML is a format for exchanging data between different systems and platforms, so the serialization format and deserialization parse must be equal in all the systems.
However, if you dive into MSDN docs, you can read this:
The majority of the methods found in an XmlConvert class are used to convert data between strings and strongly-typed formats. Methods are locale independent. This means that they do not take into account any locale settings when doing conversion.
on Conversion of XML Data Types.
Upvotes: 5