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 internal static object FromXmlString (TypeData type, string value)
248 if (value == null) return null;
250 switch (type.XmlType)
252 case "boolean": return XmlConvert.ToBoolean (value);
253 case "unsignedByte": return XmlConvert.ToByte (value);
254 case "char": return (char)XmlConvert.ToInt32 (value);
255 case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
256 case "date": return XmlConvert.ToDateTime (value).Date;
257 case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
258 case "decimal": return XmlConvert.ToDecimal (value);
259 case "double": return XmlConvert.ToDouble (value);
260 case "short": return XmlConvert.ToInt16 (value);
261 case "int": return XmlConvert.ToInt32 (value);
262 case "long": return XmlConvert.ToInt64 (value);
263 case "byte": return XmlConvert.ToSByte (value);
264 case "float": return XmlConvert.ToSingle (value);
265 case "unsignedShort": return XmlConvert.ToUInt16 (value);
266 case "unsignedInt": return XmlConvert.ToUInt32 (value);
267 case "unsignedLong": return XmlConvert.ToUInt64 (value);
268 case "guid": return XmlConvert.ToGuid (value);
270 case "base64Binary": return Convert.FromBase64String (value);
271 case "hexBinary": return XmlConvert.FromBinHexString (value);
272 case "duration": return value;
274 if (type.Type != null)
275 return Convert.ChangeType (value, type.Type, null);
281 internal static string GenerateToXmlString (TypeData type, string value)
283 if (type.NullableOverride)
284 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
286 return GenerateToXmlStringCore (type, value);
289 static string GenerateToXmlStringCore (TypeData type, string value)
291 if (type.NullableOverride)
292 value = value + ".Value";
293 switch (type.XmlType)
295 case "boolean": return "(" + value + "?\"true\":\"false\")";
296 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
297 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
298 case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
299 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
300 case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
301 case "decimal": return "XmlConvert.ToString (" + value + ")";
302 case "double": return "XmlConvert.ToString (" + value + ")";
303 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
304 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
305 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
306 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
307 case "float": return "XmlConvert.ToString (" + value + ")";
308 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
309 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
310 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
311 case "guid": return "XmlConvert.ToString (" + value + ")";
313 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
314 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
315 case "duration": return value;
325 case "normalizedString":
326 case "string": return value;
327 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
331 internal static string GenerateFromXmlString (TypeData type, string value)
333 if (type.NullableOverride)
334 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
336 return GenerateFromXmlStringCore (type, value);
339 static string GenerateFromXmlStringCore (TypeData type, string value)
341 switch (type.XmlType)
343 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
344 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
345 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
346 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
347 case "date": return "XmlConvert.ToDateTime (" + value + ").Date";
348 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
349 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
350 case "double": return "XmlConvert.ToDouble (" + value + ")";
351 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
352 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
353 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
354 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
355 case "float": return "XmlConvert.ToSingle (" + value + ")";
356 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
357 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
358 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
359 case "guid": return "XmlConvert.ToGuid (" + value + ")";
361 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
362 case "hexBinary": return "FromBinHexString (" + value + ")";
363 case "duration": return value;
364 default: return value;
368 #endregion // Methods