1 //------------------------------------------------------------------------------
2 // <copyright file="XmlCustomFormatter.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7 namespace System.Xml.Serialization {
11 using System.Globalization;
12 using System.ComponentModel;
13 using System.Diagnostics;
14 using System.Diagnostics.CodeAnalysis;
16 using System.Collections;
17 using System.Configuration;
18 using System.Xml.Serialization.Configuration;
21 /// The <see cref="XmlCustomFormatter"/> class provides a set of static methods for converting
22 /// primitive type values to and from their XML string representations.</summary>
23 internal class XmlCustomFormatter {
25 private static DateTimeSerializationSection.DateTimeSerializationMode mode;
27 static DateTimeSerializationSection.DateTimeSerializationMode Mode {
28 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")]
30 if (mode == DateTimeSerializationSection.DateTimeSerializationMode.Default) {
31 DateTimeSerializationSection section = PrivilegedConfigurationManager.GetSection(ConfigurationStrings.DateTimeSerializationSectionPath) as DateTimeSerializationSection;
32 if (section != null) {
36 mode = DateTimeSerializationSection.DateTimeSerializationMode.Roundtrip;
43 private XmlCustomFormatter() {}
44 internal static string FromDefaultValue(object value, string formatter) {
45 if (value == null) return null;
46 Type type = value.GetType();
47 if (type == typeof(DateTime)) {
48 if (formatter == "DateTime") {
49 return FromDateTime((DateTime)value);
51 if (formatter == "Date") {
52 return FromDate((DateTime)value);
54 if (formatter == "Time") {
55 return FromTime((DateTime)value);
58 else if (type == typeof(string)) {
59 if (formatter == "XmlName") {
60 return FromXmlName((string)value);
62 if (formatter == "XmlNCName") {
63 return FromXmlNCName((string)value);
65 if (formatter == "XmlNmToken") {
66 return FromXmlNmToken((string)value);
68 if (formatter == "XmlNmTokens") {
69 return FromXmlNmTokens((string)value);
72 throw new Exception(Res.GetString(Res.XmlUnsupportedDefaultType, type.FullName));
75 internal static string FromDate(DateTime value) {
76 return XmlConvert.ToString(value, "yyyy-MM-dd");
79 internal static string FromTime(DateTime value) {
80 if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization && value.Kind == DateTimeKind.Utc)
82 return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffZ");
86 return XmlConvert.ToString(DateTime.MinValue + value.TimeOfDay, "HH:mm:ss.fffffffzzzzzz");
90 internal static string FromDateTime(DateTime value) {
92 if (Mode == DateTimeSerializationSection.DateTimeSerializationMode.Local) {
93 return XmlConvert.ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz");
96 // for mode DateTimeSerializationMode.Roundtrip and DateTimeSerializationMode.Default
97 return XmlConvert.ToString(value, XmlDateTimeSerializationMode.RoundtripKind);
100 internal static string FromChar(char value) {
101 return XmlConvert.ToString((UInt16)value);
104 internal static string FromXmlName(string name) {
105 return XmlConvert.EncodeName(name);
108 internal static string FromXmlNCName(string ncName) {
109 return XmlConvert.EncodeLocalName(ncName);
112 internal static string FromXmlNmToken(string nmToken) {
113 return XmlConvert.EncodeNmToken(nmToken);
116 internal static string FromXmlNmTokens(string nmTokens) {
117 if (nmTokens == null)
119 if (nmTokens.IndexOf(' ') < 0)
120 return FromXmlNmToken(nmTokens);
122 string[] toks = nmTokens.Split(new char[] { ' ' });
123 StringBuilder sb = new StringBuilder();
124 for (int i = 0; i < toks.Length; i++) {
125 if (i > 0) sb.Append(' ');
126 sb.Append(FromXmlNmToken(toks[i]));
128 return sb.ToString();
132 internal static void WriteArrayBase64(XmlWriter writer, byte[] inData, int start, int count) {
133 if (inData == null || count == 0) {
136 writer.WriteBase64(inData, start, count);
139 internal static string FromByteArrayHex(byte[] value) {
142 if (value.Length == 0)
144 return XmlConvert.ToBinHexString(value);
147 internal static string FromEnum(long val, string[] vals, long[] ids, string typeName) {
149 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
150 if (ids.Length != vals.Length) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Invalid enum"));
153 long originalValue = val;
154 StringBuilder sb = new StringBuilder();
157 for (int i = 0; i < ids.Length; i++) {
165 if ((ids[i] & originalValue) == ids[i]) {
173 // failed to parse the enum value
174 throw new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, originalValue, typeName == null ? "enum" : typeName));
176 if (sb.Length == 0 && iZero >= 0) {
177 sb.Append(vals[iZero]);
179 return sb.ToString();
182 internal static object ToDefaultValue(string value, string formatter) {
183 if (formatter == "DateTime") {
184 return ToDateTime(value);
186 if (formatter == "Date") {
187 return ToDate(value);
189 if (formatter == "Time") {
190 return ToTime(value);
192 if (formatter == "XmlName") {
193 return ToXmlName(value);
195 if (formatter == "XmlNCName") {
196 return ToXmlNCName(value);
198 if (formatter == "XmlNmToken") {
199 return ToXmlNmToken(value);
201 if (formatter == "XmlNmTokens") {
202 return ToXmlNmTokens(value);
204 throw new Exception(Res.GetString(Res.XmlUnsupportedDefaultValue, formatter));
205 // Debug.WriteLineIf(CompModSwitches.XmlSerialization.TraceVerbose, "XmlSerialization::Unhandled default value " + value + " formatter " + formatter);
206 // return DBNull.Value;
209 static string[] allDateTimeFormats = new string[] {
210 "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz",
248 "HH:mm:ss.fffzzzzzz",
249 "HH:mm:ss.ffffzzzzzz",
250 "HH:mm:ss.fffffzzzzzz",
251 "HH:mm:ss.ffffffzzzzzz",
252 "HH:mm:ss.fffffffzzzzzz",
253 "yyyy-MM-ddTHH:mm:ss",
254 "yyyy-MM-ddTHH:mm:ss.f",
255 "yyyy-MM-ddTHH:mm:ss.ff",
256 "yyyy-MM-ddTHH:mm:ss.fff",
257 "yyyy-MM-ddTHH:mm:ss.ffff",
258 "yyyy-MM-ddTHH:mm:ss.fffff",
259 "yyyy-MM-ddTHH:mm:ss.ffffff",
260 "yyyy-MM-ddTHH:mm:ss.fffffff",
261 "yyyy-MM-ddTHH:mm:ssZ",
262 "yyyy-MM-ddTHH:mm:ss.fZ",
263 "yyyy-MM-ddTHH:mm:ss.ffZ",
264 "yyyy-MM-ddTHH:mm:ss.fffZ",
265 "yyyy-MM-ddTHH:mm:ss.ffffZ",
266 "yyyy-MM-ddTHH:mm:ss.fffffZ",
267 "yyyy-MM-ddTHH:mm:ss.ffffffZ",
268 "yyyy-MM-ddTHH:mm:ss.fffffffZ",
269 "yyyy-MM-ddTHH:mm:sszzzzzz",
270 "yyyy-MM-ddTHH:mm:ss.fzzzzzz",
271 "yyyy-MM-ddTHH:mm:ss.ffzzzzzz",
272 "yyyy-MM-ddTHH:mm:ss.fffzzzzzz",
273 "yyyy-MM-ddTHH:mm:ss.ffffzzzzzz",
274 "yyyy-MM-ddTHH:mm:ss.fffffzzzzzz",
275 "yyyy-MM-ddTHH:mm:ss.ffffffzzzzzz",
278 static string[] allDateFormats = new string[] {
298 static string[] allTimeFormats = new string[] {
299 "HH:mm:ss.fffffffzzzzzz",
319 "HH:mm:ss.fffzzzzzz",
320 "HH:mm:ss.ffffzzzzzz",
321 "HH:mm:ss.fffffzzzzzz",
322 "HH:mm:ss.ffffffzzzzzz",
325 internal static DateTime ToDateTime(string value) {
326 #if CONFIGURATION_DEP
327 if (Mode == DateTimeSerializationSection.DateTimeSerializationMode.Local) {
328 return ToDateTime(value, allDateTimeFormats);
333 // for mode DateTimeSerializationMode.Roundtrip and DateTimeSerializationMode.Default
334 return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind);
338 internal static DateTime ToDateTime(string value, string[] formats) {
339 return XmlConvert.ToDateTime(value, formats);
342 internal static DateTime ToDate(string value) {
343 return ToDateTime(value, allDateFormats);
346 internal static DateTime ToTime(string value) {
347 if (!LocalAppContextSwitches.IgnoreKindInUtcTimeSerialization)
349 return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.RoundtripKind);
353 return DateTime.ParseExact(value, allTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite | DateTimeStyles.NoCurrentDateDefault);
357 internal static char ToChar(string value) {
358 return (char)XmlConvert.ToUInt16(value);
361 internal static string ToXmlName(string value) {
362 return XmlConvert.DecodeName(CollapseWhitespace(value));
365 internal static string ToXmlNCName(string value) {
366 return XmlConvert.DecodeName(CollapseWhitespace(value));
369 internal static string ToXmlNmToken(string value) {
370 return XmlConvert.DecodeName(CollapseWhitespace(value));
373 internal static string ToXmlNmTokens(string value) {
374 return XmlConvert.DecodeName(CollapseWhitespace(value));
377 internal static byte[] ToByteArrayBase64(string value) {
378 if (value == null) return null;
379 value = value.Trim();
380 if (value.Length == 0)
382 return Convert.FromBase64String(value);
384 internal static byte[] ToByteArrayHex(string value) {
385 if (value == null) return null;
386 value = value.Trim();
387 return XmlConvert.FromBinHexString(value);
390 internal static long ToEnum(string val, Hashtable vals, string typeName, bool validate) {
392 string[] parts = val.Split(null);
393 for (int i = 0; i < parts.Length; i++) {
394 object id = vals[parts[i]];
397 else if (validate && parts[i].Length > 0)
398 throw new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, parts[i], typeName));
403 static string CollapseWhitespace(string value) {