(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.XML / System.Xml / XmlConvert.cs
blob01be3cf6e4890fb7fd6b44125748c59a99a235f4
1 //
2 // System.Xml.XmlConvert
3 //
4 // Authors:
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)
9 //
10 // (C) 2002 Ximian, Inc (http://www.ximian.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
34 using System.IO;
35 using System.Text;
36 using System.Globalization;
37 using System.Xml.Schema;
39 namespace System.Xml {
41 public class XmlConvert {
43 const string encodedColon = "_x003A_";
44 const NumberStyles floatStyle = NumberStyles.AllowCurrencySymbol |
45 NumberStyles.AllowExponent |
46 NumberStyles.AllowDecimalPoint |
47 NumberStyles.AllowLeadingSign;
49 static readonly string [] datetimeFormats = {
50 // dateTime
51 "yyyy-MM-ddTHH:mm:ss",
52 "yyyy-MM-ddTHH:mm:ss.f",
53 "yyyy-MM-ddTHH:mm:ss.ff",
54 "yyyy-MM-ddTHH:mm:ss.fff",
55 "yyyy-MM-ddTHH:mm:ss.ffff",
56 "yyyy-MM-ddTHH:mm:ss.fffff",
57 "yyyy-MM-ddTHH:mm:ss.ffffff",
58 "yyyy-MM-ddTHH:mm:ss.fffffff",
59 "yyyy-MM-ddTHH:mm:sszzz",
60 "yyyy-MM-ddTHH:mm:ss.fzzz",
61 "yyyy-MM-ddTHH:mm:ss.ffzzz",
62 "yyyy-MM-ddTHH:mm:ss.fffzzz",
63 "yyyy-MM-ddTHH:mm:ss.ffffzzz",
64 "yyyy-MM-ddTHH:mm:ss.fffffzzz",
65 "yyyy-MM-ddTHH:mm:ss.ffffffzzz",
66 "yyyy-MM-ddTHH:mm:ss.fffffffzzz",
67 "yyyy-MM-ddTHH:mm:ssZ",
68 "yyyy-MM-ddTHH:mm:ss.fZ",
69 "yyyy-MM-ddTHH:mm:ss.ffZ",
70 "yyyy-MM-ddTHH:mm:ss.fffZ",
71 "yyyy-MM-ddTHH:mm:ss.ffffZ",
72 "yyyy-MM-ddTHH:mm:ss.fffffZ",
73 "yyyy-MM-ddTHH:mm:ss.ffffffZ",
74 "yyyy-MM-ddTHH:mm:ss.fffffffZ",
75 // time
76 "HH:mm:ss",
77 "HH:mm:ss.f",
78 "HH:mm:ss.ff",
79 "HH:mm:ss.fff",
80 "HH:mm:ss.ffff",
81 "HH:mm:ss.fffff",
82 "HH:mm:ss.ffffff",
83 "HH:mm:ss.fffffff",
84 "HH:mm:sszzz",
85 "HH:mm:ss.fzzz",
86 "HH:mm:ss.ffzzz",
87 "HH:mm:ss.fffzzz",
88 "HH:mm:ss.ffffzzz",
89 "HH:mm:ss.fffffzzz",
90 "HH:mm:ss.ffffffzzz",
91 "HH:mm:ss.fffffffzzz",
92 "HH:mm:ssZ",
93 "HH:mm:ss.fZ",
94 "HH:mm:ss.ffZ",
95 "HH:mm:ss.fffZ",
96 "HH:mm:ss.ffffZ",
97 "HH:mm:ss.fffffZ",
98 "HH:mm:ss.ffffffZ",
99 "HH:mm:ss.fffffffZ",
100 // date
101 "yyyy-MM-dd",
102 "yyyy-MM-ddzzz",
103 "yyyy-MM-ddZ",
104 // gYearMonth
105 "yyyy-MM",
106 "yyyy-MMzzz",
107 "yyyy-MMZ",
108 // gYear
109 "yyyy",
110 "yyyyzzz",
111 "yyyyZ",
112 // gMonthDay
113 "--MM-dd",
114 "--MM-ddzzz",
115 "--MM-ddZ",
116 // gDay
117 "---dd",
118 "---ddzzz",
119 "---ddZ",
122 public XmlConvert()
125 private static string TryDecoding (string s)
127 if (s == null || s.Length < 6)
128 return s;
130 char c = '\uFFFF';
131 try {
132 c = (char) Int32.Parse (s.Substring (1, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
133 } catch {
134 return s [0] + DecodeName (s.Substring (1));
137 if (s.Length == 6)
138 return c.ToString ();
139 return c + DecodeName (s.Substring (6));
142 public static string DecodeName (string name)
144 if (name == null || name.Length == 0)
145 return name;
147 int pos = name.IndexOf ('_');
148 if (pos == -1 || pos + 6 >= name.Length)
149 return name;
151 if ((name [pos + 1] != 'X' && name [pos + 1] != 'x') || name [pos + 6] != '_')
152 return name [0] + DecodeName (name.Substring (1));
154 return name.Substring (0, pos) + TryDecoding (name.Substring (pos + 1));
157 public static string EncodeLocalName (string name)
159 string encoded = EncodeName (name);
160 int pos = encoded.IndexOf (':');
161 if (pos == -1)
162 return encoded;
163 return encoded.Replace (":", encodedColon);
166 internal static bool IsInvalid (char c, bool firstOnlyLetter)
168 if (c == ':') // Special case. allowed in EncodeName, but encoded in EncodeLocalName
169 return false;
171 if (firstOnlyLetter)
172 return !XmlChar.IsFirstNameChar (c);
173 else
174 return !XmlChar.IsNameChar (c);
177 private static string EncodeName (string name, bool nmtoken)
179 StringBuilder sb = new StringBuilder ();
180 int length = name.Length;
181 for (int i = 0; i < length; i++) {
182 char c = name [i];
183 if (IsInvalid (c, i == 0 && !nmtoken))
184 sb.AppendFormat ("_x{0:X4}_", (int) c);
185 else if (c == '_' && i + 6 < length && name [i+1] == 'x' && name [i + 6] == '_')
186 sb.Append ("_x005F_");
187 else
188 sb.Append (c);
190 return sb.ToString ();
193 public static string EncodeName (string name)
195 return EncodeName (name, false);
198 public static string EncodeNmToken(string name)
200 return EncodeName (name, true);
203 // {true, false, 1, 0}
204 public static bool ToBoolean(string s)
206 s = s.Trim (XmlChar.WhitespaceChars);
207 switch(s)
209 case "1":
210 return true;
211 case "true":
212 return true;
213 case "0":
214 return false;
215 case "false":
216 return false;
217 default:
218 throw new FormatException(s + " is not a valid boolean value");
222 // LAMESPEC: It has been documented as public, but is marked as internal.
223 internal static string ToBinHexString (byte [] buffer)
225 StringWriter w = new StringWriter ();
226 WriteBinHex (buffer, 0, buffer.Length, w);
227 return w.ToString ();
230 internal static void WriteBinHex (byte [] buffer, int index, int count, TextWriter w)
232 if (buffer == null)
233 throw new ArgumentNullException ("buffer");
234 if (index < 0)
235 throw new ArgumentOutOfRangeException ("index", index, "index must be non negative integer.");
236 if (count < 0)
237 throw new ArgumentOutOfRangeException ("count", count, "count must be non negative integer.");
238 if (buffer.Length < index + count)
239 throw new ArgumentOutOfRangeException ("index and count must be smaller than the length of the buffer.");
241 // Copied from XmlTextWriter.WriteBinHex ()
242 int end = index + count;
243 for (int i = index; i < end; i++) {
244 int val = buffer [i];
245 int high = val >> 4;
246 int low = val & 15;
247 if (high > 9)
248 w.Write ((char) (high + 55));
249 else
250 w.Write ((char) (high + 0x30));
251 if (low > 9)
252 w.Write ((char) (low + 55));
253 else
254 w.Write ((char) (low + 0x30));
258 public static byte ToByte(string s)
260 return Byte.Parse(s, CultureInfo.InvariantCulture);
263 public static char ToChar(string s)
265 return Char.Parse(s);
268 public static DateTime ToDateTime(string s)
270 return ToDateTime(s, datetimeFormats);
273 public static DateTime ToDateTime(string s, string format)
275 DateTimeFormatInfo d = new DateTimeFormatInfo();
276 d.FullDateTimePattern = format;
277 return DateTime.Parse(s, d);
280 public static DateTime ToDateTime(string s, string[] formats)
282 DateTimeStyles style = DateTimeStyles.AllowLeadingWhite |
283 DateTimeStyles.AllowTrailingWhite;
284 return DateTime.ParseExact (s, formats, DateTimeFormatInfo.InvariantInfo, style);
287 public static Decimal ToDecimal(string s)
289 return Decimal.Parse(s, CultureInfo.InvariantCulture);
292 public static double ToDouble(string s)
294 if (s == null)
295 throw new ArgumentNullException();
296 if (s == "INF")
297 return Double.PositiveInfinity;
298 if (s == "-INF")
299 return Double.NegativeInfinity;
300 if (s == "NaN")
301 return Double.NaN;
302 return Double.Parse (s, floatStyle, CultureInfo.InvariantCulture);
305 public static Guid ToGuid(string s)
307 return new Guid(s);
310 public static short ToInt16(string s)
312 return Int16.Parse(s, CultureInfo.InvariantCulture);
315 public static int ToInt32(string s)
317 return Int32.Parse(s, CultureInfo.InvariantCulture);
320 public static long ToInt64(string s)
322 return Int64.Parse(s, CultureInfo.InvariantCulture);
325 [CLSCompliant (false)]
326 public static SByte ToSByte(string s)
328 return SByte.Parse(s, CultureInfo.InvariantCulture);
331 public static float ToSingle(string s)
333 if (s == null)
334 throw new ArgumentNullException();
335 if (s == "INF")
336 return Single.PositiveInfinity;
337 if (s == "-INF")
338 return Single.NegativeInfinity;
339 if (s == "NaN")
340 return Single.NaN;
341 return Single.Parse(s, floatStyle, CultureInfo.InvariantCulture);
344 public static string ToString(Guid value)
346 return value.ToString("D", CultureInfo.InvariantCulture);
349 public static string ToString(int value)
351 return value.ToString(CultureInfo.InvariantCulture);
354 public static string ToString(short value)
356 return value.ToString(CultureInfo.InvariantCulture);
359 public static string ToString(byte value)
361 return value.ToString(CultureInfo.InvariantCulture);
364 public static string ToString(long value)
366 return value.ToString(CultureInfo.InvariantCulture);
369 public static string ToString(char value)
371 return value.ToString(CultureInfo.InvariantCulture);
374 public static string ToString(bool value)
376 if (value) return "true";
377 return "false";
380 [CLSCompliant (false)]
381 public static string ToString(SByte value)
383 return value.ToString(CultureInfo.InvariantCulture);
386 public static string ToString(Decimal value)
388 return value.ToString (CultureInfo.InvariantCulture);
391 [CLSCompliant (false)]
392 public static string ToString(UInt64 value)
394 return value.ToString(CultureInfo.InvariantCulture);
397 public static string ToString (TimeSpan value)
399 StringBuilder builder = new StringBuilder ();
400 if (value.Ticks < 0) {
401 builder.Append ('-');
402 value = value.Negate ();
404 builder.Append ('P');
405 if (value.Days > 0)
406 builder.Append (value.Days).Append ('D');
407 if (value.Days > 0 || value.Hours > 0 || value.Minutes > 0 || value.Seconds > 0 || value.Milliseconds > 0) {
408 builder.Append('T');
409 if (value.Hours > 0)
410 builder.Append (value.Hours).Append ('H');
411 if (value.Minutes > 0)
412 builder.Append (value.Minutes).Append ('M');
413 if (value.Seconds > 0 || value.Milliseconds > 0) {
414 builder.Append (value.Seconds);
415 if (value.Milliseconds > 0)
416 builder.Append ('.').AppendFormat ("{0:000}", value.Milliseconds);
417 builder.Append ('S');
420 return builder.ToString ();
423 public static string ToString(double value)
425 if (Double.IsNegativeInfinity(value)) return "-INF";
426 if (Double.IsPositiveInfinity(value)) return "INF";
427 if (Double.IsNaN(value)) return "NaN";
428 return value.ToString(CultureInfo.InvariantCulture);
431 public static string ToString(float value)
433 if (Single.IsNegativeInfinity(value)) return "-INF";
434 if (Single.IsPositiveInfinity(value)) return "INF";
435 if (Single.IsNaN(value)) return "NaN";
436 return value.ToString(CultureInfo.InvariantCulture);
439 [CLSCompliant (false)]
440 public static string ToString(UInt32 value)
442 return value.ToString(CultureInfo.InvariantCulture);
445 [CLSCompliant (false)]
446 public static string ToString(UInt16 value)
448 return value.ToString(CultureInfo.InvariantCulture);
451 public static string ToString(DateTime value)
453 return value.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
456 public static string ToString(DateTime value, string format)
458 return value.ToString(format, CultureInfo.InvariantCulture);
461 public static TimeSpan ToTimeSpan(string s)
463 if (s.Length == 0)
464 throw new ArgumentException ("Invalid format string for duration schema datatype.");
466 int start = 0;
467 if (s [0] == '-')
468 start = 1;
469 bool minusValue = (start == 1);
471 if (s [start] != 'P')
472 throw new ArgumentException ("Invalid format string for duration schema datatype.");
473 start++;
475 int parseStep = 0;
476 int days = 0;
477 bool isTime = false;
478 int hours = 0;
479 int minutes = 0;
480 int seconds = 0;
482 bool error = false;
484 int i = start;
485 while (i < s.Length) {
486 if (s [i] == 'T') {
487 isTime = true;
488 parseStep = 4;
489 i++;
490 start = i;
491 continue;
493 for (; i < s.Length; i++) {
494 if (!Char.IsDigit (s [i]))
495 break;
497 int value = int.Parse (s.Substring (start, i - start), CultureInfo.InvariantCulture);
498 switch (s [i]) {
499 case 'Y':
500 days += value * 365;
501 if (parseStep > 0)
502 error = true;
503 else
504 parseStep = 1;
505 break;
506 case 'M':
507 if (parseStep < 2) {
508 days += 365 * (value / 12) + 30 * (value % 12);
509 parseStep = 2;
510 } else if (isTime && parseStep < 6) {
511 minutes = value;
512 parseStep = 6;
514 else
515 error = true;
516 break;
517 case 'D':
518 days += value;
519 if (parseStep > 2)
520 error = true;
521 else
522 parseStep = 3;
523 break;
524 case 'H':
525 hours = value;
526 if (!isTime || parseStep > 4)
527 error = true;
528 else
529 parseStep = 5;
530 break;
531 case 'S':
532 seconds = value;
533 if (!isTime || parseStep > 6)
534 error = true;
535 else
536 parseStep = 7;
537 break;
538 default:
539 error = true;
540 break;
542 if (error)
543 break;
544 ++i;
545 start = i;
547 if (error)
548 throw new ArgumentException ("Invalid format string for duration schema datatype.");
549 TimeSpan ts = new TimeSpan (days, hours, minutes, seconds);
550 return minusValue ? -ts : ts;
553 [CLSCompliant (false)]
554 public static UInt16 ToUInt16(string s)
556 return UInt16.Parse(s, CultureInfo.InvariantCulture);
559 [CLSCompliant (false)]
560 public static UInt32 ToUInt32(string s)
562 return UInt32.Parse(s, CultureInfo.InvariantCulture);
565 [CLSCompliant (false)]
566 public static UInt64 ToUInt64(string s)
568 return UInt64.Parse(s, CultureInfo.InvariantCulture);
571 public static string VerifyName (string name)
573 if (name == null)
574 throw new ArgumentNullException("name");
576 if (!XmlChar.IsName (name))
577 throw new XmlException("'" + name + "' is not a valid XML Name");
578 return name;
582 public static string VerifyNCName (string ncname)
584 if (ncname == null)
585 throw new ArgumentNullException("ncname");
587 if (!XmlChar.IsNCName (ncname))
588 throw new XmlException ("'" + ncname + "' is not a valid XML NCName");
589 return ncname;
592 #if NET_2_0
593 public static string VerifyNMTOKEN (string name)
594 #else
595 internal static string VerifyNMTOKEN (string name)
596 #endif
598 if (name == null)
599 throw new ArgumentNullException("name");
601 if (!XmlChar.IsNmToken (name))
602 throw new XmlException("'" + name + "' is not a valid XML NMTOKEN");
603 return name;
607 // It is documented as public method, but in fact it is not.
608 internal static byte [] FromBinHexString (string s)
610 char [] chars = s.ToCharArray ();
611 byte [] bytes = new byte [chars.Length / 2 + chars.Length % 2];
612 FromBinHexString (chars, 0, chars.Length, bytes);
613 return bytes;
616 internal static int FromBinHexString (char [] chars, int offset, int charLength, byte [] buffer)
618 int bufIndex = offset;
619 for (int i = 0; i < charLength - 1; i += 2) {
620 buffer [bufIndex] = (chars [i] > '9' ?
621 (byte) (chars [i] - 'A' + 10) :
622 (byte) (chars [i] - '0'));
623 buffer [bufIndex] <<= 4;
624 buffer [bufIndex] += chars [i + 1] > '9' ?
625 (byte) (chars [i + 1] - 'A' + 10) :
626 (byte) (chars [i + 1] - '0');
627 bufIndex++;
629 if (charLength %2 != 0)
630 buffer [bufIndex++] = (byte)
631 ((chars [charLength - 1] > '9' ?
632 (byte) (chars [charLength - 1] - 'A' + 10) :
633 (byte) (chars [charLength - 1] - '0'))
634 << 4);
636 return bufIndex - offset;