2 // System.Xml.XmlConvert
5 // Dwivedi, Ajay kumar (Adwiv@Yahoo.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Alan Tam Siu Lung (Tam@SiuLung.com)
8 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
10 // (C) 2002 Ximian, Inc (http://www.ximian.com)
14 using System.Globalization;
15 using System.Xml.Schema;
17 namespace System.Xml {
19 public class XmlConvert {
21 static string encodedColon;
22 static string [] datetimeFormats;
23 static NumberStyles floatStyle;
27 floatStyle = NumberStyles.AllowCurrencySymbol |
28 NumberStyles.AllowExponent |
29 NumberStyles.AllowDecimalPoint |
30 NumberStyles.AllowLeadingSign;
31 encodedColon = "_x003A_";
32 datetimeFormats = new string[] {
34 "yyyy-MM-ddTHH:mm:ss",
35 "yyyy-MM-ddTHH:mm:ss.f",
36 "yyyy-MM-ddTHH:mm:ss.ff",
37 "yyyy-MM-ddTHH:mm:ss.fff",
38 "yyyy-MM-ddTHH:mm:ss.ffff",
39 "yyyy-MM-ddTHH:mm:ss.fffff",
40 "yyyy-MM-ddTHH:mm:ss.ffffff",
41 "yyyy-MM-ddTHH:mm:ss.fffffff",
42 "yyyy-MM-ddTHH:mm:sszzz",
43 "yyyy-MM-ddTHH:mm:ss.fzzz",
44 "yyyy-MM-ddTHH:mm:ss.ffzzz",
45 "yyyy-MM-ddTHH:mm:ss.fffzzz",
46 "yyyy-MM-ddTHH:mm:ss.ffffzzz",
47 "yyyy-MM-ddTHH:mm:ss.fffffzzz",
48 "yyyy-MM-ddTHH:mm:ss.ffffffzzz",
49 "yyyy-MM-ddTHH:mm:ss.fffffffzzz",
50 "yyyy-MM-ddTHH:mm:ssZ",
51 "yyyy-MM-ddTHH:mm:ss.fZ",
52 "yyyy-MM-ddTHH:mm:ss.ffZ",
53 "yyyy-MM-ddTHH:mm:ss.fffZ",
54 "yyyy-MM-ddTHH:mm:ss.ffffZ",
55 "yyyy-MM-ddTHH:mm:ss.fffffZ",
56 "yyyy-MM-ddTHH:mm:ss.ffffffZ",
57 "yyyy-MM-ddTHH:mm:ss.fffffffZ",
74 "HH:mm:ss.fffffffzzz",
109 private static string TryDecoding (string s)
111 if (s == null || s.Length < 6)
116 c = (char) Int32.Parse (s.Substring (1, 4), NumberStyles.HexNumber);
118 return s [0] + DecodeName (s.Substring (1));
122 return c.ToString ();
123 return c + DecodeName (s.Substring (6));
126 public static string DecodeName (string name)
128 if (name == null || name.Length == 0)
131 int pos = name.IndexOf ('_');
132 if (pos == -1 || pos + 6 >= name.Length)
135 if (Char.ToUpper (name [pos + 1]) != 'X' || name [pos + 6] != '_')
136 return name [0] + DecodeName (name.Substring (1));
138 return name.Substring (0, pos) + TryDecoding (name.Substring (pos + 1));
141 public static string EncodeLocalName (string name)
143 string encoded = EncodeName (name);
144 int pos = encoded.IndexOf (':');
147 return encoded.Replace (":", encodedColon);
150 internal static bool IsInvalid (char c, bool firstOnlyLetter)
152 if (c == ':') // Special case. allowed in EncodeName, but encoded in EncodeLocalName
156 return !XmlChar.IsFirstNameChar (c);
158 return !XmlChar.IsNameChar (c);
161 private static string EncodeName (string name, bool nmtoken)
163 StringBuilder sb = new StringBuilder ();
164 int length = name.Length;
165 for (int i = 0; i < length; i++) {
167 if (IsInvalid (c, i == 0 && !nmtoken))
168 sb.AppendFormat ("_x{0:X4}_", (int) c);
169 else if (c == '_' && i + 6 < length && name [i+1] == 'x' && name [i + 6] == '_')
170 sb.Append ("_x005F_");
174 return sb.ToString ();
177 public static string EncodeName (string name)
179 return EncodeName (name, false);
182 public static string EncodeNmToken(string name)
184 return EncodeName (name, true);
187 // {true, false, 1, 0}
188 public static bool ToBoolean(string s)
190 s = s.Trim (XmlChar.WhitespaceChars);
202 throw new FormatException(s + " is not a valid boolean value");
206 public static byte ToByte(string s)
208 return Byte.Parse(s, CultureInfo.InvariantCulture);
211 public static char ToChar(string s)
213 return Char.Parse(s);
216 public static DateTime ToDateTime(string s)
218 return ToDateTime(s, datetimeFormats);
221 public static DateTime ToDateTime(string s, string format)
223 DateTimeFormatInfo d = new DateTimeFormatInfo();
224 d.FullDateTimePattern = format;
225 return DateTime.Parse(s, d);
228 public static DateTime ToDateTime(string s, string[] formats)
230 DateTimeStyles style = DateTimeStyles.AllowLeadingWhite |
231 DateTimeStyles.AllowTrailingWhite;
232 return DateTime.ParseExact (s, formats, DateTimeFormatInfo.InvariantInfo, style);
235 public static Decimal ToDecimal(string s)
237 return Decimal.Parse(s, CultureInfo.InvariantCulture);
240 public static double ToDouble(string s)
243 throw new ArgumentNullException();
245 return Double.PositiveInfinity;
247 return Double.NegativeInfinity;
250 return Double.Parse (s, floatStyle, CultureInfo.InvariantCulture);
253 public static Guid ToGuid(string s)
258 public static short ToInt16(string s)
260 return Int16.Parse(s, CultureInfo.InvariantCulture);
263 public static int ToInt32(string s)
265 return Int32.Parse(s, CultureInfo.InvariantCulture);
268 public static long ToInt64(string s)
270 return Int64.Parse(s, CultureInfo.InvariantCulture);
273 [CLSCompliant (false)]
274 public static SByte ToSByte(string s)
276 return SByte.Parse(s, CultureInfo.InvariantCulture);
279 public static float ToSingle(string s)
282 throw new ArgumentNullException();
284 return Single.PositiveInfinity;
286 return Single.NegativeInfinity;
289 return Single.Parse(s, floatStyle, CultureInfo.InvariantCulture);
292 public static string ToString(Guid value)
294 return value.ToString("D", CultureInfo.InvariantCulture);
297 public static string ToString(int value)
299 return value.ToString(CultureInfo.InvariantCulture);
302 public static string ToString(short value)
304 return value.ToString(CultureInfo.InvariantCulture);
307 public static string ToString(byte value)
309 return value.ToString(CultureInfo.InvariantCulture);
312 public static string ToString(long value)
314 return value.ToString(CultureInfo.InvariantCulture);
317 public static string ToString(char value)
319 return value.ToString(CultureInfo.InvariantCulture);
322 public static string ToString(bool value)
324 if (value) return "true";
328 [CLSCompliant (false)]
329 public static string ToString(SByte value)
331 return value.ToString(CultureInfo.InvariantCulture);
334 public static string ToString(Decimal value)
336 return value.ToString (CultureInfo.InvariantCulture);
339 [CLSCompliant (false)]
340 public static string ToString(UInt64 value)
342 return value.ToString(CultureInfo.InvariantCulture);
345 public static string ToString(TimeSpan value)
347 StringBuilder builder = new StringBuilder();
348 if (value.Ticks < 0) {
350 value = value.Negate();
353 if (value.Days > 0) builder.Append(value.Days).Append('D');
354 if (value.Days > 0 || value.Minutes > 0 || value.Seconds > 0 || value.Milliseconds > 0) {
356 if (value.Hours > 0) builder.Append(value.Hours).Append('D');
357 if (value.Minutes > 0) builder.Append(value.Minutes).Append('M');
358 if (value.Seconds > 0 || value.Milliseconds > 0) {
359 builder.Append(value.Seconds);
360 if (value.Milliseconds > 0) builder.Append('.').Append(String.Format("{0:000}", value.Milliseconds));
364 return builder.ToString();
367 public static string ToString(double value)
369 if (Double.IsNegativeInfinity(value)) return "-INF";
370 if (Double.IsPositiveInfinity(value)) return "INF";
371 if (Double.IsNaN(value)) return "NaN";
372 return value.ToString(CultureInfo.InvariantCulture);
375 public static string ToString(float value)
377 if (Single.IsNegativeInfinity(value)) return "-INF";
378 if (Single.IsPositiveInfinity(value)) return "INF";
379 if (Single.IsNaN(value)) return "NaN";
380 return value.ToString(CultureInfo.InvariantCulture);
383 [CLSCompliant (false)]
384 public static string ToString(UInt32 value)
386 return value.ToString(CultureInfo.InvariantCulture);
389 [CLSCompliant (false)]
390 public static string ToString(UInt16 value)
392 return value.ToString(CultureInfo.InvariantCulture);
395 public static string ToString(DateTime value)
397 return value.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
400 public static string ToString(DateTime value, string format)
402 return value.ToString(format, CultureInfo.InvariantCulture);
405 public static TimeSpan ToTimeSpan(string s)
408 throw new ArgumentException ("Invalid format string for duration schema datatype.");
413 bool minusValue = (start == 1);
415 if (s [start] != 'P')
416 throw new ArgumentException ("Invalid format string for duration schema datatype.");
429 while (i < s.Length) {
437 for (; i < s.Length; i++) {
438 if (!Char.IsDigit (s [i]))
441 int value = int.Parse (s.Substring (start, i - start));
452 days += 365 * (value / 12) + 30 * (value % 12);
454 } else if (isTime && parseStep < 6) {
470 if (!isTime || parseStep > 4)
477 if (!isTime || parseStep > 6)
492 throw new ArgumentException ("Invalid format string for duration schema datatype.");
493 TimeSpan ts = new TimeSpan (days, hours, minutes, seconds);
494 return minusValue ? -ts : ts;
497 [CLSCompliant (false)]
498 public static UInt16 ToUInt16(string s)
500 return UInt16.Parse(s, CultureInfo.InvariantCulture);
503 [CLSCompliant (false)]
504 public static UInt32 ToUInt32(string s)
506 return UInt32.Parse(s, CultureInfo.InvariantCulture);
509 [CLSCompliant (false)]
510 public static UInt64 ToUInt64(string s)
512 return UInt64.Parse(s, CultureInfo.InvariantCulture);
515 public static string VerifyName (string name)
518 throw new ArgumentNullException("name");
520 if(!XmlChar.IsName (name))
521 throw new XmlException("'" + name + "' is not a valid XML Name");
526 public static string VerifyNCName(string ncname)
529 throw new ArgumentNullException("ncname");
531 if(!XmlChar.IsNCName (ncname))
532 throw new XmlException ("'" + ncname + "' is not a valid XML NCName");
536 // It is documented as public method, but in fact it is not.
537 internal static byte [] FromBinHexString (string s)
539 char [] chars = s.ToCharArray ();
540 byte [] bytes = new byte [chars.Length / 2 + chars.Length % 2];
541 FromBinHexString (chars, 0, chars.Length, bytes);
545 internal static int FromBinHexString (char [] chars, int offset, int charLength, byte [] buffer)
547 int bufIndex = offset;
548 for (int i = 0; i < charLength - 1; i += 2) {
549 buffer [bufIndex] = (chars [i] > '9' ?
550 (byte) (chars [i] - 'A' + 10) :
551 (byte) (chars [i] - '0'));
552 buffer [bufIndex] <<= 4;
553 buffer [bufIndex] += chars [i + 1] > '9' ?
554 (byte) (chars [i + 1] - 'A' + 10) :
555 (byte) (chars [i + 1] - '0');
558 if (charLength %2 != 0)
559 buffer [bufIndex++] = (byte)
560 ((chars [charLength - 1] > '9' ?
561 (byte) (chars [charLength - 1] - 'A' + 10) :
562 (byte) (chars [charLength - 1] - '0'))
565 return bufIndex - offset;