2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.XML / System.Xml.Serialization / XmlCustomFormatter.cs
blob35bd7ef1566f2c3366c9a7b388a076bb03bc9f1f
1 //
2 // System.Xml.Serialization.XmlCustomFormatter.cs
3 //
4 // Author:
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System;
33 using System.Collections;
34 using System.Text;
35 using System.Xml;
36 using System.Globalization;
38 namespace System.Xml.Serialization {
39 internal class XmlCustomFormatter {
41 #region Methods
43 internal static string FromByteArrayBase64 (byte[] value)
45 return value == null ? String.Empty : Convert.ToBase64String(value);
48 internal static string FromByteArrayHex (byte[] value)
50 if (value == null) return null;
51 StringBuilder output = new StringBuilder ();
52 foreach (byte val in value)
53 output.Append (val.ToString ("X2", CultureInfo.InvariantCulture));
54 return output.ToString ();
57 internal static string FromChar (char value)
59 return ((int) value).ToString (CultureInfo.InvariantCulture);
62 internal static string FromDate (DateTime value)
64 return XmlConvert.ToString (value, "yyyy-MM-dd");
67 internal static string FromDateTime (DateTime value)
69 #if NET_2_0
70 return XmlConvert.ToString (value, XmlDateTimeSerializationMode.RoundtripKind);
71 #else
72 return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.fffffffzzz");
73 #endif
76 internal static string FromTime (DateTime value)
78 return XmlConvert.ToString (value, "HH:mm:ss.fffffffzzz");
81 internal static string FromEnum (long value, string[] values, long[] ids)
83 return FromEnum (value, values, ids, (string) null);
86 internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
88 StringBuilder sb = new StringBuilder();
89 int length = ids.Length;
90 long valueToProcess = value;
91 int zeroValue = -1;
93 for (int i = 0; i < length; i ++) {
94 if (ids[i] == 0) {
95 zeroValue = i;
96 } else {
97 if (valueToProcess == 0) {
98 break;
101 if ((ids[i] & value) == ids[i]) {
102 if (sb.Length != 0)
103 sb.Append (' ');
104 sb.Append (values[i]);
105 valueToProcess &= ~ids[i];
110 if (valueToProcess != 0) {
111 #if NET_2_0
112 if (typeName != null)
113 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
114 "'{0}' is not a valid value for {1}.", value, typeName));
115 else
116 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
117 "'{0}' is not a valid value.", value));
118 #else
119 return value.ToString ();
120 #endif
122 if (sb.Length == 0 && zeroValue != -1) {
123 sb.Append (values[zeroValue]);
125 return sb.ToString ();
128 internal static string FromXmlName (string name)
130 return XmlConvert.EncodeName (name);
133 internal static string FromXmlNCName (string ncName)
135 return XmlConvert.EncodeLocalName (ncName);
138 internal static string FromXmlNmToken (string nmToken)
140 return XmlConvert.EncodeNmToken (nmToken);
143 internal static string FromXmlNmTokens (string nmTokens)
145 string [] tokens = nmTokens.Split (' ');
146 for (int i=0; i<tokens.Length; i++)
147 tokens [i] = FromXmlNmToken (tokens [i]);
148 return String.Join (" ", tokens);
151 internal static byte[] ToByteArrayBase64 (string value)
153 return Convert.FromBase64String(value);
156 internal static char ToChar (string value)
158 return (char) XmlConvert.ToUInt16 (value);
161 internal static DateTime ToDate (string value)
163 return ToDateTime (value);
166 internal static DateTime ToDateTime (string value)
168 #if NET_2_0
169 return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
170 #else
171 return XmlConvert.ToDateTime (value);
172 #endif
175 internal static DateTime ToTime (string value)
177 return ToDateTime (value);
180 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
182 // Assuming that h contains map from value to Enumerated Name
184 You can try :
185 return ToEnum ("One Two", h, "SomeType");
186 where:
187 (1) no keys and values for h.
188 (2) string keys and long values.
190 according to MSDN docs (for .NET 2.0) the hashtable "consists of the
191 identifiers as keys and the constants as integral numbers"
193 long enumValue = 0;
194 string[] names = value.Split (' ');
196 foreach (string name in names) {
197 object nameValue = values[name];
198 if (nameValue != null) {
199 enumValue |= (long) nameValue;
200 } else if (validate && name.Length != 0) {
201 throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
205 return enumValue;
208 internal static string ToXmlName (string value)
210 return XmlConvert.DecodeName (value);
213 internal static string ToXmlNCName (string value)
215 return ToXmlName (value);
218 internal static string ToXmlNmToken (string value)
220 return ToXmlName (value);
223 internal static string ToXmlNmTokens (string value)
225 return ToXmlName (value);
228 internal static string ToXmlString (TypeData type, object value)
230 if (value == null) return null;
231 switch (type.XmlType)
233 case "boolean": return XmlConvert.ToString ((bool)value);
234 case "unsignedByte": return XmlConvert.ToString ((byte)value);
235 case "char": return XmlConvert.ToString ((int)(char)value);
236 #if NET_2_0
237 case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
238 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
239 case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
240 #else
241 case "dateTime": return XmlConvert.ToString ((DateTime)value);
242 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
243 case "time": return ((DateTime)value).ToString("HH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
244 #endif
245 case "decimal": return XmlConvert.ToString ((decimal)value);
246 case "double": return XmlConvert.ToString ((double)value);
247 case "short": return XmlConvert.ToString ((Int16)value);
248 case "int": return XmlConvert.ToString ((Int32)value);
249 case "long": return XmlConvert.ToString ((Int64)value);
250 case "byte": return XmlConvert.ToString ((sbyte)value);
251 case "float": return XmlConvert.ToString ((Single)value);
252 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
253 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
254 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
255 case "guid": return XmlConvert.ToString ((Guid)value);
256 case "base64":
257 case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
258 case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
259 case "duration": return (string) value;
260 default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
264 internal static object FromXmlString (TypeData type, string value)
266 if (value == null) return null;
268 switch (type.XmlType)
270 case "boolean": return XmlConvert.ToBoolean (value);
271 case "unsignedByte": return XmlConvert.ToByte (value);
272 case "char": return (char)XmlConvert.ToInt32 (value);
273 #if NET_2_0
274 case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
275 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
276 case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
277 #else
278 case "dateTime": return XmlConvert.ToDateTime (value);
279 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
280 case "time": return DateTime.ParseExact (value, "HH:mm:ss.fffffffzzz", null);
281 #endif
282 case "decimal": return XmlConvert.ToDecimal (value);
283 case "double": return XmlConvert.ToDouble (value);
284 case "short": return XmlConvert.ToInt16 (value);
285 case "int": return XmlConvert.ToInt32 (value);
286 case "long": return XmlConvert.ToInt64 (value);
287 case "byte": return XmlConvert.ToSByte (value);
288 case "float": return XmlConvert.ToSingle (value);
289 case "unsignedShort": return XmlConvert.ToUInt16 (value);
290 case "unsignedInt": return XmlConvert.ToUInt32 (value);
291 case "unsignedLong": return XmlConvert.ToUInt64 (value);
292 case "guid": return XmlConvert.ToGuid (value);
293 case "base64":
294 case "base64Binary": return Convert.FromBase64String (value);
295 case "hexBinary": return XmlConvert.FromBinHexString (value);
296 case "duration": return value;
297 default:
298 if (type.Type != null)
299 return Convert.ChangeType (value, type.Type);
300 else
301 return value;
305 internal static string GenerateToXmlString (TypeData type, string value)
307 if (type.NullableOverride)
308 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
309 else
310 return GenerateToXmlStringCore (type, value);
313 static string GenerateToXmlStringCore (TypeData type, string value)
315 if (type.NullableOverride)
316 value = value + ".Value";
317 switch (type.XmlType)
319 case "boolean": return "(" + value + "?\"true\":\"false\")";
320 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
321 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
322 #if NET_2_0
323 case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
324 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
325 case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
326 #else
327 case "dateTime": return value + ".ToString(\"yyyy-MM-ddTHH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
328 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
329 case "time": return value + ".ToString(\"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
330 #endif
331 case "decimal": return "XmlConvert.ToString (" + value + ")";
332 case "double": return "XmlConvert.ToString (" + value + ")";
333 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
334 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
335 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
336 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
337 case "float": return "XmlConvert.ToString (" + value + ")";
338 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
339 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
340 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
341 case "guid": return "XmlConvert.ToString (" + value + ")";
342 case "base64":
343 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
344 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
345 case "duration": return value;
346 case "NMTOKEN":
347 case "Name":
348 case "NCName":
349 case "language":
350 case "ENTITY":
351 case "ID":
352 case "IDREF":
353 case "NOTATION":
354 case "token":
355 case "normalizedString":
356 case "string": return value;
357 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
361 internal static string GenerateFromXmlString (TypeData type, string value)
363 if (type.NullableOverride)
364 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
365 else
366 return GenerateFromXmlStringCore (type, value);
369 static string GenerateFromXmlStringCore (TypeData type, string value)
371 switch (type.XmlType)
373 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
374 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
375 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
376 #if NET_2_0
377 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
378 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
379 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
380 #else
381 case "dateTime": return "XmlConvert.ToDateTime (" + value + ")";
382 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
383 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
384 #endif
385 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
386 case "double": return "XmlConvert.ToDouble (" + value + ")";
387 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
388 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
389 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
390 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
391 case "float": return "XmlConvert.ToSingle (" + value + ")";
392 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
393 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
394 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
395 case "guid": return "XmlConvert.ToGuid (" + value + ")";
396 case "base64:":
397 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
398 case "hexBinary": return "FromBinHexString (" + value + ")";
399 case "duration": return value;
400 default: return value;
404 #endregion // Methods