872 lines
24 KiB
C#
872 lines
24 KiB
C#
//
|
|
// System.Xml.XmlConvert
|
|
//
|
|
// Authors:
|
|
// Dwivedi, Ajay kumar (Adwiv@Yahoo.com)
|
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
|
// Alan Tam Siu Lung (Tam@SiuLung.com)
|
|
// Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
|
|
//
|
|
// (C) 2002 Ximian, Inc (http://www.ximian.com)
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using System.Xml.Schema;
|
|
|
|
namespace System.Xml {
|
|
|
|
public class XmlConvert {
|
|
|
|
const string encodedColon = "_x003A_";
|
|
const NumberStyles floatStyle = NumberStyles.AllowCurrencySymbol |
|
|
NumberStyles.AllowExponent |
|
|
NumberStyles.AllowDecimalPoint |
|
|
NumberStyles.AllowLeadingSign |
|
|
NumberStyles.AllowLeadingWhite |
|
|
NumberStyles.AllowTrailingWhite;
|
|
|
|
const NumberStyles integerStyle = NumberStyles.Integer |
|
|
NumberStyles.AllowLeadingWhite |
|
|
NumberStyles.AllowTrailingWhite;
|
|
|
|
static readonly string [] datetimeFormats = {
|
|
// dateTime
|
|
"yyyy-MM-ddTHH:mm:sszzz",
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFzzz",
|
|
"yyyy-MM-ddTHH:mm:ssZ",
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFZ",
|
|
"yyyy-MM-ddTHH:mm:ss",
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFF",
|
|
"HH:mm:ss",
|
|
"HH:mm:ss.FFFFFFF",
|
|
"HH:mm:sszzz",
|
|
"HH:mm:ss.FFFFFFFzzz",
|
|
"HH:mm:ssZ",
|
|
"HH:mm:ss.FFFFFFFZ",
|
|
// date
|
|
"yyyy-MM-dd",
|
|
"yyyy-MM-ddzzz",
|
|
"yyyy-MM-ddZ",
|
|
// gYearMonth
|
|
"yyyy-MM",
|
|
"yyyy-MMzzz",
|
|
"yyyy-MMZ",
|
|
// gYear
|
|
"yyyy",
|
|
"yyyyzzz",
|
|
"yyyyZ",
|
|
// gMonthDay
|
|
"--MM-dd",
|
|
"--MM-ddzzz",
|
|
"--MM-ddZ",
|
|
// gDay
|
|
"---dd",
|
|
"---ddzzz",
|
|
"---ddZ",
|
|
};
|
|
|
|
static DateTimeStyles _defaultStyle = DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite;
|
|
|
|
public XmlConvert()
|
|
{}
|
|
|
|
private static string TryDecoding (string s)
|
|
{
|
|
if (s == null || s.Length < 6)
|
|
return s;
|
|
|
|
char c = '\uFFFF';
|
|
try {
|
|
c = (char) Int32.Parse (s.Substring (1, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
} catch {
|
|
return s [0] + DecodeName (s.Substring (1));
|
|
}
|
|
|
|
if (s.Length == 6)
|
|
return c.ToString ();
|
|
return c + DecodeName (s.Substring (6));
|
|
}
|
|
|
|
public static string DecodeName (string name)
|
|
{
|
|
if (name == null || name.Length == 0)
|
|
return name;
|
|
|
|
int pos = name.IndexOf ('_');
|
|
if (pos == -1 || pos + 6 >= name.Length)
|
|
return name;
|
|
|
|
if ((name [pos + 1] != 'X' && name [pos + 1] != 'x') || name [pos + 6] != '_')
|
|
return name [0] + DecodeName (name.Substring (1));
|
|
|
|
return name.Substring (0, pos) + TryDecoding (name.Substring (pos + 1));
|
|
}
|
|
|
|
public static string EncodeLocalName (string name)
|
|
{
|
|
if (name == null)
|
|
return name;
|
|
|
|
string encoded = EncodeName (name);
|
|
int pos = encoded.IndexOf (':');
|
|
if (pos == -1)
|
|
return encoded;
|
|
return encoded.Replace (":", encodedColon);
|
|
}
|
|
|
|
internal static bool IsInvalid (char c, bool firstOnlyLetter)
|
|
{
|
|
if (c == ':') // Special case. allowed in EncodeName, but encoded in EncodeLocalName
|
|
return false;
|
|
|
|
if (firstOnlyLetter)
|
|
return !XmlChar.IsFirstNameChar (c);
|
|
else
|
|
return !XmlChar.IsNameChar (c);
|
|
}
|
|
|
|
private static string EncodeName (string name, bool nmtoken)
|
|
{
|
|
if (name == null || name.Length == 0)
|
|
return name;
|
|
|
|
StringBuilder sb = new StringBuilder ();
|
|
int length = name.Length;
|
|
for (int i = 0; i < length; i++) {
|
|
char c = name [i];
|
|
if (IsInvalid (c, i == 0 && !nmtoken))
|
|
sb.AppendFormat ("_x{0:X4}_", (int) c);
|
|
else if (c == '_' && i + 6 < length && name [i+1] == 'x' && name [i + 6] == '_')
|
|
sb.Append ("_x005F_");
|
|
else
|
|
sb.Append (c);
|
|
}
|
|
return sb.ToString ();
|
|
}
|
|
|
|
public static string EncodeName (string name)
|
|
{
|
|
return EncodeName (name, false);
|
|
}
|
|
|
|
public static string EncodeNmToken (string name)
|
|
{
|
|
if (name == String.Empty)
|
|
throw new XmlException ("Invalid NmToken: ''");
|
|
return EncodeName (name, true);
|
|
}
|
|
|
|
// {true, false, 1, 0}
|
|
public static bool ToBoolean(string s)
|
|
{
|
|
s = s.Trim (XmlChar.WhitespaceChars);
|
|
switch(s)
|
|
{
|
|
case "1":
|
|
return true;
|
|
case "true":
|
|
return true;
|
|
case "0":
|
|
return false;
|
|
case "false":
|
|
return false;
|
|
default:
|
|
throw new FormatException(s + " is not a valid boolean value");
|
|
}
|
|
}
|
|
|
|
// LAMESPEC: It has been documented as public, but is marked as internal.
|
|
internal static string ToBinHexString (byte [] buffer)
|
|
{
|
|
StringWriter w = new StringWriter ();
|
|
WriteBinHex (buffer, 0, buffer.Length, w);
|
|
return w.ToString ();
|
|
}
|
|
|
|
internal static void WriteBinHex (byte [] buffer, int index, int count, TextWriter w)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException ("buffer");
|
|
if (index < 0) {
|
|
throw new ArgumentOutOfRangeException (
|
|
#if !NET_2_1
|
|
"index", index,
|
|
#endif
|
|
"index must be non negative integer.");
|
|
}
|
|
if (count < 0) {
|
|
throw new ArgumentOutOfRangeException (
|
|
#if !NET_2_1
|
|
"count", count,
|
|
#endif
|
|
"count must be non negative integer.");
|
|
}
|
|
if (buffer.Length < index + count)
|
|
throw new ArgumentOutOfRangeException ("index and count must be smaller than the length of the buffer.");
|
|
|
|
// Copied from XmlTextWriter.WriteBinHex ()
|
|
int end = index + count;
|
|
for (int i = index; i < end; i++) {
|
|
int val = buffer [i];
|
|
int high = val >> 4;
|
|
int low = val & 15;
|
|
if (high > 9)
|
|
w.Write ((char) (high + 55));
|
|
else
|
|
w.Write ((char) (high + 0x30));
|
|
if (low > 9)
|
|
w.Write ((char) (low + 55));
|
|
else
|
|
w.Write ((char) (low + 0x30));
|
|
}
|
|
}
|
|
|
|
public static byte ToByte(string s)
|
|
{
|
|
return Byte.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static char ToChar(string s)
|
|
{
|
|
#if !NET_2_1
|
|
return Char.Parse(s);
|
|
#else
|
|
if (s == null)
|
|
throw new ArgumentNullException ("s");
|
|
|
|
if (s.Length != 1)
|
|
throw new FormatException ("String contain more than one char");
|
|
|
|
return s [0];
|
|
#endif
|
|
}
|
|
|
|
[Obsolete]
|
|
public static DateTime ToDateTime (string s)
|
|
{
|
|
return ToDateTime (s, datetimeFormats);
|
|
}
|
|
|
|
public static DateTime ToDateTime (string s, XmlDateTimeSerializationMode dateTimeOption)
|
|
{
|
|
switch (dateTimeOption) {
|
|
case XmlDateTimeSerializationMode.Local:
|
|
return ToDateTime(s, datetimeFormats, _defaultStyle | DateTimeStyles.AssumeLocal).ToLocalTime();
|
|
case XmlDateTimeSerializationMode.RoundtripKind:
|
|
return ToDateTime(s, datetimeFormats, _defaultStyle | DateTimeStyles.RoundtripKind);
|
|
case XmlDateTimeSerializationMode.Utc:
|
|
return ToDateTime(s, datetimeFormats, _defaultStyle | DateTimeStyles.AssumeUniversal).ToUniversalTime();
|
|
default:
|
|
return new DateTime (ToDateTime(s, datetimeFormats, _defaultStyle | DateTimeStyles.RoundtripKind).Ticks, DateTimeKind.Unspecified);
|
|
}
|
|
}
|
|
public static DateTime ToDateTime(string s, string format)
|
|
{
|
|
//DateTimeFormatInfo d = new DateTimeFormatInfo();
|
|
//d.FullDateTimePattern = format;
|
|
//return DateTime.Parse(s, d);
|
|
DateTimeStyles style = DateTimeStyles.AllowLeadingWhite |
|
|
DateTimeStyles.AllowTrailingWhite;
|
|
return DateTime.ParseExact (s, format, DateTimeFormatInfo.InvariantInfo, style);
|
|
}
|
|
|
|
public static DateTime ToDateTime(string s, string[] formats)
|
|
{
|
|
return ToDateTime (s, formats, _defaultStyle);
|
|
}
|
|
|
|
private static DateTime ToDateTime (string s, string [] formats, DateTimeStyles style)
|
|
{
|
|
try {
|
|
return DateTime.ParseExact (s, formats, DateTimeFormatInfo.InvariantInfo, style);
|
|
} catch (ArgumentOutOfRangeException) {
|
|
return DateTime.MinValue;
|
|
}
|
|
}
|
|
|
|
public static Decimal ToDecimal(string s)
|
|
{
|
|
return Decimal.Parse(s, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static double ToDouble(string s)
|
|
{
|
|
if (s == null)
|
|
throw new ArgumentNullException();
|
|
|
|
float f = TryParseStringFloatConstants (s);
|
|
if (f != 0)
|
|
return f;
|
|
|
|
return Double.Parse (s, floatStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
static float TryParseStringFloatConstants (string s)
|
|
{
|
|
int sidx = 0;
|
|
while (sidx < s.Length && Char.IsWhiteSpace (s [sidx]))
|
|
sidx++;
|
|
if (sidx == s.Length)
|
|
throw new FormatException ();
|
|
int sEndPos = s.Length - 1;
|
|
while (Char.IsWhiteSpace (s [sEndPos]))
|
|
sEndPos--;
|
|
|
|
if (TryParseStringConstant ("NaN", s, sidx, sEndPos))
|
|
return Single.NaN;
|
|
if (TryParseStringConstant ("INF", s, sidx, sEndPos))
|
|
return Single.PositiveInfinity;
|
|
if (TryParseStringConstant ("-INF", s, sidx, sEndPos))
|
|
return Single.NegativeInfinity;
|
|
// Handle these here because Single.Parse("Infinity") is invalid while XmlConvert.ToSingle("Infinity") is valid.
|
|
if (TryParseStringConstant ("Infinity", s, sidx, sEndPos))
|
|
return Single.PositiveInfinity;
|
|
if (TryParseStringConstant ("-Infinity", s, sidx, sEndPos))
|
|
return Single.NegativeInfinity;
|
|
return 0;
|
|
}
|
|
|
|
static bool TryParseStringConstant (string format, string s, int start, int end)
|
|
{
|
|
return end - start + 1 == format.Length && String.CompareOrdinal (format, 0, s, start, format.Length) == 0;
|
|
}
|
|
|
|
public static Guid ToGuid (string s)
|
|
{
|
|
try {
|
|
return new Guid(s);
|
|
} catch (FormatException ex) {
|
|
throw new FormatException (String.Format ("Invalid Guid input '{0}'", ex.InnerException));
|
|
}
|
|
}
|
|
|
|
public static short ToInt16(string s)
|
|
{
|
|
return Int16.Parse (s, integerStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static int ToInt32(string s)
|
|
{
|
|
return Int32.Parse (s, integerStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static long ToInt64(string s)
|
|
{
|
|
return Int64.Parse (s, integerStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static SByte ToSByte(string s)
|
|
{
|
|
return SByte.Parse(s, integerStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static float ToSingle(string s)
|
|
{
|
|
if (s == null)
|
|
throw new ArgumentNullException();
|
|
|
|
float f = TryParseStringFloatConstants (s);
|
|
if (f != 0)
|
|
return f;
|
|
|
|
return Single.Parse(s, floatStyle, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(Guid value)
|
|
{
|
|
return value.ToString("D", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(int value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(short value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(byte value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(long value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(char value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(bool value)
|
|
{
|
|
if (value) return "true";
|
|
return "false";
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static string ToString(SByte value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(Decimal value)
|
|
{
|
|
return value.ToString (CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static string ToString(UInt64 value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString (TimeSpan value)
|
|
{
|
|
if (value == TimeSpan.Zero)
|
|
return "PT0S";
|
|
|
|
StringBuilder builder = new StringBuilder ();
|
|
if (value.Ticks < 0) {
|
|
if (value == TimeSpan.MinValue)
|
|
return "-P10675199DT2H48M5.4775808S"; // There's one fewer tick on the positive side, so we cannot Negate this value; just hard-code it
|
|
builder.Append ('-');
|
|
value = value.Negate ();
|
|
}
|
|
builder.Append ('P');
|
|
if (value.Days > 0)
|
|
builder.Append (value.Days).Append ('D');
|
|
long ticks = value.Ticks % TimeSpan.TicksPerMillisecond;
|
|
if (value.Hours > 0 || value.Minutes > 0 || value.Seconds > 0 || value.Milliseconds > 0 || ticks > 0) {
|
|
builder.Append('T');
|
|
if (value.Hours > 0)
|
|
builder.Append (value.Hours).Append ('H');
|
|
if (value.Minutes > 0)
|
|
builder.Append (value.Minutes).Append ('M');
|
|
if (value.Seconds > 0 || value.Milliseconds > 0 || ticks > 0) {
|
|
builder.Append (value.Seconds);
|
|
bool trimZero = true;
|
|
if (ticks > 0)
|
|
builder.Append ('.').AppendFormat ("{0:0000000}", value.Ticks % TimeSpan.TicksPerSecond);
|
|
else if (value.Milliseconds > 0)
|
|
builder.Append ('.').AppendFormat ("{0:000}", value.Milliseconds);
|
|
else
|
|
trimZero = false;
|
|
if (trimZero)
|
|
while (builder [builder.Length - 1] == '0')
|
|
builder.Remove (builder.Length - 1, 1);
|
|
|
|
builder.Append ('S');
|
|
}
|
|
}
|
|
return builder.ToString ();
|
|
}
|
|
|
|
public static string ToString(double value)
|
|
{
|
|
if (Double.IsNegativeInfinity(value)) return "-INF";
|
|
if (Double.IsPositiveInfinity(value)) return "INF";
|
|
if (Double.IsNaN(value)) return "NaN";
|
|
return value.ToString("R", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString(float value)
|
|
{
|
|
if (Single.IsNegativeInfinity(value)) return "-INF";
|
|
if (Single.IsPositiveInfinity(value)) return "INF";
|
|
if (Single.IsNaN(value)) return "NaN";
|
|
return value.ToString("R", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static string ToString(UInt32 value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static string ToString(UInt16 value)
|
|
{
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[Obsolete]
|
|
public static string ToString (DateTime value)
|
|
{
|
|
return value.ToString ("yyyy-MM-ddTHH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string ToString (DateTime value, XmlDateTimeSerializationMode dateTimeOption)
|
|
{
|
|
// Unlike usual DateTime formatting, it preserves
|
|
// MaxValue/MinValue as is.
|
|
switch (dateTimeOption) {
|
|
case XmlDateTimeSerializationMode.Local:
|
|
return (value == DateTime.MinValue ? DateTime.MinValue : value == DateTime.MaxValue ? value : value.ToLocalTime ()).ToString (
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFzzz",
|
|
CultureInfo.InvariantCulture);
|
|
case XmlDateTimeSerializationMode.RoundtripKind:
|
|
return value.ToString (
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFK",
|
|
CultureInfo.InvariantCulture);
|
|
default:
|
|
return value.ToString (
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFzzz",
|
|
CultureInfo.InvariantCulture);
|
|
case XmlDateTimeSerializationMode.Utc:
|
|
return (value == DateTime.MinValue ? DateTime.MinValue : value == DateTime.MaxValue ? value : value.ToUniversalTime ()).ToString (
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFFZ",
|
|
CultureInfo.InvariantCulture);
|
|
case XmlDateTimeSerializationMode.Unspecified:
|
|
return value.ToString (
|
|
"yyyy-MM-ddTHH:mm:ss.FFFFFFF",
|
|
CultureInfo.InvariantCulture);
|
|
}
|
|
}
|
|
|
|
public static string ToString(DateTime value, string format)
|
|
{
|
|
return value.ToString(format, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static TimeSpan ToTimeSpan(string s)
|
|
{
|
|
s = s.Trim (XmlChar.WhitespaceChars);
|
|
if (s.Length == 0)
|
|
throw new FormatException ("Invalid format string for duration schema datatype.");
|
|
|
|
int start = 0;
|
|
if (s [0] == '-')
|
|
start = 1;
|
|
bool minusValue = (start == 1);
|
|
|
|
if (s [start] != 'P')
|
|
throw new FormatException ("Invalid format string for duration schema datatype.");
|
|
start++;
|
|
|
|
int parseStep = 0;
|
|
int days = 0;
|
|
bool isTime = false;
|
|
int hours = 0;
|
|
int minutes = 0;
|
|
int seconds = 0;
|
|
long ticks = 0;
|
|
int parsedDigits = 0;
|
|
|
|
bool error = false;
|
|
|
|
int i = start;
|
|
while (i < s.Length) {
|
|
if (s [i] == 'T') {
|
|
isTime = true;
|
|
parseStep = 4;
|
|
i++;
|
|
start = i;
|
|
continue;
|
|
}
|
|
for (; i < s.Length; i++)
|
|
if (s [i] < '0' || '9' < s [i])
|
|
break;
|
|
if (parseStep == 7)
|
|
parsedDigits = i - start;
|
|
int value = int.Parse (s.Substring (start, i - start), CultureInfo.InvariantCulture);
|
|
if (parseStep == 7) {
|
|
// adjust to 7 digits so that it makes sense as millisecond digits
|
|
for (; parsedDigits > 7; parsedDigits--)
|
|
value /= 10;
|
|
for (; parsedDigits < 7; parsedDigits++)
|
|
value *= 10;
|
|
}
|
|
switch (s [i]) {
|
|
case 'Y':
|
|
days += value * 365;
|
|
if (parseStep > 0)
|
|
error = true;
|
|
else
|
|
parseStep = 1;
|
|
break;
|
|
case 'M':
|
|
if (parseStep < 2) {
|
|
days += 365 * (value / 12) + 30 * (value % 12);
|
|
parseStep = 2;
|
|
} else if (isTime && parseStep < 6) {
|
|
minutes = value;
|
|
parseStep = 6;
|
|
}
|
|
else
|
|
error = true;
|
|
break;
|
|
case 'D':
|
|
days += value;
|
|
if (parseStep > 2)
|
|
error = true;
|
|
else
|
|
parseStep = 3;
|
|
break;
|
|
case 'H':
|
|
hours = value;
|
|
if (!isTime || parseStep > 4)
|
|
error = true;
|
|
else
|
|
parseStep = 5;
|
|
break;
|
|
case 'S':
|
|
if (parseStep == 7)
|
|
ticks = value;
|
|
else
|
|
seconds = value;
|
|
if (!isTime || parseStep > 7)
|
|
error = true;
|
|
else
|
|
parseStep = 8;
|
|
break;
|
|
case '.':
|
|
if (parseStep > 7)
|
|
error = true;
|
|
seconds = value;
|
|
parseStep = 7;
|
|
break;
|
|
default:
|
|
error = true;
|
|
break;
|
|
}
|
|
if (error)
|
|
break;
|
|
++i;
|
|
start = i;
|
|
}
|
|
if (error)
|
|
throw new FormatException ("Invalid format string for duration schema datatype.");
|
|
TimeSpan ts = new TimeSpan (days, hours, minutes, seconds);
|
|
if (minusValue)
|
|
return TimeSpan.FromTicks (- (ts.Ticks + ticks));
|
|
else
|
|
return TimeSpan.FromTicks (ts.Ticks + ticks);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static UInt16 ToUInt16(string s)
|
|
{
|
|
return UInt16.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static UInt32 ToUInt32(string s)
|
|
{
|
|
return UInt32.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
[CLSCompliant (false)]
|
|
public static UInt64 ToUInt64(string s)
|
|
{
|
|
return UInt64.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static string VerifyName (string name)
|
|
{
|
|
if (name == null || name.Length == 0)
|
|
throw new ArgumentNullException("name");
|
|
|
|
if (!XmlChar.IsName (name))
|
|
throw new XmlException("'" + name + "' is not a valid XML Name");
|
|
return name;
|
|
|
|
}
|
|
|
|
public static string VerifyNCName (string name)
|
|
{
|
|
if (name == null || name.Length == 0)
|
|
throw new ArgumentNullException("name");
|
|
|
|
if (!XmlChar.IsNCName (name))
|
|
throw new XmlException ("'" + name + "' is not a valid XML NCName");
|
|
return name;
|
|
}
|
|
|
|
public static string VerifyTOKEN (string token)
|
|
{
|
|
if (token == null)
|
|
throw new ArgumentNullException("token");
|
|
|
|
if (token.Length == 0)
|
|
return token;
|
|
|
|
if (XmlChar.IsWhitespace (token [0]) ||
|
|
XmlChar.IsWhitespace (token [token.Length - 1]))
|
|
throw new XmlException ("Whitespace characters (#xA, #xD, #x9, #x20) are not allowed as leading or trailing whitespaces of xs:token.");
|
|
|
|
for (int i = 0; i < token.Length; i++)
|
|
if (XmlChar.IsWhitespace (token [i]) && token [i] != ' ')
|
|
throw new XmlException ("Either #xA, #xD or #x9 are not allowed inside xs:token.");
|
|
|
|
return token;
|
|
}
|
|
|
|
public static string VerifyNMTOKEN (string name)
|
|
{
|
|
if (name == null)
|
|
throw new ArgumentNullException("name");
|
|
|
|
if (!XmlChar.IsNmToken (name))
|
|
throw new XmlException("'" + name + "' is not a valid XML NMTOKEN");
|
|
return name;
|
|
|
|
}
|
|
|
|
// It is documented as public method, but in fact it is not.
|
|
internal static byte [] FromBinHexString (string s)
|
|
{
|
|
char [] chars = s.ToCharArray ();
|
|
byte [] bytes = new byte [chars.Length / 2 + chars.Length % 2];
|
|
FromBinHexString (chars, 0, chars.Length, bytes);
|
|
return bytes;
|
|
}
|
|
|
|
internal static int FromBinHexString (char [] chars, int offset, int charLength, byte [] buffer)
|
|
{
|
|
int bufIndex = offset;
|
|
for (int i = 0; i < charLength - 1; i += 2) {
|
|
buffer [bufIndex] = (chars [i] > '9' ?
|
|
(byte) (chars [i] - 'A' + 10) :
|
|
(byte) (chars [i] - '0'));
|
|
buffer [bufIndex] <<= 4;
|
|
buffer [bufIndex] += chars [i + 1] > '9' ?
|
|
(byte) (chars [i + 1] - 'A' + 10) :
|
|
(byte) (chars [i + 1] - '0');
|
|
bufIndex++;
|
|
}
|
|
if (charLength %2 != 0)
|
|
buffer [bufIndex++] = (byte)
|
|
((chars [charLength - 1] > '9' ?
|
|
(byte) (chars [charLength - 1] - 'A' + 10) :
|
|
(byte) (chars [charLength - 1] - '0'))
|
|
<< 4);
|
|
|
|
return bufIndex - offset;
|
|
}
|
|
|
|
|
|
public static DateTimeOffset ToDateTimeOffset (string s)
|
|
{
|
|
return ToDateTimeOffset (s, datetimeFormats);
|
|
}
|
|
|
|
public static DateTimeOffset ToDateTimeOffset (string s, string format)
|
|
{
|
|
return DateTimeOffset.ParseExact (s, format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
|
}
|
|
|
|
public static DateTimeOffset ToDateTimeOffset (string s, string [] formats)
|
|
{
|
|
DateTimeStyles style = DateTimeStyles.AllowLeadingWhite |
|
|
DateTimeStyles.AllowTrailingWhite |
|
|
DateTimeStyles.AssumeUniversal;
|
|
return DateTimeOffset.ParseExact (s, formats, CultureInfo.InvariantCulture, style);
|
|
}
|
|
|
|
public static string ToString (DateTimeOffset value)
|
|
{
|
|
return ToString (value, "yyyy-MM-ddTHH:mm:ss.FFFFFFFzzz");
|
|
}
|
|
|
|
public static string ToString (DateTimeOffset value, string format)
|
|
{
|
|
return value.ToString (format, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
// it is used only from 2.1 System.Xml.Serialization.dll from
|
|
// MS Silverlight SDK. We don't use it so far.
|
|
internal static Uri ToUri (string s)
|
|
{
|
|
return new Uri (s, UriKind.RelativeOrAbsolute);
|
|
}
|
|
|
|
|
|
public static bool IsNCNameChar (char ch)
|
|
{
|
|
return XmlChar.IsNCNameChar (ch);
|
|
}
|
|
|
|
public static bool IsPublicIdChar (char ch)
|
|
{
|
|
return XmlChar.IsPubidChar (ch);
|
|
}
|
|
|
|
public static bool IsStartNCNameChar (char ch)
|
|
{
|
|
return XmlChar.IsFirstNameChar (ch);
|
|
}
|
|
|
|
public static bool IsWhitespaceChar (char ch)
|
|
{
|
|
return XmlChar.IsWhitespace (ch);
|
|
}
|
|
|
|
public static bool IsXmlChar (char ch)
|
|
{
|
|
return XmlChar.IsValid (ch);
|
|
}
|
|
|
|
public static bool IsXmlSurrogatePair (char lowChar, char highChar)
|
|
{
|
|
return 0xD800 <= lowChar && lowChar <= 0xDBFF && 0xDC00 <= highChar && highChar <= 0xDFFF;
|
|
}
|
|
|
|
public static string VerifyPublicId (string publicId)
|
|
{
|
|
if (publicId == null)
|
|
throw new ArgumentNullException ("publicId");
|
|
if (XmlChar.IsPubid (publicId))
|
|
return publicId;
|
|
throw new XmlException (string.Format ("'{0}' is not a valid PUBLIC ID", publicId));
|
|
}
|
|
|
|
public static string VerifyWhitespace (string content)
|
|
{
|
|
if (content == null)
|
|
throw new ArgumentNullException ("content");
|
|
if (XmlChar.IsWhitespace (content))
|
|
return content;
|
|
throw new XmlException (string.Format ("'{0}' is not whitespace", content));
|
|
}
|
|
|
|
public static string VerifyXmlChars (string content)
|
|
{
|
|
if (content == null)
|
|
throw new ArgumentNullException ("content");
|
|
var idx = XmlChar.IndexOfInvalid (content, true);
|
|
if (idx < 0)
|
|
return content;
|
|
throw new XmlException (string.Format ("Invalid XML character was found in the content, at index {0}.", idx));
|
|
}
|
|
}
|
|
}
|