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.h-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;
26 encodedColon = "_x003A_";
27 datetimeFormats = new string[] {
29 "yyyy-MM-ddTHH:mm:ss",
30 "yyyy-MM-ddTHH:mm:ss.f",
31 "yyyy-MM-ddTHH:mm:ss.ff",
32 "yyyy-MM-ddTHH:mm:ss.fff",
33 "yyyy-MM-ddTHH:mm:ss.ffff",
34 "yyyy-MM-ddTHH:mm:ss.fffff",
35 "yyyy-MM-ddTHH:mm:ss.ffffff",
36 "yyyy-MM-ddTHH:mm:ss.fffffff",
37 "yyyy-MM-ddTHH:mm:sszzz",
38 "yyyy-MM-ddTHH:mm:ss.fzzz",
39 "yyyy-MM-ddTHH:mm:ss.ffzzz",
40 "yyyy-MM-ddTHH:mm:ss.fffzzz",
41 "yyyy-MM-ddTHH:mm:ss.ffffzzz",
42 "yyyy-MM-ddTHH:mm:ss.fffffzzz",
43 "yyyy-MM-ddTHH:mm:ss.ffffffzzz",
44 "yyyy-MM-ddTHH:mm:ss.fffffffzzz",
45 "yyyy-MM-ddTHH:mm:ssZ",
46 "yyyy-MM-ddTHH:mm:ss.fZ",
47 "yyyy-MM-ddTHH:mm:ss.ffZ",
48 "yyyy-MM-ddTHH:mm:ss.fffZ",
49 "yyyy-MM-ddTHH:mm:ss.ffffZ",
50 "yyyy-MM-ddTHH:mm:ss.fffffZ",
51 "yyyy-MM-ddTHH:mm:ss.ffffffZ",
52 "yyyy-MM-ddTHH:mm:ss.fffffffZ",
69 "HH:mm:ss.fffffffzzz",
104 private static string TryDecoding (string s)
106 if (s == null || s.Length < 6)
111 c = (char) Int32.Parse (s.Substring (1, 4), NumberStyles.HexNumber);
113 return s [0] + DecodeName (s.Substring (1));
117 return c.ToString ();
118 return c + DecodeName (s.Substring (6));
121 public static string DecodeName (string name)
123 if (name == null || name.Length == 0)
126 int pos = name.IndexOf ('_');
127 if (pos == -1 || pos + 6 >= name.Length)
130 if (Char.ToUpper (name [pos + 1]) != 'X' || name [pos + 6] != '_')
131 return name [0] + DecodeName (name.Substring (1));
133 return name.Substring (0, pos) + TryDecoding (name.Substring (pos + 1));
136 public static string EncodeLocalName (string name)
138 string encoded = EncodeName (name);
139 int pos = encoded.IndexOf (':');
142 return encoded.Replace (":", encodedColon);
145 internal static bool IsInvalid (char c, bool firstOnlyLetter)
147 if (c == ':') // Special case. allowed in EncodeName, but encoded in EncodeLocalName
151 return !XmlChar.IsFirstNameChar (c);
153 return !XmlChar.IsNameChar (c);
156 private static string EncodeName (string name, bool nmtoken)
158 StringBuilder sb = new StringBuilder ();
159 int length = name.Length;
160 for (int i = 0; i < length; i++) {
162 if (IsInvalid (c, i == 0 && !nmtoken))
163 sb.AppendFormat ("_x{0:X4}_", (int) c);
164 else if (c == '_' && i + 6 < length && name [i+1] == 'x' && name [i + 6] == '_')
165 sb.Append ("_x005F_");
169 return sb.ToString ();
172 public static string EncodeName (string name)
174 return EncodeName (name, false);
177 public static string EncodeNmToken(string name)
179 return EncodeName (name, true);
182 // {true, false, 1, 0}
183 public static bool ToBoolean(string s)
185 s = s.Trim (XmlChar.WhitespaceChars);
197 throw new FormatException(s + " is not a valid boolean value");
201 public static byte ToByte(string s)
203 return Byte.Parse(s, CultureInfo.InvariantCulture);
206 public static char ToChar(string s)
208 return Char.Parse(s);
211 public static DateTime ToDateTime(string s)
213 return ToDateTime(s, datetimeFormats);
216 public static DateTime ToDateTime(string s, string format)
218 DateTimeFormatInfo d = new DateTimeFormatInfo();
219 d.FullDateTimePattern = format;
220 return DateTime.Parse(s, d);
223 public static DateTime ToDateTime(string s, string[] formats)
225 DateTimeStyles style = DateTimeStyles.AllowLeadingWhite |
226 DateTimeStyles.AllowTrailingWhite;
227 return DateTime.ParseExact (s, formats, DateTimeFormatInfo.InvariantInfo, style);
230 public static Decimal ToDecimal(string s)
232 return Decimal.Parse(s, NumberFormatInfo.InvariantInfo);
235 public static double ToDouble(string s)
237 if (s == "INF") return System.Double.PositiveInfinity;
238 if (s == "-INF") return System.Double.NegativeInfinity;
239 if (s == "NaN") return System.Double.NaN;
240 return Double.Parse(s, CultureInfo.InvariantCulture);
243 public static Guid ToGuid(string s)
248 public static short ToInt16(string s)
250 return Int16.Parse(s, CultureInfo.InvariantCulture);
253 public static int ToInt32(string s)
255 return Int32.Parse(s, CultureInfo.InvariantCulture);
258 public static long ToInt64(string s)
260 return Int64.Parse(s, CultureInfo.InvariantCulture);
263 [CLSCompliant (false)]
264 public static SByte ToSByte(string s)
266 return SByte.Parse(s, CultureInfo.InvariantCulture);
269 public static float ToSingle(string s)
271 if (s == "INF") return System.Single.PositiveInfinity;
272 if (s == "-INF") return System.Single.NegativeInfinity;
273 if (s == "NaN") return System.Single.NaN;
274 return Single.Parse(s, CultureInfo.InvariantCulture);
277 public static string ToString(Guid value)
279 return value.ToString("D",CultureInfo.InvariantCulture);
282 public static string ToString(int value)
284 return value.ToString(CultureInfo.InvariantCulture);
287 public static string ToString(short value)
289 return value.ToString(CultureInfo.InvariantCulture);
292 public static string ToString(byte value)
294 return value.ToString(CultureInfo.InvariantCulture);
297 public static string ToString(long value)
299 return value.ToString(CultureInfo.InvariantCulture);
302 public static string ToString(char value)
304 return value.ToString(CultureInfo.InvariantCulture);
307 public static string ToString(bool value)
309 if (value) return "true";
313 [CLSCompliant (false)]
314 public static string ToString(SByte value)
316 return value.ToString(CultureInfo.InvariantCulture);
319 public static string ToString(Decimal value)
321 return value.ToString(CultureInfo.InvariantCulture);
324 [CLSCompliant (false)]
325 public static string ToString(UInt64 value)
327 return value.ToString(CultureInfo.InvariantCulture);
330 public static string ToString(TimeSpan value)
332 StringBuilder builder = new StringBuilder();
333 if (value.Ticks < 0) {
335 value = value.Negate();
338 if (value.Days > 0) builder.Append(value.Days).Append('D');
339 if (value.Days > 0 || value.Minutes > 0 || value.Seconds > 0 || value.Milliseconds > 0) {
341 if (value.Hours > 0) builder.Append(value.Hours).Append('D');
342 if (value.Minutes > 0) builder.Append(value.Minutes).Append('M');
343 if (value.Seconds > 0 || value.Milliseconds > 0) {
344 builder.Append(value.Seconds);
345 if (value.Milliseconds > 0) builder.Append('.').Append(String.Format("{0:000}", value.Milliseconds));
349 return builder.ToString();
352 public static string ToString(double value)
354 if (Double.IsNegativeInfinity(value)) return "-INF";
355 if (Double.IsPositiveInfinity(value)) return "INF";
356 if (Double.IsNaN(value)) return "NaN";
357 return value.ToString(CultureInfo.InvariantCulture);
360 public static string ToString(float value)
362 if (Single.IsNegativeInfinity(value)) return "-INF";
363 if (Single.IsPositiveInfinity(value)) return "INF";
364 if (Single.IsNaN(value)) return "NaN";
365 return value.ToString(CultureInfo.InvariantCulture);
368 [CLSCompliant (false)]
369 public static string ToString(UInt32 value)
371 return value.ToString(CultureInfo.InvariantCulture);
374 [CLSCompliant (false)]
375 public static string ToString(UInt16 value)
377 return value.ToString(CultureInfo.InvariantCulture);
380 public static string ToString(DateTime value)
382 return value.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
385 public static string ToString(DateTime value, string format)
387 return value.ToString(format, CultureInfo.InvariantCulture);
390 public static TimeSpan ToTimeSpan(string s)
393 throw new ArgumentException ("Invalid format string for duration schema datatype.");
398 bool minusValue = (start == 1);
400 if (s [start] != 'P')
401 throw new ArgumentException ("Invalid format string for duration schema datatype.");
414 while (i < s.Length) {
422 for (; i < s.Length; i++) {
423 if (!Char.IsDigit (s [i]))
426 int value = int.Parse (s.Substring (start, i - start));
437 days += 365 * (value / 12) + 30 * (value % 12);
439 } else if (isTime && parseStep < 6) {
455 if (!isTime || parseStep > 4)
462 if (!isTime || parseStep > 6)
477 throw new ArgumentException ("Invalid format string for duration schema datatype.");
478 TimeSpan ts = new TimeSpan (days, hours, minutes, seconds);
479 return minusValue ? -ts : ts;
482 [CLSCompliant (false)]
483 public static UInt16 ToUInt16(string s)
485 return UInt16.Parse(s, CultureInfo.InvariantCulture);
488 [CLSCompliant (false)]
489 public static UInt32 ToUInt32(string s)
491 return UInt32.Parse(s, CultureInfo.InvariantCulture);
494 [CLSCompliant (false)]
495 public static UInt64 ToUInt64(string s)
497 return UInt64.Parse(s, CultureInfo.InvariantCulture);
500 public static string VerifyName (string name)
503 throw new ArgumentNullException("name");
505 if(!XmlChar.IsName (name))
506 throw new XmlException("'" + name + "' is not a valid XML Name");
511 public static string VerifyNCName(string ncname)
514 throw new ArgumentNullException("ncname");
516 if(!XmlChar.IsNCName (ncname))
517 throw new XmlException ("'" + ncname + "' is not a valid XML NCName");
521 // It is documented as public method, but in fact it is not.
522 internal static byte [] FromBinHexString (string s)
524 char [] chars = s.ToCharArray ();
525 byte [] bytes = new byte [chars.Length / 2 + chars.Length % 2];
526 FromBinHexString (chars, 0, chars.Length, bytes);
530 internal static int FromBinHexString (char [] chars, int offset, int charLength, byte [] buffer)
532 int bufIndex = offset;
533 for (int i = 0; i < charLength - 1; i += 2) {
534 buffer [bufIndex] = (chars [i] > '9' ?
535 (byte) (chars [i] - 'A' + 10) :
536 (byte) (chars [i] - '0'));
537 buffer [bufIndex] <<= 4;
538 buffer [bufIndex] += chars [i + 1] > '9' ?
539 (byte) (chars [i + 1] - 'A' + 10) :
540 (byte) (chars [i + 1] - '0');
543 if (charLength %2 != 0)
544 buffer [bufIndex++] = (byte)
545 ((chars [charLength - 1] > '9' ?
546 (byte) (chars [charLength - 1] - 'A' + 10) :
547 (byte) (chars [charLength - 1] - '0'))
550 return bufIndex - offset;