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)
70 return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.FFFFFFF");
72 return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.fffffffzzz");
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;
93 for (int i = 0; i < length; i ++) {
97 if (valueToProcess == 0) {
101 if ((ids[i] & value) == ids[i]) {
104 sb.Append (values[i]);
105 valueToProcess &= ~ids[i];
110 if (valueToProcess != 0) {
112 if (typeName != null)
113 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
114 "'{0}' is not a valid value for {1}.", value, typeName));
116 throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
117 "'{0}' is not a valid value.", value));
119 return value.ToString ();
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 return XmlConvert.ToDateTime (value);
171 internal static DateTime ToTime (string value)
173 return ToDateTime (value);
176 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
178 // Assuming that h contains map from value to Enumerated Name
181 return ToEnum ("One Two", h, "SomeType");
183 (1) no keys and values for h.
184 (2) string keys and long values.
186 according to MSDN docs (for .NET 2.0) the hashtable "consists of the
187 identifiers as keys and the constants as integral numbers"
190 string[] names = value.Split (' ');
192 foreach (string name in names) {
193 object nameValue = values[name];
194 if (nameValue != null) {
195 enumValue |= (long) nameValue;
196 } else if (validate && name.Length != 0) {
197 throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
204 internal static string ToXmlName (string value)
206 return XmlConvert.DecodeName (value);
209 internal static string ToXmlNCName (string value)
211 return ToXmlName (value);
214 internal static string ToXmlNmToken (string value)
216 return ToXmlName (value);
219 internal static string ToXmlNmTokens (string value)
221 return ToXmlName (value);
224 internal static string ToXmlString (TypeData type, object value)
226 if (value == null) return null;
227 switch (type.XmlType)
229 case "boolean": return XmlConvert.ToString ((bool)value);
230 case "unsignedByte": return XmlConvert.ToString ((byte)value);
231 case "char": return XmlConvert.ToString ((int)(char)value);
233 case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.Unspecified);
234 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
235 case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
237 case "dateTime": return XmlConvert.ToString ((DateTime)value);
238 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
239 case "time": return ((DateTime)value).ToString("HH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
241 case "decimal": return XmlConvert.ToString ((decimal)value);
242 case "double": return XmlConvert.ToString ((double)value);
243 case "short": return XmlConvert.ToString ((Int16)value);
244 case "int": return XmlConvert.ToString ((Int32)value);
245 case "long": return XmlConvert.ToString ((Int64)value);
246 case "byte": return XmlConvert.ToString ((sbyte)value);
247 case "float": return XmlConvert.ToString ((Single)value);
248 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
249 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
250 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
251 case "guid": return XmlConvert.ToString ((Guid)value);
253 case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
254 case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
255 case "duration": return XmlConvert.ToString ((TimeSpan) value);
256 default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
260 internal static object FromXmlString (TypeData type, string value)
262 if (value == null) return null;
264 switch (type.XmlType)
266 case "boolean": return XmlConvert.ToBoolean (value);
267 case "unsignedByte": return XmlConvert.ToByte (value);
268 case "char": return (char)XmlConvert.ToInt32 (value);
269 case "dateTime": return XmlConvert.ToDateTime (value);
270 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
272 case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
274 case "time": return DateTime.ParseExact (value, "HH:mm:ss.fffffffzzz", null);
276 case "decimal": return XmlConvert.ToDecimal (value);
277 case "double": return XmlConvert.ToDouble (value);
278 case "short": return XmlConvert.ToInt16 (value);
279 case "int": return XmlConvert.ToInt32 (value);
280 case "long": return XmlConvert.ToInt64 (value);
281 case "byte": return XmlConvert.ToSByte (value);
282 case "float": return XmlConvert.ToSingle (value);
283 case "unsignedShort": return XmlConvert.ToUInt16 (value);
284 case "unsignedInt": return XmlConvert.ToUInt32 (value);
285 case "unsignedLong": return XmlConvert.ToUInt64 (value);
286 case "guid": return XmlConvert.ToGuid (value);
288 case "base64Binary": return Convert.FromBase64String (value);
289 case "hexBinary": return XmlConvert.FromBinHexString (value);
290 case "duration": return XmlConvert.ToTimeSpan (value);
292 if (type.Type != null)
293 return Convert.ChangeType (value, type.Type);
299 internal static string GenerateToXmlString (TypeData type, string value)
301 if (type.NullableOverride)
302 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
304 return GenerateToXmlStringCore (type, value);
307 static string GenerateToXmlStringCore (TypeData type, string value)
309 if (type.NullableOverride)
310 value = value + ".Value";
311 switch (type.XmlType)
313 case "boolean": return "(" + value + "?\"true\":\"false\")";
314 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
315 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
316 case "dateTime": return value + ".ToString(\"yyyy-MM-ddTHH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
317 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
318 case "time": return value + ".ToString(\"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
319 case "decimal": return "XmlConvert.ToString (" + value + ")";
320 case "double": return "XmlConvert.ToString (" + value + ")";
321 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
322 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
323 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
324 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
325 case "float": return "XmlConvert.ToString (" + value + ")";
326 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
327 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
328 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
329 case "guid": return "XmlConvert.ToString (" + value + ")";
331 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
332 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
333 case "duration": return "XmlConvert.ToString (" + value + ")";
343 case "normalizedString":
344 case "string": return value;
345 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
349 internal static string GenerateFromXmlString (TypeData type, string value)
351 if (type.NullableOverride)
352 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
354 return GenerateFromXmlStringCore (type, value);
357 static string GenerateFromXmlStringCore (TypeData type, string value)
359 switch (type.XmlType)
361 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
362 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
363 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
365 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.Unspecified)";
366 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
367 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
369 case "dateTime": return "XmlConvert.ToDateTime (" + value + ")";
370 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
371 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
373 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
374 case "double": return "XmlConvert.ToDouble (" + value + ")";
375 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
376 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
377 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
378 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
379 case "float": return "XmlConvert.ToSingle (" + value + ")";
380 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
381 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
382 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
383 case "guid": return "XmlConvert.ToGuid (" + value + ")";
385 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
386 case "hexBinary": return "FromBinHexString (" + value + ")";
387 case "duration": return "XmlConvert.ToTimeSpan (" + value + ")";
388 default: return value;
392 #endregion // Methods