2 // System.Xml.Serialization.XmlCustomFormatter.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
8 // Copyright (C) Tim Coleman, 2002
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
33 using System.Collections;
36 using System.Globalization;
38 namespace System.Xml.Serialization {
39 internal class XmlCustomFormatter {
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 return XmlConvert.ToString (value, XmlDateTimeSerializationMode.RoundtripKind);
72 internal static string FromTime (DateTime value)
74 return XmlConvert.ToString (value, "HH:mm:ss.fffffffzzz");
77 internal static string FromEnum (long value, string[] values, long[] ids)
79 return FromEnum (value, values, ids, (string) null);
82 internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
84 StringBuilder sb = new StringBuilder();
85 int length = ids.Length;
86 long valueToProcess = value;
89 for (int i = 0; i < length; i ++) {
93 if (valueToProcess == 0) {
97 if ((ids[i] & value) == ids[i]) {
100 sb.Append (values[i]);
101 valueToProcess &= ~ids[i];
106 if (valueToProcess != 0) {
107 if (typeName != null)
108 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
109 "'{0}' is not a valid value for {1}.", value, typeName));
111 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
112 "'{0}' is not a valid value.", value));
114 if (sb.Length == 0 && zeroValue != -1) {
115 sb.Append (values[zeroValue]);
117 return sb.ToString ();
120 internal static string FromXmlName (string name)
122 return XmlConvert.EncodeName (name);
125 internal static string FromXmlNCName (string ncName)
127 return XmlConvert.EncodeLocalName (ncName);
130 internal static string FromXmlNmToken (string nmToken)
132 return XmlConvert.EncodeNmToken (nmToken);
135 internal static string FromXmlNmTokens (string nmTokens)
137 string [] tokens = nmTokens.Split (' ');
138 for (int i=0; i<tokens.Length; i++)
139 tokens [i] = FromXmlNmToken (tokens [i]);
140 return String.Join (" ", tokens);
143 internal static byte[] ToByteArrayBase64 (string value)
145 return Convert.FromBase64String(value);
148 internal static char ToChar (string value)
150 return (char) XmlConvert.ToUInt16 (value);
153 internal static DateTime ToDate (string value)
155 return ToDateTime (value);
158 internal static DateTime ToDateTime (string value)
160 return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
163 internal static DateTime ToTime (string value)
165 return ToDateTime (value);
168 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
170 // Assuming that h contains map from value to Enumerated Name
173 return ToEnum ("One Two", h, "SomeType");
175 (1) no keys and values for h.
176 (2) string keys and long values.
178 according to MSDN docs (for .NET 2.0) the hashtable "consists of the
179 identifiers as keys and the constants as integral numbers"
182 string[] names = value.Split (' ');
184 foreach (string name in names) {
185 object nameValue = values[name];
186 if (nameValue != null) {
187 enumValue |= (long) nameValue;
188 } else if (validate && name.Length != 0) {
189 throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
196 internal static string ToXmlName (string value)
198 return XmlConvert.DecodeName (value);
201 internal static string ToXmlNCName (string value)
203 return ToXmlName (value);
206 internal static string ToXmlNmToken (string value)
208 return ToXmlName (value);
211 internal static string ToXmlNmTokens (string value)
213 return ToXmlName (value);
216 internal static string ToXmlString (TypeData type, object value)
218 if (value == null) return null;
219 switch (type.XmlType)
221 case "boolean": return XmlConvert.ToString ((bool)value);
222 case "unsignedByte": return XmlConvert.ToString ((byte)value);
223 case "char": return XmlConvert.ToString ((int)(char)value);
224 case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
225 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
226 case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
227 case "decimal": return XmlConvert.ToString ((decimal)value);
228 case "double": return XmlConvert.ToString ((double)value);
229 case "short": return XmlConvert.ToString ((Int16)value);
230 case "int": return XmlConvert.ToString ((Int32)value);
231 case "long": return XmlConvert.ToString ((Int64)value);
232 case "byte": return XmlConvert.ToString ((sbyte)value);
233 case "float": return XmlConvert.ToString ((Single)value);
234 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
235 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
236 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
237 case "guid": return XmlConvert.ToString ((Guid)value);
239 case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
240 case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
241 case "duration": return (string) value;
242 default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
246 static string[] allTimeFormats = new string[] {
247 "HH:mm:ss.fffffffzzzzzz",
267 "HH:mm:ss.fffzzzzzz",
268 "HH:mm:ss.ffffzzzzzz",
269 "HH:mm:ss.fffffzzzzzz",
270 "HH:mm:ss.ffffffzzzzzz",
273 internal static object FromXmlString (TypeData type, string value)
275 if (value == null) return null;
277 switch (type.XmlType)
279 case "boolean": return XmlConvert.ToBoolean (value);
280 case "unsignedByte": return XmlConvert.ToByte (value);
281 case "char": return (char)XmlConvert.ToInt32 (value);
282 case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
283 case "date": return XmlConvert.ToDateTime (value).Date;
284 case "time": return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind);
285 case "decimal": return XmlConvert.ToDecimal (value);
286 case "double": return XmlConvert.ToDouble (value);
287 case "short": return XmlConvert.ToInt16 (value);
288 case "int": return XmlConvert.ToInt32 (value);
289 case "long": return XmlConvert.ToInt64 (value);
290 case "byte": return XmlConvert.ToSByte (value);
291 case "float": return XmlConvert.ToSingle (value);
292 case "unsignedShort": return XmlConvert.ToUInt16 (value);
293 case "unsignedInt": return XmlConvert.ToUInt32 (value);
294 case "unsignedLong": return XmlConvert.ToUInt64 (value);
295 case "guid": return XmlConvert.ToGuid (value);
297 case "base64Binary": return Convert.FromBase64String (value);
298 case "hexBinary": return XmlConvert.FromBinHexString (value);
299 case "duration": return value;
301 if (type.Type != null)
302 return Convert.ChangeType (value, type.Type, null);
308 internal static string GenerateToXmlString (TypeData type, string value)
310 if (type.NullableOverride)
311 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
313 return GenerateToXmlStringCore (type, value);
316 static string GenerateToXmlStringCore (TypeData type, string value)
318 if (type.NullableOverride)
319 value = value + ".Value";
320 switch (type.XmlType)
322 case "boolean": return "(" + value + "?\"true\":\"false\")";
323 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
324 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
325 case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
326 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
327 case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
328 case "decimal": return "XmlConvert.ToString (" + value + ")";
329 case "double": return "XmlConvert.ToString (" + value + ")";
330 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
331 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
332 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
333 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
334 case "float": return "XmlConvert.ToString (" + value + ")";
335 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
336 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
337 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
338 case "guid": return "XmlConvert.ToString (" + value + ")";
340 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
341 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
342 case "duration": return value;
352 case "normalizedString":
353 case "string": return value;
354 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
358 internal static string GenerateFromXmlString (TypeData type, string value)
360 if (type.NullableOverride)
361 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
363 return GenerateFromXmlStringCore (type, value);
366 static string GenerateFromXmlStringCore (TypeData type, string value)
368 switch (type.XmlType)
370 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
371 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
372 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
373 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
374 case "date": return "XmlConvert.ToDateTime (" + value + ").Date";
375 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
376 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
377 case "double": return "XmlConvert.ToDouble (" + value + ")";
378 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
379 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
380 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
381 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
382 case "float": return "XmlConvert.ToSingle (" + value + ")";
383 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
384 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
385 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
386 case "guid": return "XmlConvert.ToGuid (" + value + ")";
388 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
389 case "hexBinary": return "FromBinHexString (" + value + ")";
390 case "duration": return value;
391 default: return value;
395 #endregion // Methods