//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // [....] //------------------------------------------------------------------------------ namespace System.Xml { using System.IO; using System.Text; using System.Globalization; using System.Xml.Schema; using System.Diagnostics; using System.Collections; using System.Text.RegularExpressions; // ExceptionType enum is used inside XmlConvert to specify which type of exception should be thrown at some of the verification and exception creating methods internal enum ExceptionType { ArgumentException, XmlException, } // Options for serializing and deserializing DateTime public enum XmlDateTimeSerializationMode { Local, Utc, Unspecified, RoundtripKind, } /// /// /// Encodes and decodes XML names according to /// the "Encoding of arbitrary Unicode Characters in XML Names" specification. /// public class XmlConvert { // // Static fields with implicit initialization // static XmlCharType xmlCharType = XmlCharType.Instance; #if !SILVERLIGHT internal static char[] crt = new char[] {'\n', '\r', '\t'}; #endif /// /// /// /// Converts names, such /// as DataTable or /// DataColumn names, that contain characters that are not permitted in /// XML names to valid names. /// public static string EncodeName(string name) { return EncodeName(name, true/*Name_not_NmToken*/, false/*Local?*/); } /// /// /// Verifies the name is valid /// according to production [7] in the XML spec. /// public static string EncodeNmToken(string name) { return EncodeName(name, false/*Name_not_NmToken*/, false/*Local?*/); } /// /// /// Converts names, such as DataTable or DataColumn names, that contain /// characters that are not permitted in XML names to valid names. /// public static string EncodeLocalName(string name) { return EncodeName(name, true/*Name_not_NmToken*/, true/*Local?*/); } /// /// /// /// Transforms an XML name into an object name (such as DataTable or DataColumn). /// public static string DecodeName(string name) { if (name == null || name.Length == 0) return name; StringBuilder bufBld = null; int length = name.Length; int copyPosition = 0; int underscorePos = name.IndexOf('_'); MatchCollection mc = null; IEnumerator en = null; if (underscorePos >= 0) { if ( c_DecodeCharPattern == null ) { c_DecodeCharPattern = new Regex("_[Xx]([0-9a-fA-F]{4}|[0-9a-fA-F]{8})_"); } mc = c_DecodeCharPattern.Matches(name, underscorePos); en = mc.GetEnumerator(); } else { return name; } int matchPos = -1; if (en != null && en.MoveNext()) { Match m = (Match)en.Current; matchPos = m.Index; } for (int position = 0; position < length - c_EncodedCharLength + 1; position ++) { if (position == matchPos) { if (en.MoveNext()) { Match m = (Match)en.Current; matchPos = m.Index; } if (bufBld == null) { bufBld = new StringBuilder(length + 20); } bufBld.Append(name, copyPosition, position - copyPosition); if (name[position + 6]!='_') { //_x1234_ Int32 u = FromHex(name[position + 2]) * 0x10000000 + FromHex(name[position + 3]) * 0x1000000 + FromHex(name[position + 4]) * 0x100000 + FromHex(name[position + 5]) * 0x10000 + FromHex(name[position + 6]) * 0x1000 + FromHex(name[position + 7]) * 0x100 + FromHex(name[position + 8]) * 0x10 + FromHex(name[position + 9]); if (u >= 0x00010000) { if (u <= 0x0010ffff) { //convert to two chars copyPosition = position + c_EncodedCharLength + 4; char lowChar, highChar; XmlCharType.SplitSurrogateChar(u, out lowChar, out highChar); bufBld.Append(highChar); bufBld.Append(lowChar); } //else bad ucs-4 char dont convert } else { //convert to single char copyPosition = position + c_EncodedCharLength + 4; bufBld.Append((char)u); } position += c_EncodedCharLength - 1 + 4; //just skip } else { copyPosition = position + c_EncodedCharLength; bufBld.Append((char)( FromHex(name[position + 2]) * 0x1000 + FromHex(name[position + 3]) * 0x100 + FromHex(name[position + 4]) * 0x10 + FromHex(name[position + 5]))); position += c_EncodedCharLength - 1; } } } if (copyPosition == 0) { return name; } else { if (copyPosition < length) { bufBld.Append(name, copyPosition, length - copyPosition); } return bufBld.ToString(); } } private static string EncodeName(string name, /*Name_not_NmToken*/ bool first, bool local) { if (string.IsNullOrEmpty(name)) { return name; } StringBuilder bufBld = null; int length = name.Length; int copyPosition = 0; int position = 0; int underscorePos = name.IndexOf('_'); MatchCollection mc = null; IEnumerator en = null; if (underscorePos >= 0) { if ( c_EncodeCharPattern == null ) { c_EncodeCharPattern = new Regex("(?<=_)[Xx]([0-9a-fA-F]{4}|[0-9a-fA-F]{8})_"); } mc = c_EncodeCharPattern.Matches(name, underscorePos); en = mc.GetEnumerator(); } int matchPos = -1; if (en != null && en.MoveNext()) { Match m = (Match)en.Current; matchPos = m.Index - 1; } if (first) { if ( ( !xmlCharType.IsStartNCNameCharXml4e( name[0] ) && (local || (!local && name[0] != ':'))) || matchPos == 0) { if (bufBld == null) { bufBld = new StringBuilder(length + 20); } bufBld.Append("_x"); if (length > 1 && XmlCharType.IsHighSurrogate(name[0]) && XmlCharType.IsLowSurrogate(name[1]) ) { int x = name[0]; int y = name[1]; Int32 u = XmlCharType.CombineSurrogateChar(y, x); bufBld.Append(u.ToString("X8", CultureInfo.InvariantCulture)); position ++; copyPosition = 2; } else { bufBld.Append(((Int32)name[0]).ToString("X4", CultureInfo.InvariantCulture)); copyPosition = 1; } bufBld.Append("_"); position ++; if (matchPos == 0) if (en.MoveNext()) { Match m = (Match)en.Current; matchPos = m.Index - 1; } } } for (; position < length; position ++) { if ((local && !xmlCharType.IsNCNameCharXml4e(name[position])) || (!local && !xmlCharType.IsNameCharXml4e(name[position])) || (matchPos == position)) { if (bufBld == null) { bufBld = new StringBuilder(length + 20); } if (matchPos == position) if (en.MoveNext()) { Match m = (Match)en.Current; matchPos = m.Index - 1; } bufBld.Append(name, copyPosition, position - copyPosition); bufBld.Append("_x"); if ((length > position + 1) && XmlCharType.IsHighSurrogate(name[position]) && XmlCharType.IsLowSurrogate(name[position + 1])) { int x = name[position]; int y = name[position + 1]; Int32 u = XmlCharType.CombineSurrogateChar(y, x); bufBld.Append(u.ToString("X8", CultureInfo.InvariantCulture)); copyPosition = position + 2; position ++; } else { bufBld.Append(((Int32)name[position]).ToString("X4", CultureInfo.InvariantCulture)); copyPosition = position + 1; } bufBld.Append("_"); } } if (copyPosition == 0) { return name; } else { if (copyPosition < length) { bufBld.Append(name, copyPosition, length - copyPosition); } return bufBld.ToString(); } } private static readonly int c_EncodedCharLength = 7; // ("_xFFFF_".Length); private static volatile Regex c_EncodeCharPattern; private static volatile Regex c_DecodeCharPattern; private static int FromHex(char digit) { return(digit <= '9') ? ((int)digit - (int)'0') : (((digit <= 'F') ? ((int)digit - (int)'A') : ((int)digit - (int)'a')) + 10); } internal static byte[] FromBinHexString(string s) { return FromBinHexString(s, true); } internal static byte[] FromBinHexString(string s, bool allowOddCount ) { if (s == null) { throw new ArgumentNullException("s"); } return BinHexDecoder.Decode(s.ToCharArray(), allowOddCount); } internal static string ToBinHexString(byte[] inArray) { if (inArray == null) { throw new ArgumentNullException("inArray"); } return BinHexEncoder.Encode(inArray, 0, inArray.Length); } // // Verification methods for strings // /// /// /// /// /// public static string VerifyName(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentNullException("name", Res.GetString(Res.Xml_EmptyName)); } // parse name int endPos = ValidateNames.ParseNameNoNamespaces(name, 0); if (endPos != name.Length) { // did not parse to the end -> there is invalid character at endPos throw CreateInvalidNameCharException(name, endPos, ExceptionType.XmlException); } return name; } #if !SILVERLIGHT internal static Exception TryVerifyName(string name) { if (name == null || name.Length == 0) { return new XmlException(Res.Xml_EmptyName, string.Empty); } int endPos = ValidateNames.ParseNameNoNamespaces(name, 0); if (endPos != name.Length) { return new XmlException(endPos == 0 ? Res.Xml_BadStartNameChar : Res.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, endPos)); } return null; } internal static string VerifyQName(string name) { return VerifyQName(name, ExceptionType.XmlException); } #endif #if SILVERLIGHT internal static string VerifyQName(string name, ExceptionType exceptionType) { #else internal static unsafe string VerifyQName(string name, ExceptionType exceptionType) { #endif if (name == null || name.Length == 0) { throw new ArgumentNullException("name"); } int colonPosition = -1; int endPos = ValidateNames.ParseQName(name, 0, out colonPosition); if (endPos != name.Length) { throw CreateException(Res.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, endPos), exceptionType, 0, endPos + 1); } return name; } /// /// /// /// /// public static string VerifyNCName(string name) { return VerifyNCName(name, ExceptionType.XmlException); } internal static string VerifyNCName(string name, ExceptionType exceptionType) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentNullException("name", Res.GetString(Res.Xml_EmptyLocalName)); } int end = ValidateNames.ParseNCName(name, 0); if (end != name.Length) { // If the string is not a valid NCName, then throw or return false throw CreateInvalidNameCharException(name, end, exceptionType); } return name; } #if !SILVERLIGHT internal static Exception TryVerifyNCName(string name) { int len = ValidateNames.ParseNCName(name); if (len == 0 || len != name.Length) { return ValidateNames.GetInvalidNameException(name, 0, len); } return null; } /// /// /// /// /// public static string VerifyTOKEN(string token) { if (token == null || token.Length == 0) { return token; } if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1) { throw new XmlException(Res.Sch_NotTokenString, token); } return token; } internal static Exception TryVerifyTOKEN(string token) { if (token == null || token.Length == 0) { return null; } if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1) { return new XmlException(Res.Sch_NotTokenString, token); } return null; } #endif /// /// /// /// /// public static string VerifyNMTOKEN(string name) { return VerifyNMTOKEN(name, ExceptionType.XmlException); } internal static string VerifyNMTOKEN(string name, ExceptionType exceptionType) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw CreateException(Res.Xml_InvalidNmToken, name, exceptionType); } int endPos = ValidateNames.ParseNmtokenNoNamespaces(name, 0); if (endPos != name.Length) { throw CreateException(Res.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, endPos), exceptionType, 0, endPos + 1); } return name; } #if !SILVERLIGHT internal static Exception TryVerifyNMTOKEN(string name) { if (name == null || name.Length == 0) { return new XmlException(Res.Xml_EmptyName, string.Empty); } int endPos = ValidateNames.ParseNmtokenNoNamespaces(name, 0); if (endPos != name.Length) { return new XmlException(Res.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, endPos)); } return null; } internal static string VerifyNormalizedString(string str) { if (str.IndexOfAny(crt) != -1) { throw new XmlSchemaException(Res.Sch_NotNormalizedString, str); } return str; } internal static Exception TryVerifyNormalizedString(string str) { if (str.IndexOfAny(crt) != -1) { return new XmlSchemaException(Res.Sch_NotNormalizedString, str); } return null; } #endif // Verification method for XML characters as defined in XML spec production [2] Char. // Throws XmlException if invalid character is found, otherwise returns the input string. public static string VerifyXmlChars(string content) { if (content == null) { throw new ArgumentNullException("content"); } VerifyCharData(content, ExceptionType.XmlException); return content; } // Verification method for XML public ID characters as defined in XML spec production [13] PubidChar. // Throws XmlException if invalid character is found, otherwise returns the input string. public static string VerifyPublicId(string publicId) { if (publicId == null) { throw new ArgumentNullException("publicId"); } // returns the position of invalid character or -1 int pos = xmlCharType.IsPublicId(publicId); if (pos != -1) { throw CreateInvalidCharException(publicId, pos, ExceptionType.XmlException); } return publicId; } // Verification method for XML whitespace characters as defined in XML spec production [3] S. // Throws XmlException if invalid character is found, otherwise returns the input string. public static string VerifyWhitespace(string content) { if (content == null) { throw new ArgumentNullException("content"); } // returns the position of invalid character or -1 int pos = xmlCharType.IsOnlyWhitespaceWithPos(content); if (pos != -1) { throw new XmlException(Res.Xml_InvalidWhitespaceCharacter, XmlException.BuildCharExceptionArgs(content, pos), 0, pos + 1); } return content; } // // Verification methods for single characters and surrogates // // In cases where the direct call into XmlCharType would not get automatically inlined (because of the use of byte* field), // direct access to the XmlCharType.charProperties is used instead (= manual inlining). // // Start name character types - as defined in Namespaces XML 1.0 spec (second edition) production [6] NCNameStartChar // combined with the production [4] NameStartChar of XML 1.0 spec public static unsafe bool IsStartNCNameChar(char ch) { #if SILVERLIGHT return xmlCharType.IsStartNCNameSingleChar(ch); #else return (xmlCharType.charProperties[ch] & XmlCharType.fNCStartNameSC) != 0; #endif } #if XML10_FIFTH_EDITION public static bool IsStartNCNameSurrogatePair(char lowChar, char highChar) { return xmlCharType.IsNCNameSurrogateChar(lowChar, highChar); } #endif // Name character types - as defined in Namespaces XML 1.0 spec (second edition) production [6] NCNameStartChar // combined with the production [4] NameChar of XML 1.0 spec public static unsafe bool IsNCNameChar(char ch) { #if SILVERLIGHT return xmlCharType.IsNCNameSingleChar(ch); #else return (xmlCharType.charProperties[ch] & XmlCharType.fNCNameSC) != 0; #endif } #if XML10_FIFTH_EDITION public static bool IsNCNameSurrogatePair(char lowChar, char highChar) { return xmlCharType.IsNCNameSurrogateChar(lowChar, highChar); } #endif // Valid XML character – as defined in XML 1.0 spec (fifth edition) production [2] Char public static unsafe bool IsXmlChar(char ch) { #if SILVERLIGHT return xmlCharType.IsCharData(ch); #else return (xmlCharType.charProperties[ch] & XmlCharType.fCharData) != 0; #endif } public static bool IsXmlSurrogatePair(char lowChar, char highChar) { return XmlCharType.IsHighSurrogate(highChar) && XmlCharType.IsLowSurrogate(lowChar); } // Valid PUBLIC ID character – as defined in XML 1.0 spec (fifth edition) production [13] PublidChar public static bool IsPublicIdChar(char ch) { return xmlCharType.IsPubidChar(ch); } // Valid Xml white space – as defined in XML 1.0 spec (fifth edition) production [3] S public static unsafe bool IsWhitespaceChar(char ch) { #if SILVERLIGHT return xmlCharType.IsWhiteSpace(ch); #else return (xmlCharType.charProperties[ch] & XmlCharType.fWhitespace) != 0; #endif } // Value convertors: // // String representation of Base types in XML (xsd) sometimes differ from // one common language runtime offer and for all types it has to be locale independent. // o -- means that XmlConvert pass through to common language runtime converter with InvariantInfo FormatInfo // x -- means we doing something special to make a convertion. // // From: To: Bol Chr SBy Byt I16 U16 I32 U32 I64 U64 Sgl Dbl Dec Dat Tim Str uid // ------------------------------------------------------------------------------ // Boolean x // Char o // SByte o // Byte o // Int16 o // UInt16 o // Int32 o // UInt32 o // Int64 o // UInt64 o // Single x // Double x // Decimal o // DateTime x // String x o o o o o o o o o o x x o o x // Guid x // ----------------------------------------------------------------------------- /// /// /// [To be supplied.] /// public static string ToString(Boolean value) { return value ? "true" : "false"; } /// /// /// [To be supplied.] /// public static string ToString(Char value) { return value.ToString(null); } /// /// /// [To be supplied.] /// public static string ToString(Decimal value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static string ToString(SByte value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Int16 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Int32 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Int64 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Byte value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static string ToString(UInt16 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static string ToString(UInt32 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static string ToString(UInt64 value) { return value.ToString(null, NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Single value) { if (Single.IsNegativeInfinity(value)) return "-INF"; if (Single.IsPositiveInfinity(value)) return "INF"; if (IsNegativeZero((double)value)) { return("-0"); } return value.ToString("R", NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(Double value) { if (Double.IsNegativeInfinity(value)) return "-INF"; if (Double.IsPositiveInfinity(value)) return "INF"; if (IsNegativeZero(value)) { return("-0"); } return value.ToString("R", NumberFormatInfo.InvariantInfo); } /// /// /// [To be supplied.] /// public static string ToString(TimeSpan value) { return new XsdDuration(value).ToString(); } #if !SILVERLIGHT /// /// /// [To be supplied.] /// [Obsolete("Use XmlConvert.ToString() that takes in XmlDateTimeSerializationMode")] public static string ToString(DateTime value) { return ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz"); } /// /// /// [To be supplied.] /// public static string ToString(DateTime value, string format) { return value.ToString(format, DateTimeFormatInfo.InvariantInfo); } #endif /// /// /// [To be supplied.] /// public static string ToString(DateTime value, XmlDateTimeSerializationMode dateTimeOption) { switch(dateTimeOption) { case XmlDateTimeSerializationMode.Local: value = SwitchToLocalTime(value); break; case XmlDateTimeSerializationMode.Utc: value = SwitchToUtcTime(value); break; case XmlDateTimeSerializationMode.Unspecified: value = new DateTime(value.Ticks, DateTimeKind.Unspecified); break; case XmlDateTimeSerializationMode.RoundtripKind: break; default: throw new ArgumentException(Res.GetString(Res.Sch_InvalidDateTimeOption, dateTimeOption, "dateTimeOption")); } XsdDateTime xsdDateTime = new XsdDateTime(value, XsdDateTimeFlags.DateTime); return xsdDateTime.ToString(); } public static string ToString(DateTimeOffset value) { XsdDateTime xsdDateTime = new XsdDateTime(value); return xsdDateTime.ToString(); } public static string ToString(DateTimeOffset value, string format) { return value.ToString( format, DateTimeFormatInfo.InvariantInfo ); } /// /// /// [To be supplied.] /// public static string ToString(Guid value) { return value.ToString(); } /// /// /// [To be supplied.] /// public static Boolean ToBoolean (string s) { s = TrimString(s); if (s == "1" || s == "true" ) return true; if (s == "0" || s == "false") return false; throw new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Boolean")); } #if !SILVERLIGHT internal static Exception TryToBoolean(string s, out Boolean result) { s = TrimString(s); if (s == "0" || s == "false") { result = false; return null; } else if (s == "1" || s == "true") { result = true; return null; } result = false; return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Boolean")); } #endif /// /// /// [To be supplied.] /// public static Char ToChar (string s) { if (s == null) { throw new ArgumentNullException("s"); } if (s.Length != 1) { throw new FormatException(Res.GetString(Res.XmlConvert_NotOneCharString)); } return s[0]; } #if !SILVERLIGHT internal static Exception TryToChar(string s, out Char result) { if (!Char.TryParse(s, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Char")); } return null; } #endif /// /// /// [To be supplied.] /// public static Decimal ToDecimal (string s) { return Decimal.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToDecimal(string s, out Decimal result) { if (!Decimal.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Decimal")); } return null; } internal static Decimal ToInteger (string s) { return Decimal.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } internal static Exception TryToInteger(string s, out Decimal result) { if (!Decimal.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Integer")); } return null; } #endif /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static SByte ToSByte (string s) { return SByte.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToSByte(string s, out SByte result) { if (!SByte.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "SByte")); } return null; } #endif /// /// /// [To be supplied.] /// public static Int16 ToInt16 (string s) { return Int16.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToInt16(string s, out Int16 result) { if (!Int16.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Int16")); } return null; } #endif /// /// /// [To be supplied.] /// public static Int32 ToInt32 (string s) { return Int32.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToInt32(string s, out Int32 result) { if (!Int32.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Int32")); } return null; } #endif /// /// /// [To be supplied.] /// public static Int64 ToInt64 (string s) { return Int64.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToInt64(string s, out Int64 result) { if (!Int64.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Int64")); } return null; } #endif /// /// /// [To be supplied.] /// public static Byte ToByte (string s) { return Byte.Parse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToByte(string s, out Byte result) { if (!Byte.TryParse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Byte")); } return null; } #endif /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static UInt16 ToUInt16 (string s) { return UInt16.Parse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToUInt16(string s, out UInt16 result) { if (!UInt16.TryParse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "UInt16")); } return null; } #endif /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static UInt32 ToUInt32 (string s) { return UInt32.Parse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToUInt32(string s, out UInt32 result) { if (!UInt32.TryParse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "UInt32")); } return null; } #endif /// /// /// [To be supplied.] /// [CLSCompliant(false)] public static UInt64 ToUInt64 (string s) { return UInt64.Parse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); } #if !SILVERLIGHT internal static Exception TryToUInt64(string s, out UInt64 result) { if (!UInt64.TryParse(s, NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "UInt64")); } return null; } #endif /// /// /// [To be supplied.] /// public static Single ToSingle (string s) { s = TrimString(s); if(s == "-INF") return Single.NegativeInfinity; if(s == "INF") return Single.PositiveInfinity; float f = Single.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowExponent, NumberFormatInfo.InvariantInfo); if (f == 0 && s[0] == '-') { return -0f; } return f; } #if !SILVERLIGHT internal static Exception TryToSingle(string s, out Single result) { s = TrimString(s); if (s == "-INF") { result = Single.NegativeInfinity; return null; } else if (s == "INF") { result = Single.PositiveInfinity; return null; } else if (!Single.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowExponent, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Single")); } if (result == 0 && s[0] == '-') { result = -0f; } return null; } #endif /// /// /// [To be supplied.] /// public static Double ToDouble(string s) { s = TrimString(s); if(s == "-INF") return Double.NegativeInfinity; if(s == "INF") return Double.PositiveInfinity; double dVal = Double.Parse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowExponent|NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo); if (dVal == 0 && s[0] == '-') { return -0d; } return dVal; } #if !SILVERLIGHT internal static Exception TryToDouble (string s, out double result) { s = TrimString(s); if (s == "-INF") { result = Double.NegativeInfinity; return null; } else if (s == "INF") { result = Double.PositiveInfinity; return null; } else if (!Double.TryParse(s, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowExponent, NumberFormatInfo.InvariantInfo, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Double")); } if (result == 0 && s[0] == '-') { result = -0d; } return null; } #endif #if !SILVERLIGHT internal static Double ToXPathDouble (Object o) { string str = o as string; if (str != null) { str = TrimString(str); if (str.Length != 0 && str[0] != '+') { double d; if (Double.TryParse(str, NumberStyles.AllowLeadingSign|NumberStyles.AllowDecimalPoint|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out d)) { return d; } } return Double.NaN; } if (o is double) { return (double) o; } if (o is bool) { return ((bool) o) ? 1.0 : 0.0; } try { return Convert.ToDouble(o, NumberFormatInfo.InvariantInfo); } catch ( FormatException ) { } catch ( OverflowException ) { } catch ( ArgumentNullException ) {} return Double.NaN; } internal static String ToXPathString(Object value){ string s = value as string; if ( s != null ) { return s; } else if ( value is double ) { return ((double)value).ToString("R", NumberFormatInfo.InvariantInfo); } else if ( value is bool ) { return (bool)value ? "true" : "false"; } else { return Convert.ToString(value, NumberFormatInfo.InvariantInfo); } } internal static Double XPathRound(Double value) { double temp = Math.Round(value); return (value - temp == 0.5) ? temp + 1 : temp; } #endif /// /// /// [To be supplied.] /// public static TimeSpan ToTimeSpan(string s) { XsdDuration duration; TimeSpan timeSpan; try { duration = new XsdDuration(s); } catch (Exception) { // Remap exception for v1 compatibility throw new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "TimeSpan")); } timeSpan = duration.ToTimeSpan(); return timeSpan; } #if !SILVERLIGHT internal static Exception TryToTimeSpan(string s, out TimeSpan result) { XsdDuration duration; Exception exception; exception = XsdDuration.TryParse(s, out duration); if (exception != null) { result = TimeSpan.MinValue; return exception; } else { return duration.TryToTimeSpan(out result); } } #endif #if !SILVERLIGHT // use AllDateTimeFormats property to access the formats static volatile string[] s_allDateTimeFormats; // NOTE: Do not use this property for reference comparison. It may not be unique. static string[] AllDateTimeFormats { get { if ( s_allDateTimeFormats == null ) { CreateAllDateTimeFormats(); } return s_allDateTimeFormats; } } static void CreateAllDateTimeFormats() { if ( s_allDateTimeFormats == null ) { // no locking; the array is immutable so it's not a problem that it may get initialized more than once s_allDateTimeFormats = new string[] { "yyyy-MM-ddTHH:mm:ss.FFFFFFFzzzzzz", //dateTime "yyyy-MM-ddTHH:mm:ss.FFFFFFF", "yyyy-MM-ddTHH:mm:ss.FFFFFFFZ", "HH:mm:ss.FFFFFFF", //time "HH:mm:ss.FFFFFFFZ", "HH:mm:ss.FFFFFFFzzzzzz", "yyyy-MM-dd", // date "yyyy-MM-ddZ", "yyyy-MM-ddzzzzzz", "yyyy-MM", // yearMonth "yyyy-MMZ", "yyyy-MMzzzzzz", "yyyy", // year "yyyyZ", "yyyyzzzzzz", "--MM-dd", // monthDay "--MM-ddZ", "--MM-ddzzzzzz", "---dd", // day "---ddZ", "---ddzzzzzz", "--MM--", // month "--MM--Z", "--MM--zzzzzz", }; } } /// /// /// [To be supplied.] /// [Obsolete("Use XmlConvert.ToDateTime() that takes in XmlDateTimeSerializationMode")] public static DateTime ToDateTime(string s) { return ToDateTime(s, AllDateTimeFormats); } #endif /// /// /// [To be supplied.] /// public static DateTime ToDateTime(string s, string format) { return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite|DateTimeStyles.AllowTrailingWhite); } /// /// /// [To be supplied.] /// public static DateTime ToDateTime(string s, string[] formats) { return DateTime.ParseExact(s, formats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite|DateTimeStyles.AllowTrailingWhite); } /// /// /// [To be supplied.] /// public static DateTime ToDateTime(string s, XmlDateTimeSerializationMode dateTimeOption) { XsdDateTime xsdDateTime = new XsdDateTime(s, XsdDateTimeFlags.AllXsd); DateTime dt = (DateTime)xsdDateTime; switch (dateTimeOption) { case XmlDateTimeSerializationMode.Local: dt = SwitchToLocalTime(dt); break; case XmlDateTimeSerializationMode.Utc: dt = SwitchToUtcTime(dt); break; case XmlDateTimeSerializationMode.Unspecified: dt = new DateTime(dt.Ticks, DateTimeKind.Unspecified); break; case XmlDateTimeSerializationMode.RoundtripKind: break; default: throw new ArgumentException(Res.GetString(Res.Sch_InvalidDateTimeOption, dateTimeOption, "dateTimeOption")); } return dt; } public static DateTimeOffset ToDateTimeOffset(string s) { if (s == null) { throw new ArgumentNullException("s"); } XsdDateTime xsdDateTime = new XsdDateTime(s, XsdDateTimeFlags.AllXsd); DateTimeOffset dateTimeOffset = (DateTimeOffset)xsdDateTime; return dateTimeOffset; } public static DateTimeOffset ToDateTimeOffset(string s, string format) { if ( s == null ) { throw new ArgumentNullException( "s" ); } return DateTimeOffset.ParseExact( s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite ); } public static DateTimeOffset ToDateTimeOffset(string s, string[] formats) { if ( s == null ) { throw new ArgumentNullException( "s" ); } return DateTimeOffset.ParseExact( s, formats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite ); } /// /// /// [To be supplied.] /// public static Guid ToGuid (string s) { return new Guid(s); } #if !SILVERLIGHT internal static Exception TryToGuid(string s, out Guid result) { Exception exception = null; result = Guid.Empty; try { result = new Guid(s); } catch (ArgumentException) { exception = new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Guid")); } catch (FormatException) { exception = new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Guid")); } return exception; } #endif private static DateTime SwitchToLocalTime(DateTime value) { switch (value.Kind) { case DateTimeKind.Local: return value; case DateTimeKind.Unspecified: return new DateTime(value.Ticks, DateTimeKind.Local); case DateTimeKind.Utc: return value.ToLocalTime(); } return value; } private static DateTime SwitchToUtcTime(DateTime value) { switch (value.Kind) { case DateTimeKind.Utc: return value; case DateTimeKind.Unspecified: return new DateTime(value.Ticks, DateTimeKind.Utc); case DateTimeKind.Local: return value.ToUniversalTime(); } return value; } internal static Uri ToUri(string s) { if (s != null && s.Length > 0) { //string.Empty is a valid uri but not " " s = TrimString(s); if (s.Length == 0 || s.IndexOf("##", StringComparison.Ordinal) != -1) { throw new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Uri")); } } Uri uri; if (!Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri)) { throw new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Uri")); } return uri; } #if !SILVERLIGHT internal static Exception TryToUri(string s, out Uri result) { result = null; if (s != null && s.Length > 0) { //string.Empty is a valid uri but not " " s = TrimString(s); if (s.Length == 0 || s.IndexOf("##", StringComparison.Ordinal) != -1) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Uri")); } } if (!Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out result)) { return new FormatException(Res.GetString(Res.XmlConvert_BadFormat, s, "Uri")); } return null; } #endif // Compares the given character interval and string and returns true if the characters are identical internal static bool StrEqual( char[] chars, int strPos1, int strLen1, string str2 ) { if ( strLen1 != str2.Length ) { return false; } int i = 0; while ( i < strLen1 && chars[strPos1+i] == str2[i] ) { i++; } return i == strLen1; } // XML whitespace characters, http://www.w3.org/TR/REC-xml#NT-S internal static readonly char[] WhitespaceChars = new char[] { ' ', '\t', '\n', '\r' }; // Trim a string using XML whitespace characters internal static string TrimString(string value) { return value.Trim(WhitespaceChars); } // Trim beginning of a string using XML whitespace characters internal static string TrimStringStart(string value) { return value.TrimStart(WhitespaceChars); } // Trim end of a string using XML whitespace characters internal static string TrimStringEnd(string value) { return value.TrimEnd(WhitespaceChars); } // Split a string into a whitespace-separated list of tokens internal static string[] SplitString(string value) { return value.Split(WhitespaceChars, StringSplitOptions.RemoveEmptyEntries); } internal static string[] SplitString(string value, StringSplitOptions splitStringOptions) { return value.Split(WhitespaceChars, splitStringOptions); } internal static bool IsNegativeZero(double value) { // Simple equals function will report that -0 is equal to +0, so compare bits instead if (value == 0 && DoubleToInt64Bits(value) == DoubleToInt64Bits(-0e0)) { return true; } return false; } #if SILVERLIGHT && !SILVERLIGHT_DISABLE_SECURITY [System.Security.SecuritySafeCritical] #endif private static unsafe long DoubleToInt64Bits(double value) { // NOTE: BitConverter.DoubleToInt64Bits is missing in Silverlight return *((long*)&value); } internal static void VerifyCharData(string data, ExceptionType exceptionType) { VerifyCharData(data, exceptionType, exceptionType); } #if SILVERLIGHT internal static void VerifyCharData( string data, ExceptionType invCharExceptionType, ExceptionType invSurrogateExceptionType ) { #else internal static unsafe void VerifyCharData( string data, ExceptionType invCharExceptionType, ExceptionType invSurrogateExceptionType ) { #endif if ( data == null || data.Length == 0 ) { return; } int i = 0; int len = data.Length; for (;;) { #if SILVERLIGHT while (i < len && xmlCharType.IsCharData(data[i])) { #else while ( i < len && ( xmlCharType.charProperties[data[i]] & XmlCharType.fCharData ) != 0 ) { #endif i++; } if ( i == len ) { return; } char ch = data[i]; if ( XmlCharType.IsHighSurrogate( ch ) ) { if ( i + 1 == len ) { throw CreateException( Res.Xml_InvalidSurrogateMissingLowChar, invSurrogateExceptionType, 0, i + 1 ); } ch = data[i+1]; if ( XmlCharType.IsLowSurrogate( ch ) ) { i += 2; continue; } else { throw CreateInvalidSurrogatePairException( data[i+1], data[i], invSurrogateExceptionType, 0, i + 1 ); } } throw CreateInvalidCharException( data, i, invCharExceptionType ); } } #if SILVERLIGHT internal static void VerifyCharData(char[] data, int offset, int len, ExceptionType exceptionType) { #else internal static unsafe void VerifyCharData( char[] data, int offset, int len, ExceptionType exceptionType ) { #endif if ( data == null || len == 0 ) { return; } int i = offset; int endPos = offset + len; for (;;) { #if SILVERLIGHT while ( i < endPos && xmlCharType.IsCharData(data[i])) { #else while ( i < endPos && ( xmlCharType.charProperties[data[i]] & XmlCharType.fCharData ) != 0 ) { #endif i++; } if ( i == endPos ) { return; } char ch = data[i]; if ( XmlCharType.IsHighSurrogate( ch ) ) { if ( i + 1 == endPos ) { throw CreateException(Res.Xml_InvalidSurrogateMissingLowChar, exceptionType, 0, offset - i + 1); } ch = data[i+1]; if ( XmlCharType.IsLowSurrogate( ch ) ) { i += 2; continue; } else { throw CreateInvalidSurrogatePairException(data[i + 1], data[i], exceptionType, 0, offset - i + 1); } } throw CreateInvalidCharException( data, len, i, exceptionType ); } } #if !SILVERLIGHT internal static string EscapeValueForDebuggerDisplay( string value ) { StringBuilder sb = null; int i = 0; int start = 0; while ( i < value.Length ) { char ch = value[i]; if ( (int)ch < 0x20 || ch == '"' ) { if ( sb == null ) { sb = new StringBuilder( value.Length + 4 ); } if ( i - start > 0 ) { sb.Append( value, start, i - start ); } start = i + 1; switch ( ch ) { case '"': sb.Append( "\\\"" ); break; case '\r': sb.Append( "\\r" ); break; case '\n': sb.Append( "\\n" ); break; case '\t': sb.Append( "\\t" ); break; default: sb.Append( ch ); break; } } i++; } if ( sb == null ) { return value; } if ( i - start > 0 ) { sb.Append( value, start, i - start ); } return sb.ToString(); } #endif internal static Exception CreateException( string res, ExceptionType exceptionType ) { return CreateException( res, exceptionType, 0, 0 ); } internal static Exception CreateException( string res, ExceptionType exceptionType, int lineNo, int linePos ) { switch ( exceptionType ) { case ExceptionType.ArgumentException: return new ArgumentException( Res.GetString( res ) ); case ExceptionType.XmlException: default: return new XmlException( res, string.Empty, lineNo, linePos ); } } internal static Exception CreateException( string res, string arg, ExceptionType exceptionType ) { return CreateException( res, arg, exceptionType, 0, 0 ); } internal static Exception CreateException( string res, string arg, ExceptionType exceptionType, int lineNo, int linePos ) { switch ( exceptionType ) { case ExceptionType.ArgumentException: return new ArgumentException( Res.GetString( res, arg ) ); case ExceptionType.XmlException: default: return new XmlException( res, arg, lineNo, linePos ); } } internal static Exception CreateException( string res, string[] args, ExceptionType exceptionType ) { return CreateException(res, args, exceptionType, 0, 0); } internal static Exception CreateException(string res, string[] args, ExceptionType exceptionType, int lineNo, int linePos) { switch ( exceptionType ) { case ExceptionType.ArgumentException: return new ArgumentException( Res.GetString( res, args ) ); case ExceptionType.XmlException: default: return new XmlException( res, args, lineNo, linePos ); } } internal static Exception CreateInvalidSurrogatePairException( char low, char hi ) { return CreateInvalidSurrogatePairException( low, hi, ExceptionType.ArgumentException ); } internal static Exception CreateInvalidSurrogatePairException(char low, char hi, ExceptionType exceptionType) { return CreateInvalidSurrogatePairException(low, hi, exceptionType, 0, 0); } internal static Exception CreateInvalidSurrogatePairException( char low, char hi, ExceptionType exceptionType, int lineNo, int linePos ) { string[] args = new string[] { ((uint)hi).ToString( "X", CultureInfo.InvariantCulture ), ((uint)low).ToString( "X", CultureInfo.InvariantCulture ) } ; return CreateException( Res.Xml_InvalidSurrogatePairWithArgs, args, exceptionType, lineNo, linePos ); } internal static Exception CreateInvalidHighSurrogateCharException( char hi ) { return CreateInvalidHighSurrogateCharException( hi, ExceptionType.ArgumentException ); } internal static Exception CreateInvalidHighSurrogateCharException( char hi, ExceptionType exceptionType ) { return CreateInvalidHighSurrogateCharException( hi, exceptionType, 0, 0); } internal static Exception CreateInvalidHighSurrogateCharException(char hi, ExceptionType exceptionType, int lineNo, int linePos) { return CreateException( Res.Xml_InvalidSurrogateHighChar, ((uint)hi).ToString( "X", CultureInfo.InvariantCulture ), exceptionType, lineNo, linePos ); } internal static Exception CreateInvalidCharException(char[] data, int length, int invCharPos) { return CreateInvalidCharException(data, length, invCharPos, ExceptionType.ArgumentException); } internal static Exception CreateInvalidCharException(char[] data, int length, int invCharPos, ExceptionType exceptionType) { return CreateException(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs(data, length, invCharPos), exceptionType, 0, invCharPos + 1); } internal static Exception CreateInvalidCharException( string data, int invCharPos ) { return CreateInvalidCharException( data, invCharPos, ExceptionType.ArgumentException ); } internal static Exception CreateInvalidCharException( string data, int invCharPos, ExceptionType exceptionType ) { return CreateException(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs(data, invCharPos), exceptionType, 0, invCharPos + 1); } internal static Exception CreateInvalidCharException( char invChar, char nextChar ) { return CreateInvalidCharException(invChar, nextChar, ExceptionType.ArgumentException); } internal static Exception CreateInvalidCharException( char invChar, char nextChar, ExceptionType exceptionType) { return CreateException(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs(invChar, nextChar), exceptionType); } internal static Exception CreateInvalidNameCharException(string name, int index, ExceptionType exceptionType) { return CreateException(index == 0 ? Res.Xml_BadStartNameChar : Res.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, index), exceptionType, 0, index + 1); } internal static ArgumentException CreateInvalidNameArgumentException(string name, string argumentName) { return ( name == null ) ? new ArgumentNullException( argumentName ) : new ArgumentException( Res.GetString( Res.Xml_EmptyName ), argumentName ); } } }