Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XsltLibrary.cs / 1 / XsltLibrary.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.Collections.Specialized; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Xml.XPath; using System.Xml.Xsl.Xslt; using System.ComponentModel; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; // List of all XPath/XSLT runtime methods internal static class XsltMethods { // Formatting error messages public static readonly MethodInfo FormatMessage = GetMethod(typeof(XsltLibrary), "FormatMessage"); // Runtime type checks and casts public static readonly MethodInfo EnsureNodeSet = GetMethod(typeof(XsltConvert), "EnsureNodeSet" , typeof(IList)); // Comparisons public static readonly MethodInfo EqualityOperator = GetMethod(typeof(XsltLibrary), "EqualityOperator"); public static readonly MethodInfo RelationalOperator = GetMethod(typeof(XsltLibrary), "RelationalOperator"); // XPath functions public static readonly MethodInfo StartsWith = GetMethod(typeof(XsltFunctions), "StartsWith"); public static readonly MethodInfo Contains = GetMethod(typeof(XsltFunctions), "Contains"); public static readonly MethodInfo SubstringBefore = GetMethod(typeof(XsltFunctions), "SubstringBefore"); public static readonly MethodInfo SubstringAfter = GetMethod(typeof(XsltFunctions), "SubstringAfter"); public static readonly MethodInfo Substring2 = GetMethod(typeof(XsltFunctions), "Substring", typeof(string), typeof(double)); public static readonly MethodInfo Substring3 = GetMethod(typeof(XsltFunctions), "Substring", typeof(string), typeof(double), typeof(double)); public static readonly MethodInfo NormalizeSpace = GetMethod(typeof(XsltFunctions), "NormalizeSpace"); public static readonly MethodInfo Translate = GetMethod(typeof(XsltFunctions), "Translate"); public static readonly MethodInfo Lang = GetMethod(typeof(XsltFunctions), "Lang"); public static readonly MethodInfo Floor = GetMethod(typeof(Math) , "Floor" , typeof(double)); public static readonly MethodInfo Ceiling = GetMethod(typeof(Math) , "Ceiling", typeof(double)); public static readonly MethodInfo Round = GetMethod(typeof(XsltFunctions), "Round"); // XSLT functions and helper methods (static) public static readonly MethodInfo SystemProperty = GetMethod(typeof(XsltFunctions), "SystemProperty"); public static readonly MethodInfo BaseUri = GetMethod(typeof(XsltFunctions), "BaseUri"); public static readonly MethodInfo OuterXml = GetMethod(typeof(XsltFunctions), "OuterXml"); public static readonly MethodInfo OnCurrentNodeChanged = GetMethod(typeof(XmlQueryRuntime), "OnCurrentNodeChanged"); // MSXML extension functions public static readonly MethodInfo MSFormatDateTime = GetMethod(typeof(XsltFunctions), "MSFormatDateTime"); public static readonly MethodInfo MSStringCompare = GetMethod(typeof(XsltFunctions), "MSStringCompare"); public static readonly MethodInfo MSUtc = GetMethod(typeof(XsltFunctions), "MSUtc" ); public static readonly MethodInfo MSNumber = GetMethod(typeof(XsltFunctions), "MSNumber" ); public static readonly MethodInfo MSLocalName = GetMethod(typeof(XsltFunctions), "MSLocalName" ); public static readonly MethodInfo MSNamespaceUri = GetMethod(typeof(XsltFunctions), "MSNamespaceUri" ); // EXSLT functions public static readonly MethodInfo EXslObjectType = GetMethod(typeof(XsltFunctions), "EXslObjectType"); // XSLT functions and helper methods (non-static) public static readonly MethodInfo CheckScriptNamespace = GetMethod(typeof(XsltLibrary), "CheckScriptNamespace"); public static readonly MethodInfo FunctionAvailable = GetMethod(typeof(XsltLibrary), "FunctionAvailable"); public static readonly MethodInfo ElementAvailable = GetMethod(typeof(XsltLibrary), "ElementAvailable"); public static readonly MethodInfo RegisterDecimalFormat = GetMethod(typeof(XsltLibrary), "RegisterDecimalFormat"); public static readonly MethodInfo RegisterDecimalFormatter = GetMethod(typeof(XsltLibrary), "RegisterDecimalFormatter"); public static readonly MethodInfo FormatNumberStatic = GetMethod(typeof(XsltLibrary), "FormatNumberStatic"); public static readonly MethodInfo FormatNumberDynamic = GetMethod(typeof(XsltLibrary), "FormatNumberDynamic"); public static readonly MethodInfo IsSameNodeSort = GetMethod(typeof(XsltLibrary), "IsSameNodeSort"); public static readonly MethodInfo LangToLcid = GetMethod(typeof(XsltLibrary), "LangToLcid"); public static readonly MethodInfo NumberFormat = GetMethod(typeof(XsltLibrary), "NumberFormat"); public static MethodInfo GetMethod(Type className, string methName) { MethodInfo methInfo = className.GetMethod(methName); Debug.Assert(methInfo != null, "Method " + className.Name + "." + methName + " not found"); return methInfo; } public static MethodInfo GetMethod(Type className, string methName, params Type[] args) { MethodInfo methInfo = className.GetMethod(methName, args); Debug.Assert(methInfo != null, "Method " + className.Name + "." + methName + " not found"); return methInfo; } } [EditorBrowsable(EditorBrowsableState.Never)] public sealed class XsltLibrary { private XmlQueryRuntime runtime; private HybridDictionary functionsAvail; private DecimalFormats decimalFormats; private List decimalFormatters; internal XsltLibrary(XmlQueryRuntime runtime) { this.runtime = runtime; } public string FormatMessage(string res, IList args) { string[] arr = new string[args.Count]; for (int i = 0; i < arr.Length; i++) arr[i] = args[i]; return XslTransformException.CreateMessage(res, arr); } public int CheckScriptNamespace(string nsUri) { // Check that extension and script namespaces do not clash if (runtime.ExternalContext.GetLateBoundObject(nsUri) != null) { throw new XslTransformException(Res.Xslt_ScriptAndExtensionClash, nsUri); } return 0; // have to return something } // Spec: http://www.w3.org/TR/xslt#function-element-available public bool ElementAvailable(XmlQualifiedName name) { return QilGenerator.IsElementAvailable(name); } // Spec: http://www.w3.org/TR/xslt#function-function-available public bool FunctionAvailable(XmlQualifiedName name) { if (functionsAvail == null) { functionsAvail = new HybridDictionary(); } else { object obj = functionsAvail[name]; if (obj != null) { return (bool)obj; } } bool result = FunctionAvailableHelper(name); functionsAvail[name] = result; return result; } private bool FunctionAvailableHelper(XmlQualifiedName name) { // Is this an XPath or an XSLT function? if (QilGenerator.IsFunctionAvailable(name.Name, name.Namespace)) { return true; } // Script blocks and extension objects cannot implement neither null nor XSLT namespace if (name.Namespace.Length == 0 || name.Namespace == XmlReservedNs.NsXslt) { return false; } // Is this an extension object function? if (runtime.ExternalContext.LateBoundFunctionExists(name.Name, name.Namespace)) { return true; } // Is this a script function? return runtime.EarlyBoundFunctionExists(name.Name, name.Namespace); } public int RegisterDecimalFormat(XmlQualifiedName name, string infinitySymbol, string nanSymbol, string characters) { if (decimalFormats == null) { decimalFormats = new DecimalFormats(); } DecimalFormatDecl format = new DecimalFormatDecl(name, infinitySymbol, nanSymbol, characters); decimalFormats.Add(format); return 0; // have to return something } private DecimalFormatter CreateDecimalFormatter(string formatPicture, string infinitySymbol, string nanSymbol, string characters) { // NumberFormatInfo info = new NumberFormatInfo(); info.NumberDecimalSeparator = char.ToString(characters[0]); info.NumberGroupSeparator = char.ToString(characters[1]); info.PositiveInfinitySymbol = infinitySymbol; info.NegativeSign = char.ToString(characters[7]); info.NaNSymbol = nanSymbol; info.PercentSymbol = char.ToString(characters[2]); info.PerMilleSymbol = char.ToString(characters[3]); info.NegativeInfinitySymbol = info.NegativeSign + info.PositiveInfinitySymbol; DecimalFormat formatInfo = new DecimalFormat(info, characters[5], characters[4], characters[6]); return new DecimalFormatter(formatPicture, formatInfo); } public double RegisterDecimalFormatter(string formatPicture, string infinitySymbol, string nanSymbol, string characters) { if (decimalFormatters == null) { decimalFormatters = new List (); } decimalFormatters.Add(CreateDecimalFormatter(formatPicture, infinitySymbol, nanSymbol, characters)); return decimalFormatters.Count - 1; } public string FormatNumberStatic(double value, double decimalFormatterIndex) { int idx = (int)decimalFormatterIndex; Debug.Assert(0 <= idx && idx < decimalFormatters.Count, "Value of decimalFormatterIndex is out of range"); return decimalFormatters[idx].Format(value); } public string FormatNumberDynamic(double value, string formatPicture, XmlQualifiedName decimalFormatName, string errorMessageName) { DecimalFormatDecl format; if (decimalFormats != null && decimalFormats.Contains(decimalFormatName)) { format = decimalFormats[decimalFormatName]; } else { if (decimalFormatName != DecimalFormatDecl.Default.Name) { throw new XslTransformException(Res.Xslt_NoDecimalFormat, errorMessageName); } format = DecimalFormatDecl.Default; } DecimalFormatter formatter = CreateDecimalFormatter(formatPicture, format.InfinitySymbol, format.NanSymbol, new string(format.Characters)); return formatter.Format(value); } public string NumberFormat(IList value, string formatString, double lang, string letterValue, string groupingSeparator, double groupingSize) { // NumberFormatter formatter = new NumberFormatter(formatString, (int)lang, letterValue, groupingSeparator, (int)groupingSize); return formatter.FormatSequence(value); } internal const int InvariantCultureLcid = 0x007f; public int LangToLcid(string lang, bool forwardCompatibility) { return LangToLcidInternal(lang, forwardCompatibility, null); } internal static int LangToLcidInternal(string lang, bool forwardCompatibility, IErrorHelper errorHelper) { int lcid = InvariantCultureLcid; if (lang != null) { // The value of the 'lang' attribute must be a non-empty nmtoken if (lang.Length == 0) { if (!forwardCompatibility) { if (errorHelper != null) { errorHelper.ReportError(/*[XT_032]*/Res.Xslt_InvalidAttrValue, "lang", lang); } else { throw new XslTransformException(Res.Xslt_InvalidAttrValue, "lang", lang); } } } else { // Check if lang is a supported culture name try { lcid = new CultureInfo(lang).LCID; } catch (System.ArgumentException) { if (!forwardCompatibility) { if (errorHelper != null) { errorHelper.ReportError(/*[XT_033]*/Res.Xslt_InvalidLanguage, lang); } else { throw new XslTransformException(Res.Xslt_InvalidLanguage, lang); } } } } } return lcid; } #region Comparisons internal enum ComparisonOperator { /*Equality */ Eq, Ne, /*Relational*/ Lt, Le, Gt, Ge, } // Returns TypeCode of the given atomic value private static TypeCode GetTypeCode(XPathItem item) { // Faster implementation of Type.GetTypeCode(item.ValueType); Debug.Assert(!item.IsNode, "Atomic value expected"); Type itemType = item.ValueType; if (itemType == XsltConvert.StringType) { return TypeCode.String; } else if (itemType == XsltConvert.DoubleType) { return TypeCode.Double; } else { Debug.Assert(itemType == XsltConvert.BooleanType, "Unexpected type of atomic value " + itemType.ToString()); return TypeCode.Boolean; } } // Returns weakest of the two given TypeCodes, String > Double > Boolean private static TypeCode WeakestTypeCode(TypeCode typeCode1, TypeCode typeCode2) { Debug.Assert(TypeCode.Boolean < TypeCode.Double && TypeCode.Double < TypeCode.String, "Cannot use the smallest TypeCode as a weakest one"); return typeCode1 < typeCode2 ? typeCode1 : typeCode2; } private static bool CompareNumbers(ComparisonOperator op, double left, double right) { switch (op) { case ComparisonOperator.Eq: return left == right; case ComparisonOperator.Ne: return left != right; case ComparisonOperator.Lt: return left < right; case ComparisonOperator.Le: return left <= right; case ComparisonOperator.Gt: return left > right; default: return left >= right; } } private static bool CompareValues(ComparisonOperator op, XPathItem left, XPathItem right, TypeCode compType) { if (compType == TypeCode.Double) { return CompareNumbers(op, XsltConvert.ToDouble(left), XsltConvert.ToDouble(right)); } else { Debug.Assert(op == ComparisonOperator.Eq || op == ComparisonOperator.Ne); if (compType == TypeCode.String) { return (XsltConvert.ToString(left) == XsltConvert.ToString(right)) == (op == ComparisonOperator.Eq); } else { Debug.Assert(compType == TypeCode.Boolean); return (XsltConvert.ToBoolean(left) == XsltConvert.ToBoolean(right)) == (op == ComparisonOperator.Eq); } } } private static bool CompareNodeSetAndValue(ComparisonOperator op, IList nodeset, XPathItem val, TypeCode compType) { Debug.Assert(compType == TypeCode.Boolean || compType == TypeCode.Double || compType == TypeCode.String); if (compType == TypeCode.Boolean) { // Cast nodeset to boolean type, then take its ordinal number return CompareNumbers(op, (nodeset.Count != 0) ? 1 : 0, XsltConvert.ToBoolean(val) ? 1 : 0); } else { int length = nodeset.Count; for (int idx = 0; idx < length; idx++) { if (CompareValues(op, nodeset[idx], val, compType)) { return true; } } return false; } } private static bool CompareNodeSetAndNodeSet(ComparisonOperator op, IList left, IList right, TypeCode compType) { int leftLen = left.Count; int rightLen = right.Count; for (int leftIdx = 0; leftIdx < leftLen; leftIdx++) { for (int rightIdx = 0; rightIdx < rightLen; rightIdx++) { if (CompareValues(op, left[leftIdx], right[rightIdx], compType)) { return true; } } } return false; } public bool EqualityOperator(double opCode, IList left, IList right) { ComparisonOperator op = (ComparisonOperator)opCode; Debug.Assert(op == ComparisonOperator.Eq || op == ComparisonOperator.Ne); CheckXsltValue(left); CheckXsltValue(right); if (IsNodeSetOrRtf(left)) { if (IsNodeSetOrRtf(right)) { // Both left and right are node-sets return CompareNodeSetAndNodeSet(op, ToNodeSetOrRtf(left), ToNodeSetOrRtf(right), TypeCode.String); } else { // left is a node-set, right is an atomic value XPathItem rightItem = right[0]; return CompareNodeSetAndValue(op, ToNodeSetOrRtf(left), rightItem, GetTypeCode(rightItem)); } } else if (IsNodeSetOrRtf(right)) { // left is an atomic value, right is a node-set XPathItem leftItem = left[0]; // Swap operands: left op right -> right op left return CompareNodeSetAndValue(op, ToNodeSetOrRtf(right), leftItem, GetTypeCode(leftItem)); } else { // Both left and right are atomic values XPathItem leftItem = left[0]; XPathItem rightItem = right[0]; return CompareValues(op, leftItem, rightItem, WeakestTypeCode(GetTypeCode(leftItem), GetTypeCode(rightItem))); } } // Inverts relational operator in order to swap operands of the comparison private static ComparisonOperator InvertOperator(ComparisonOperator op) { switch (op) { case ComparisonOperator.Lt: return ComparisonOperator.Gt; case ComparisonOperator.Le: return ComparisonOperator.Ge; case ComparisonOperator.Gt: return ComparisonOperator.Lt; case ComparisonOperator.Ge: return ComparisonOperator.Le; default: return op; } } public bool RelationalOperator(double opCode, IList left, IList right) { ComparisonOperator op = (ComparisonOperator)opCode; Debug.Assert(ComparisonOperator.Lt <= op && op <= ComparisonOperator.Ge); CheckXsltValue(left); CheckXsltValue(right); if (IsNodeSetOrRtf(left)) { if (IsNodeSetOrRtf(right)) { // Both left and right are node-sets return CompareNodeSetAndNodeSet(op, ToNodeSetOrRtf(left), ToNodeSetOrRtf(right), TypeCode.Double); } else { // left is a node-set, right is an atomic value XPathItem rightItem = right[0]; return CompareNodeSetAndValue(op, ToNodeSetOrRtf(left), rightItem, WeakestTypeCode(GetTypeCode(rightItem), TypeCode.Double)); } } else if (IsNodeSetOrRtf(right)) { // left is an atomic value, right is a node-set XPathItem leftItem = left[0]; // Swap operands: left op right -> right InvertOperator(op) left op = InvertOperator(op); return CompareNodeSetAndValue(op, ToNodeSetOrRtf(right), leftItem, WeakestTypeCode(GetTypeCode(leftItem), TypeCode.Double)); } else { // Both left and right are atomic values XPathItem leftItem = left[0]; XPathItem rightItem = right[0]; return CompareValues(op, leftItem, rightItem, TypeCode.Double); } } #endregion // nav1 and nav2 are assumed to belong to the same document public bool IsSameNodeSort(XPathNavigator nav1, XPathNavigator nav2) { Debug.Assert(XPathNodeType.SignificantWhitespace == XPathNodeType.Text + 1); Debug.Assert(XPathNodeType.Whitespace == XPathNodeType.Text + 2); XPathNodeType nt1 = nav1.NodeType; XPathNodeType nt2 = nav2.NodeType; // If one of nodes is a text node, the other one must also be a text node if (XPathNodeType.Text <= nt1 && nt1 <= XPathNodeType.Whitespace) { return XPathNodeType.Text <= nt2 && nt2 <= XPathNodeType.Whitespace; } // Otherwise nodes must have the same node kind, the same local name, and the same namespace URI Debug.Assert((object)nav1.NameTable == (object)nav2.NameTable, "Ref.Equal cannot be used if navigators have different name tables"); return nt1 == nt2 && Ref.Equal(nav1.LocalName, nav2.LocalName) && Ref.Equal(nav1.NamespaceURI, nav2.NamespaceURI); } //------------------------------------------------ // Helper methods //------------------------------------------------ [Conditional("DEBUG")] internal static void CheckXsltValue(XPathItem item) { CheckXsltValue(new XmlQueryItemSequence(item)); } [Conditional("DEBUG")] internal static void CheckXsltValue(IList val) { // IsDocOrderDistinct is not always set to true even if the node-set is ordered // Debug.Assert(val.Count <= 1 || val.IsDocOrderDistinct, "All node-sets must be ordered"); if (val.Count == 1) { XsltFunctions.EXslObjectType(val); } else { // Every item must be a node, but for performance reasons we check only // the first two and the last two items int count = val.Count; for (int idx = 0; idx < count; idx++) { if (!val[idx].IsNode) { Debug.Fail("Invalid XSLT value"); break; } if (idx == 1) { idx += Math.Max(count - 4, 0); } } } } private static bool IsNodeSetOrRtf(IList val) { CheckXsltValue(val); if (val.Count == 1) { return val[0].IsNode; } return true; } private static IList ToNodeSetOrRtf(IList val) { return XmlILStorageConverter.ItemsToNavigators(val); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.Collections.Specialized; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Xml.XPath; using System.Xml.Xsl.Xslt; using System.ComponentModel; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; // List of all XPath/XSLT runtime methods internal static class XsltMethods { // Formatting error messages public static readonly MethodInfo FormatMessage = GetMethod(typeof(XsltLibrary), "FormatMessage"); // Runtime type checks and casts public static readonly MethodInfo EnsureNodeSet = GetMethod(typeof(XsltConvert), "EnsureNodeSet" , typeof(IList)); // Comparisons public static readonly MethodInfo EqualityOperator = GetMethod(typeof(XsltLibrary), "EqualityOperator"); public static readonly MethodInfo RelationalOperator = GetMethod(typeof(XsltLibrary), "RelationalOperator"); // XPath functions public static readonly MethodInfo StartsWith = GetMethod(typeof(XsltFunctions), "StartsWith"); public static readonly MethodInfo Contains = GetMethod(typeof(XsltFunctions), "Contains"); public static readonly MethodInfo SubstringBefore = GetMethod(typeof(XsltFunctions), "SubstringBefore"); public static readonly MethodInfo SubstringAfter = GetMethod(typeof(XsltFunctions), "SubstringAfter"); public static readonly MethodInfo Substring2 = GetMethod(typeof(XsltFunctions), "Substring", typeof(string), typeof(double)); public static readonly MethodInfo Substring3 = GetMethod(typeof(XsltFunctions), "Substring", typeof(string), typeof(double), typeof(double)); public static readonly MethodInfo NormalizeSpace = GetMethod(typeof(XsltFunctions), "NormalizeSpace"); public static readonly MethodInfo Translate = GetMethod(typeof(XsltFunctions), "Translate"); public static readonly MethodInfo Lang = GetMethod(typeof(XsltFunctions), "Lang"); public static readonly MethodInfo Floor = GetMethod(typeof(Math) , "Floor" , typeof(double)); public static readonly MethodInfo Ceiling = GetMethod(typeof(Math) , "Ceiling", typeof(double)); public static readonly MethodInfo Round = GetMethod(typeof(XsltFunctions), "Round"); // XSLT functions and helper methods (static) public static readonly MethodInfo SystemProperty = GetMethod(typeof(XsltFunctions), "SystemProperty"); public static readonly MethodInfo BaseUri = GetMethod(typeof(XsltFunctions), "BaseUri"); public static readonly MethodInfo OuterXml = GetMethod(typeof(XsltFunctions), "OuterXml"); public static readonly MethodInfo OnCurrentNodeChanged = GetMethod(typeof(XmlQueryRuntime), "OnCurrentNodeChanged"); // MSXML extension functions public static readonly MethodInfo MSFormatDateTime = GetMethod(typeof(XsltFunctions), "MSFormatDateTime"); public static readonly MethodInfo MSStringCompare = GetMethod(typeof(XsltFunctions), "MSStringCompare"); public static readonly MethodInfo MSUtc = GetMethod(typeof(XsltFunctions), "MSUtc" ); public static readonly MethodInfo MSNumber = GetMethod(typeof(XsltFunctions), "MSNumber" ); public static readonly MethodInfo MSLocalName = GetMethod(typeof(XsltFunctions), "MSLocalName" ); public static readonly MethodInfo MSNamespaceUri = GetMethod(typeof(XsltFunctions), "MSNamespaceUri" ); // EXSLT functions public static readonly MethodInfo EXslObjectType = GetMethod(typeof(XsltFunctions), "EXslObjectType"); // XSLT functions and helper methods (non-static) public static readonly MethodInfo CheckScriptNamespace = GetMethod(typeof(XsltLibrary), "CheckScriptNamespace"); public static readonly MethodInfo FunctionAvailable = GetMethod(typeof(XsltLibrary), "FunctionAvailable"); public static readonly MethodInfo ElementAvailable = GetMethod(typeof(XsltLibrary), "ElementAvailable"); public static readonly MethodInfo RegisterDecimalFormat = GetMethod(typeof(XsltLibrary), "RegisterDecimalFormat"); public static readonly MethodInfo RegisterDecimalFormatter = GetMethod(typeof(XsltLibrary), "RegisterDecimalFormatter"); public static readonly MethodInfo FormatNumberStatic = GetMethod(typeof(XsltLibrary), "FormatNumberStatic"); public static readonly MethodInfo FormatNumberDynamic = GetMethod(typeof(XsltLibrary), "FormatNumberDynamic"); public static readonly MethodInfo IsSameNodeSort = GetMethod(typeof(XsltLibrary), "IsSameNodeSort"); public static readonly MethodInfo LangToLcid = GetMethod(typeof(XsltLibrary), "LangToLcid"); public static readonly MethodInfo NumberFormat = GetMethod(typeof(XsltLibrary), "NumberFormat"); public static MethodInfo GetMethod(Type className, string methName) { MethodInfo methInfo = className.GetMethod(methName); Debug.Assert(methInfo != null, "Method " + className.Name + "." + methName + " not found"); return methInfo; } public static MethodInfo GetMethod(Type className, string methName, params Type[] args) { MethodInfo methInfo = className.GetMethod(methName, args); Debug.Assert(methInfo != null, "Method " + className.Name + "." + methName + " not found"); return methInfo; } } [EditorBrowsable(EditorBrowsableState.Never)] public sealed class XsltLibrary { private XmlQueryRuntime runtime; private HybridDictionary functionsAvail; private DecimalFormats decimalFormats; private List decimalFormatters; internal XsltLibrary(XmlQueryRuntime runtime) { this.runtime = runtime; } public string FormatMessage(string res, IList args) { string[] arr = new string[args.Count]; for (int i = 0; i < arr.Length; i++) arr[i] = args[i]; return XslTransformException.CreateMessage(res, arr); } public int CheckScriptNamespace(string nsUri) { // Check that extension and script namespaces do not clash if (runtime.ExternalContext.GetLateBoundObject(nsUri) != null) { throw new XslTransformException(Res.Xslt_ScriptAndExtensionClash, nsUri); } return 0; // have to return something } // Spec: http://www.w3.org/TR/xslt#function-element-available public bool ElementAvailable(XmlQualifiedName name) { return QilGenerator.IsElementAvailable(name); } // Spec: http://www.w3.org/TR/xslt#function-function-available public bool FunctionAvailable(XmlQualifiedName name) { if (functionsAvail == null) { functionsAvail = new HybridDictionary(); } else { object obj = functionsAvail[name]; if (obj != null) { return (bool)obj; } } bool result = FunctionAvailableHelper(name); functionsAvail[name] = result; return result; } private bool FunctionAvailableHelper(XmlQualifiedName name) { // Is this an XPath or an XSLT function? if (QilGenerator.IsFunctionAvailable(name.Name, name.Namespace)) { return true; } // Script blocks and extension objects cannot implement neither null nor XSLT namespace if (name.Namespace.Length == 0 || name.Namespace == XmlReservedNs.NsXslt) { return false; } // Is this an extension object function? if (runtime.ExternalContext.LateBoundFunctionExists(name.Name, name.Namespace)) { return true; } // Is this a script function? return runtime.EarlyBoundFunctionExists(name.Name, name.Namespace); } public int RegisterDecimalFormat(XmlQualifiedName name, string infinitySymbol, string nanSymbol, string characters) { if (decimalFormats == null) { decimalFormats = new DecimalFormats(); } DecimalFormatDecl format = new DecimalFormatDecl(name, infinitySymbol, nanSymbol, characters); decimalFormats.Add(format); return 0; // have to return something } private DecimalFormatter CreateDecimalFormatter(string formatPicture, string infinitySymbol, string nanSymbol, string characters) { // NumberFormatInfo info = new NumberFormatInfo(); info.NumberDecimalSeparator = char.ToString(characters[0]); info.NumberGroupSeparator = char.ToString(characters[1]); info.PositiveInfinitySymbol = infinitySymbol; info.NegativeSign = char.ToString(characters[7]); info.NaNSymbol = nanSymbol; info.PercentSymbol = char.ToString(characters[2]); info.PerMilleSymbol = char.ToString(characters[3]); info.NegativeInfinitySymbol = info.NegativeSign + info.PositiveInfinitySymbol; DecimalFormat formatInfo = new DecimalFormat(info, characters[5], characters[4], characters[6]); return new DecimalFormatter(formatPicture, formatInfo); } public double RegisterDecimalFormatter(string formatPicture, string infinitySymbol, string nanSymbol, string characters) { if (decimalFormatters == null) { decimalFormatters = new List (); } decimalFormatters.Add(CreateDecimalFormatter(formatPicture, infinitySymbol, nanSymbol, characters)); return decimalFormatters.Count - 1; } public string FormatNumberStatic(double value, double decimalFormatterIndex) { int idx = (int)decimalFormatterIndex; Debug.Assert(0 <= idx && idx < decimalFormatters.Count, "Value of decimalFormatterIndex is out of range"); return decimalFormatters[idx].Format(value); } public string FormatNumberDynamic(double value, string formatPicture, XmlQualifiedName decimalFormatName, string errorMessageName) { DecimalFormatDecl format; if (decimalFormats != null && decimalFormats.Contains(decimalFormatName)) { format = decimalFormats[decimalFormatName]; } else { if (decimalFormatName != DecimalFormatDecl.Default.Name) { throw new XslTransformException(Res.Xslt_NoDecimalFormat, errorMessageName); } format = DecimalFormatDecl.Default; } DecimalFormatter formatter = CreateDecimalFormatter(formatPicture, format.InfinitySymbol, format.NanSymbol, new string(format.Characters)); return formatter.Format(value); } public string NumberFormat(IList value, string formatString, double lang, string letterValue, string groupingSeparator, double groupingSize) { // NumberFormatter formatter = new NumberFormatter(formatString, (int)lang, letterValue, groupingSeparator, (int)groupingSize); return formatter.FormatSequence(value); } internal const int InvariantCultureLcid = 0x007f; public int LangToLcid(string lang, bool forwardCompatibility) { return LangToLcidInternal(lang, forwardCompatibility, null); } internal static int LangToLcidInternal(string lang, bool forwardCompatibility, IErrorHelper errorHelper) { int lcid = InvariantCultureLcid; if (lang != null) { // The value of the 'lang' attribute must be a non-empty nmtoken if (lang.Length == 0) { if (!forwardCompatibility) { if (errorHelper != null) { errorHelper.ReportError(/*[XT_032]*/Res.Xslt_InvalidAttrValue, "lang", lang); } else { throw new XslTransformException(Res.Xslt_InvalidAttrValue, "lang", lang); } } } else { // Check if lang is a supported culture name try { lcid = new CultureInfo(lang).LCID; } catch (System.ArgumentException) { if (!forwardCompatibility) { if (errorHelper != null) { errorHelper.ReportError(/*[XT_033]*/Res.Xslt_InvalidLanguage, lang); } else { throw new XslTransformException(Res.Xslt_InvalidLanguage, lang); } } } } } return lcid; } #region Comparisons internal enum ComparisonOperator { /*Equality */ Eq, Ne, /*Relational*/ Lt, Le, Gt, Ge, } // Returns TypeCode of the given atomic value private static TypeCode GetTypeCode(XPathItem item) { // Faster implementation of Type.GetTypeCode(item.ValueType); Debug.Assert(!item.IsNode, "Atomic value expected"); Type itemType = item.ValueType; if (itemType == XsltConvert.StringType) { return TypeCode.String; } else if (itemType == XsltConvert.DoubleType) { return TypeCode.Double; } else { Debug.Assert(itemType == XsltConvert.BooleanType, "Unexpected type of atomic value " + itemType.ToString()); return TypeCode.Boolean; } } // Returns weakest of the two given TypeCodes, String > Double > Boolean private static TypeCode WeakestTypeCode(TypeCode typeCode1, TypeCode typeCode2) { Debug.Assert(TypeCode.Boolean < TypeCode.Double && TypeCode.Double < TypeCode.String, "Cannot use the smallest TypeCode as a weakest one"); return typeCode1 < typeCode2 ? typeCode1 : typeCode2; } private static bool CompareNumbers(ComparisonOperator op, double left, double right) { switch (op) { case ComparisonOperator.Eq: return left == right; case ComparisonOperator.Ne: return left != right; case ComparisonOperator.Lt: return left < right; case ComparisonOperator.Le: return left <= right; case ComparisonOperator.Gt: return left > right; default: return left >= right; } } private static bool CompareValues(ComparisonOperator op, XPathItem left, XPathItem right, TypeCode compType) { if (compType == TypeCode.Double) { return CompareNumbers(op, XsltConvert.ToDouble(left), XsltConvert.ToDouble(right)); } else { Debug.Assert(op == ComparisonOperator.Eq || op == ComparisonOperator.Ne); if (compType == TypeCode.String) { return (XsltConvert.ToString(left) == XsltConvert.ToString(right)) == (op == ComparisonOperator.Eq); } else { Debug.Assert(compType == TypeCode.Boolean); return (XsltConvert.ToBoolean(left) == XsltConvert.ToBoolean(right)) == (op == ComparisonOperator.Eq); } } } private static bool CompareNodeSetAndValue(ComparisonOperator op, IList nodeset, XPathItem val, TypeCode compType) { Debug.Assert(compType == TypeCode.Boolean || compType == TypeCode.Double || compType == TypeCode.String); if (compType == TypeCode.Boolean) { // Cast nodeset to boolean type, then take its ordinal number return CompareNumbers(op, (nodeset.Count != 0) ? 1 : 0, XsltConvert.ToBoolean(val) ? 1 : 0); } else { int length = nodeset.Count; for (int idx = 0; idx < length; idx++) { if (CompareValues(op, nodeset[idx], val, compType)) { return true; } } return false; } } private static bool CompareNodeSetAndNodeSet(ComparisonOperator op, IList left, IList right, TypeCode compType) { int leftLen = left.Count; int rightLen = right.Count; for (int leftIdx = 0; leftIdx < leftLen; leftIdx++) { for (int rightIdx = 0; rightIdx < rightLen; rightIdx++) { if (CompareValues(op, left[leftIdx], right[rightIdx], compType)) { return true; } } } return false; } public bool EqualityOperator(double opCode, IList left, IList right) { ComparisonOperator op = (ComparisonOperator)opCode; Debug.Assert(op == ComparisonOperator.Eq || op == ComparisonOperator.Ne); CheckXsltValue(left); CheckXsltValue(right); if (IsNodeSetOrRtf(left)) { if (IsNodeSetOrRtf(right)) { // Both left and right are node-sets return CompareNodeSetAndNodeSet(op, ToNodeSetOrRtf(left), ToNodeSetOrRtf(right), TypeCode.String); } else { // left is a node-set, right is an atomic value XPathItem rightItem = right[0]; return CompareNodeSetAndValue(op, ToNodeSetOrRtf(left), rightItem, GetTypeCode(rightItem)); } } else if (IsNodeSetOrRtf(right)) { // left is an atomic value, right is a node-set XPathItem leftItem = left[0]; // Swap operands: left op right -> right op left return CompareNodeSetAndValue(op, ToNodeSetOrRtf(right), leftItem, GetTypeCode(leftItem)); } else { // Both left and right are atomic values XPathItem leftItem = left[0]; XPathItem rightItem = right[0]; return CompareValues(op, leftItem, rightItem, WeakestTypeCode(GetTypeCode(leftItem), GetTypeCode(rightItem))); } } // Inverts relational operator in order to swap operands of the comparison private static ComparisonOperator InvertOperator(ComparisonOperator op) { switch (op) { case ComparisonOperator.Lt: return ComparisonOperator.Gt; case ComparisonOperator.Le: return ComparisonOperator.Ge; case ComparisonOperator.Gt: return ComparisonOperator.Lt; case ComparisonOperator.Ge: return ComparisonOperator.Le; default: return op; } } public bool RelationalOperator(double opCode, IList left, IList right) { ComparisonOperator op = (ComparisonOperator)opCode; Debug.Assert(ComparisonOperator.Lt <= op && op <= ComparisonOperator.Ge); CheckXsltValue(left); CheckXsltValue(right); if (IsNodeSetOrRtf(left)) { if (IsNodeSetOrRtf(right)) { // Both left and right are node-sets return CompareNodeSetAndNodeSet(op, ToNodeSetOrRtf(left), ToNodeSetOrRtf(right), TypeCode.Double); } else { // left is a node-set, right is an atomic value XPathItem rightItem = right[0]; return CompareNodeSetAndValue(op, ToNodeSetOrRtf(left), rightItem, WeakestTypeCode(GetTypeCode(rightItem), TypeCode.Double)); } } else if (IsNodeSetOrRtf(right)) { // left is an atomic value, right is a node-set XPathItem leftItem = left[0]; // Swap operands: left op right -> right InvertOperator(op) left op = InvertOperator(op); return CompareNodeSetAndValue(op, ToNodeSetOrRtf(right), leftItem, WeakestTypeCode(GetTypeCode(leftItem), TypeCode.Double)); } else { // Both left and right are atomic values XPathItem leftItem = left[0]; XPathItem rightItem = right[0]; return CompareValues(op, leftItem, rightItem, TypeCode.Double); } } #endregion // nav1 and nav2 are assumed to belong to the same document public bool IsSameNodeSort(XPathNavigator nav1, XPathNavigator nav2) { Debug.Assert(XPathNodeType.SignificantWhitespace == XPathNodeType.Text + 1); Debug.Assert(XPathNodeType.Whitespace == XPathNodeType.Text + 2); XPathNodeType nt1 = nav1.NodeType; XPathNodeType nt2 = nav2.NodeType; // If one of nodes is a text node, the other one must also be a text node if (XPathNodeType.Text <= nt1 && nt1 <= XPathNodeType.Whitespace) { return XPathNodeType.Text <= nt2 && nt2 <= XPathNodeType.Whitespace; } // Otherwise nodes must have the same node kind, the same local name, and the same namespace URI Debug.Assert((object)nav1.NameTable == (object)nav2.NameTable, "Ref.Equal cannot be used if navigators have different name tables"); return nt1 == nt2 && Ref.Equal(nav1.LocalName, nav2.LocalName) && Ref.Equal(nav1.NamespaceURI, nav2.NamespaceURI); } //------------------------------------------------ // Helper methods //------------------------------------------------ [Conditional("DEBUG")] internal static void CheckXsltValue(XPathItem item) { CheckXsltValue(new XmlQueryItemSequence(item)); } [Conditional("DEBUG")] internal static void CheckXsltValue(IList val) { // IsDocOrderDistinct is not always set to true even if the node-set is ordered // Debug.Assert(val.Count <= 1 || val.IsDocOrderDistinct, "All node-sets must be ordered"); if (val.Count == 1) { XsltFunctions.EXslObjectType(val); } else { // Every item must be a node, but for performance reasons we check only // the first two and the last two items int count = val.Count; for (int idx = 0; idx < count; idx++) { if (!val[idx].IsNode) { Debug.Fail("Invalid XSLT value"); break; } if (idx == 1) { idx += Math.Max(count - 4, 0); } } } } private static bool IsNodeSetOrRtf(IList val) { CheckXsltValue(val); if (val.Count == 1) { return val[0].IsNode; } return true; } private static IList ToNodeSetOrRtf(IList val) { return XmlILStorageConverter.ItemsToNavigators(val); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ContainerParaClient.cs
- Vertex.cs
- SecurityNegotiationException.cs
- SystemInfo.cs
- GridViewSelectEventArgs.cs
- OutputCacheModule.cs
- QilLoop.cs
- SiteMapNodeCollection.cs
- SchemaObjectWriter.cs
- SecurityHelper.cs
- MenuScrollingVisibilityConverter.cs
- RadioButtonStandardAdapter.cs
- _NativeSSPI.cs
- ImageMapEventArgs.cs
- ScrollViewerAutomationPeer.cs
- ScriptingProfileServiceSection.cs
- Mapping.cs
- SystemThemeKey.cs
- CompositeControl.cs
- ParentQuery.cs
- CheckBox.cs
- PageThemeParser.cs
- XmlDataLoader.cs
- ColumnHeader.cs
- Stylesheet.cs
- ArrayList.cs
- XmlBinaryWriter.cs
- ProfileSettings.cs
- DbConnectionPoolGroupProviderInfo.cs
- DataControlPagerLinkButton.cs
- ImportContext.cs
- CustomError.cs
- CodeTypeDelegate.cs
- ByteAnimationBase.cs
- XmlStreamStore.cs
- ConstraintEnumerator.cs
- Pair.cs
- CutCopyPasteHelper.cs
- SchemaImporterExtensionElement.cs
- TimeoutValidationAttribute.cs
- WebPartTransformer.cs
- XmlMtomReader.cs
- DataDocumentXPathNavigator.cs
- SimpleMailWebEventProvider.cs
- BaseTemplateParser.cs
- FrameworkReadOnlyPropertyMetadata.cs
- Control.cs
- TemplateBaseAction.cs
- GlyphRunDrawing.cs
- EmbossBitmapEffect.cs
- HttpCachePolicy.cs
- LiteralText.cs
- SqlLiftIndependentRowExpressions.cs
- WebEvents.cs
- BCryptSafeHandles.cs
- SQLMembershipProvider.cs
- FlowDocumentReaderAutomationPeer.cs
- CompositeActivityCodeGenerator.cs
- HtmlObjectListAdapter.cs
- COM2Properties.cs
- HyperLinkField.cs
- SourceSwitch.cs
- CollectionViewGroup.cs
- HttpDebugHandler.cs
- Color.cs
- ReadOnlyCollectionBase.cs
- RightNameExpirationInfoPair.cs
- FrameworkName.cs
- PasswordBox.cs
- XmlSchemaSimpleTypeRestriction.cs
- GifBitmapDecoder.cs
- IdnMapping.cs
- SettingsProviderCollection.cs
- FormViewUpdatedEventArgs.cs
- ToolStripSeparatorRenderEventArgs.cs
- SrgsGrammarCompiler.cs
- PageContentCollection.cs
- ClientType.cs
- validationstate.cs
- CodeAccessPermission.cs
- SecurityElement.cs
- SessionEndingEventArgs.cs
- NamedObjectList.cs
- Focus.cs
- SettingsAttributes.cs
- Rectangle.cs
- XamlWrappingReader.cs
- SqlConnectionStringBuilder.cs
- EtwTrackingBehaviorElement.cs
- PaintValueEventArgs.cs
- CodeDomExtensionMethods.cs
- UrlMappingsModule.cs
- FrugalMap.cs
- UdpTransportSettingsElement.cs
- ZipIOExtraField.cs
- TypeLoadException.cs
- TreeWalkHelper.cs
- Translator.cs
- ExpressionBindings.cs
- DataGridCell.cs