The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.Runtime \ XsltConvert

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XsltConvert.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Xml.XPath;
  19. using System.Xml.Xsl;
  20. using System.Xml.Schema;
  21. using System.Diagnostics;
  22. using System.ComponentModel;
  23. namespace System.Xml.Xsl.Runtime
  24. {
  25.     using Res = System.Xml.Utils.Res;
  26.    
  27.     /// <summary>
  28.     /// Contains conversion routines used by Xslt. These conversions fall into several categories:
  29.     /// 1. Internal type to internal type: These are conversions from one of the five Xslt types to another
  30.     /// of the five types.
  31.     /// 2. External type to internal type: These are conversions from any of the Xsd types to one of the five
  32.     /// Xslt types.
  33.     /// 3. Internal type to external type: These are conversions from one of the five Xslt types to any of
  34.     /// of the Xsd types.
  35.     /// </summary>
  36.     [EditorBrowsable(EditorBrowsableState.Never)]
  37.     public static class XsltConvert
  38.     {
  39.         static internal readonly Type BooleanType = typeof(bool);
  40.         static internal readonly Type ByteArrayType = typeof(byte[]);
  41.         static internal readonly Type ByteType = typeof(byte);
  42.         static internal readonly Type DateTimeType = typeof(DateTime);
  43.         static internal readonly Type DecimalType = typeof(decimal);
  44.         static internal readonly Type DoubleType = typeof(double);
  45.         static internal readonly Type ICollectionType = typeof(ICollection);
  46.         static internal readonly Type IEnumerableType = typeof(IEnumerable);
  47.         static internal readonly Type IListType = typeof(IList);
  48.         static internal readonly Type Int16Type = typeof(short);
  49.         static internal readonly Type Int32Type = typeof(int);
  50.         static internal readonly Type Int64Type = typeof(long);
  51.         static internal readonly Type IXPathNavigableType = typeof(IXPathNavigable);
  52.         static internal readonly Type ObjectType = typeof(object);
  53.         static internal readonly Type SByteType = typeof(sbyte);
  54.         static internal readonly Type SingleType = typeof(float);
  55.         static internal readonly Type StringType = typeof(string);
  56.         static internal readonly Type TimeSpanType = typeof(TimeSpan);
  57.         static internal readonly Type UInt16Type = typeof(ushort);
  58.         static internal readonly Type UInt32Type = typeof(uint);
  59.         static internal readonly Type UInt64Type = typeof(ulong);
  60.         static internal readonly Type UriType = typeof(Uri);
  61.         static internal readonly Type VoidType = typeof(void);
  62.         static internal readonly Type XmlAtomicValueType = typeof(XmlAtomicValue);
  63.         static internal readonly Type XmlQualifiedNameType = typeof(XmlQualifiedName);
  64.         static internal readonly Type XPathItemType = typeof(XPathItem);
  65.         static internal readonly Type XPathNavigatorArrayType = typeof(XPathNavigator[]);
  66.         static internal readonly Type XPathNavigatorType = typeof(XPathNavigator);
  67.         static internal readonly Type XPathNodeIteratorType = typeof(XPathNodeIterator);
  68.        
  69.        
  70.         //------------------------------------------------------------------------
  71.         // ToBoolean (internal type to internal type)
  72.         //------------------------------------------------------------------------
  73.        
  74.         public static bool ToBoolean(XPathItem item)
  75.         {
  76.             XsltLibrary.CheckXsltValue(item);
  77.            
  78.             if (item.IsNode)
  79.                 return true;
  80.            
  81.             Type itemType = item.ValueType;
  82.            
  83.             if (itemType == StringType) {
  84.                 return item.Value.Length != 0;
  85.             }
  86.             else if (itemType == DoubleType) {
  87.                 // (x < 0 || 0 < x) == (x != 0) && !Double.IsNaN(x)
  88.                 double dbl = item.ValueAsDouble;
  89.                 return dbl < 0 || 0 < dbl;
  90.             }
  91.             else {
  92.                 Debug.Assert(itemType == BooleanType, "Unexpected type of atomic sequence " + itemType.ToString());
  93.                 return item.ValueAsBoolean;
  94.             }
  95.         }
  96.        
  97.         public static bool ToBoolean(IList<XPathItem> listItems)
  98.         {
  99.             XsltLibrary.CheckXsltValue(listItems);
  100.            
  101.             if (listItems.Count == 0)
  102.                 return false;
  103.            
  104.             return ToBoolean(listItems[0]);
  105.         }
  106.        
  107.        
  108.         //------------------------------------------------------------------------
  109.         // ToDouble (internal type to internal type)
  110.         //------------------------------------------------------------------------
  111.        
  112.         public static double ToDouble(string value)
  113.         {
  114.             return XPathConvert.StringToDouble(value);
  115.         }
  116.        
  117.         public static double ToDouble(XPathItem item)
  118.         {
  119.             XsltLibrary.CheckXsltValue(item);
  120.            
  121.             if (item.IsNode)
  122.                 return XPathConvert.StringToDouble(item.Value);
  123.            
  124.             Type itemType = item.ValueType;
  125.            
  126.             if (itemType == StringType) {
  127.                 return XPathConvert.StringToDouble(item.Value);
  128.             }
  129.             else if (itemType == DoubleType) {
  130.                 return item.ValueAsDouble;
  131.             }
  132.             else {
  133.                 Debug.Assert(itemType == BooleanType, "Unexpected type of atomic sequence " + itemType.ToString());
  134.                 return item.ValueAsBoolean ? 1.0 : 0.0;
  135.             }
  136.         }
  137.        
  138.         public static double ToDouble(IList<XPathItem> listItems)
  139.         {
  140.             XsltLibrary.CheckXsltValue(listItems);
  141.            
  142.             if (listItems.Count == 0)
  143.                 return Double.NaN;
  144.            
  145.             return ToDouble(listItems[0]);
  146.         }
  147.        
  148.        
  149.         //------------------------------------------------------------------------
  150.         // ToNode (internal type to internal type)
  151.         //------------------------------------------------------------------------
  152.        
  153.         public static XPathNavigator ToNode(XPathItem item)
  154.         {
  155.             XsltLibrary.CheckXsltValue(item);
  156.            
  157.             if (!item.IsNode) {
  158.                 // Create Navigator over text node containing string value of item
  159.                 XPathDocument doc = new XPathDocument();
  160.                 XmlRawWriter writer = doc.LoadFromWriter(XPathDocument.LoadFlags.AtomizeNames, string.Empty);
  161.                 writer.WriteString(ToString(item));
  162.                 writer.Close();
  163.                 return doc.CreateNavigator();
  164.             }
  165.            
  166.             RtfNavigator rtf = item as RtfNavigator;
  167.             if (rtf != null)
  168.                 return rtf.ToNavigator();
  169.            
  170.             return (XPathNavigator)item;
  171.         }
  172.        
  173.         public static XPathNavigator ToNode(IList<XPathItem> listItems)
  174.         {
  175.             XsltLibrary.CheckXsltValue(listItems);
  176.            
  177.             if (listItems.Count == 1)
  178.                 return ToNode(listItems[0]);
  179.            
  180.             throw new XslTransformException(Res.Xslt_NodeSetNotNode, string.Empty);
  181.         }
  182.        
  183.        
  184.         //------------------------------------------------------------------------
  185.         // ToNodes (internal type to internal type)
  186.         //------------------------------------------------------------------------
  187.        
  188.         public static IList<XPathNavigator> ToNodeSet(XPathItem item)
  189.         {
  190.             return new XmlQueryNodeSequence(ToNode(item));
  191.         }
  192.        
  193.         public static IList<XPathNavigator> ToNodeSet(IList<XPathItem> listItems)
  194.         {
  195.             XsltLibrary.CheckXsltValue(listItems);
  196.            
  197.             if (listItems.Count == 1)
  198.                 return new XmlQueryNodeSequence(ToNode(listItems[0]));
  199.            
  200.             return XmlILStorageConverter.ItemsToNavigators(listItems);
  201.         }
  202.        
  203.        
  204.         //------------------------------------------------------------------------
  205.         // ToString (internal type to internal type)
  206.         //------------------------------------------------------------------------
  207.        
  208.         public static string ToString(double value)
  209.         {
  210.             return XPathConvert.DoubleToString(value);
  211.         }
  212.        
  213.         public static string ToString(XPathItem item)
  214.         {
  215.             XsltLibrary.CheckXsltValue(item);
  216.            
  217.             // Use XPath 1.0 rules to convert double to string
  218.             if (!item.IsNode && item.ValueType == DoubleType)
  219.                 return XPathConvert.DoubleToString(item.ValueAsDouble);
  220.            
  221.             return item.Value;
  222.         }
  223.        
  224.         public static string ToString(IList<XPathItem> listItems)
  225.         {
  226.             XsltLibrary.CheckXsltValue(listItems);
  227.            
  228.             if (listItems.Count == 0)
  229.                 return string.Empty;
  230.            
  231.             return ToString(listItems[0]);
  232.         }
  233.        
  234.        
  235.         //------------------------------------------------------------------------
  236.         // External type to internal type
  237.         //------------------------------------------------------------------------
  238.        
  239.         public static string ToString(DateTime value)
  240.         {
  241.             return (new XsdDateTime(value, XsdDateTimeFlags.DateTime)).ToString();
  242.         }
  243.        
  244.         public static double ToDouble(decimal value)
  245.         {
  246.             return (double)value;
  247.         }
  248.        
  249.         public static double ToDouble(int value)
  250.         {
  251.             return (double)value;
  252.         }
  253.        
  254.         public static double ToDouble(long value)
  255.         {
  256.             return (double)value;
  257.         }
  258.        
  259.        
  260.         //------------------------------------------------------------------------
  261.         // Internal type to external type
  262.         //------------------------------------------------------------------------
  263.        
  264.         public static decimal ToDecimal(double value)
  265.         {
  266.             checked {
  267.                 return (decimal)value;
  268.             }
  269.         }
  270.        
  271.         public static int ToInt(double value)
  272.         {
  273.             checked {
  274.                 return (int)value;
  275.             }
  276.         }
  277.        
  278.         public static long ToLong(double value)
  279.         {
  280.             checked {
  281.                 return (long)value;
  282.             }
  283.         }
  284.        
  285.         public static DateTime ToDateTime(string value)
  286.         {
  287.             return (DateTime)(new XsdDateTime(value, XsdDateTimeFlags.AllXsd));
  288.         }
  289.        
  290.        
  291.         //------------------------------------------------------------------------
  292.         // External type to external type
  293.         //------------------------------------------------------------------------
  294.        
  295.         static internal XmlAtomicValue ConvertToType(XmlAtomicValue value, XmlQueryType destinationType)
  296.         {
  297.             Debug.Assert(destinationType.IsStrict && destinationType.IsAtomicValue, "Can only convert to strict atomic type.");
  298.            
  299.             // This conversion matrix should match the one in XmlILVisitor.GetXsltConvertMethod
  300.             switch (destinationType.TypeCode) {
  301.                 case XmlTypeCode.Boolean:
  302.                     switch (value.XmlType.TypeCode) {
  303.                         case XmlTypeCode.Boolean:
  304.                         case XmlTypeCode.Double:
  305.                         case XmlTypeCode.String:
  306.                             return new XmlAtomicValue(destinationType.SchemaType, ToBoolean(value));
  307.                     }
  308.                     break;
  309.                 case XmlTypeCode.DateTime:
  310.                    
  311.                     if (value.XmlType.TypeCode == XmlTypeCode.String)
  312.                         return new XmlAtomicValue(destinationType.SchemaType, ToDateTime(value.Value));
  313.                     break;
  314.                 case XmlTypeCode.Decimal:
  315.                    
  316.                     if (value.XmlType.TypeCode == XmlTypeCode.Double)
  317.                         return new XmlAtomicValue(destinationType.SchemaType, ToDecimal(value.ValueAsDouble));
  318.                     break;
  319.                 case XmlTypeCode.Double:
  320.                    
  321.                     switch (value.XmlType.TypeCode) {
  322.                         case XmlTypeCode.Boolean:
  323.                         case XmlTypeCode.Double:
  324.                         case XmlTypeCode.String:
  325.                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble(value));
  326.                         case XmlTypeCode.Decimal:
  327.                            
  328.                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble((decimal)value.ValueAs(DecimalType, null)));
  329.                         case XmlTypeCode.Int:
  330.                         case XmlTypeCode.Long:
  331.                            
  332.                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble(value.ValueAsLong));
  333.                     }
  334.                     break;
  335.                 case XmlTypeCode.Int:
  336.                 case XmlTypeCode.Long:
  337.                    
  338.                     if (value.XmlType.TypeCode == XmlTypeCode.Double)
  339.                         return new XmlAtomicValue(destinationType.SchemaType, ToLong(value.ValueAsDouble));
  340.                     break;
  341.                 case XmlTypeCode.String:
  342.                    
  343.                     switch (value.XmlType.TypeCode) {
  344.                         case XmlTypeCode.Boolean:
  345.                         case XmlTypeCode.Double:
  346.                         case XmlTypeCode.String:
  347.                             return new XmlAtomicValue(destinationType.SchemaType, ToString(value));
  348.                         case XmlTypeCode.DateTime:
  349.                            
  350.                             return new XmlAtomicValue(destinationType.SchemaType, ToString(value.ValueAsDateTime));
  351.                     }
  352.                     break;
  353.             }
  354.            
  355.             Debug.Fail("Conversion from " + value.XmlType.QualifiedName.Name + " to " + destinationType + " is not supported.");
  356.             return value;
  357.         }
  358.        
  359.        
  360.         //------------------------------------------------------------------------
  361.         // EnsureXXX methods (TreatAs)
  362.         //------------------------------------------------------------------------
  363.        
  364.         public static IList<XPathNavigator> EnsureNodeSet(IList<XPathItem> listItems)
  365.         {
  366.             XsltLibrary.CheckXsltValue(listItems);
  367.            
  368.             if (listItems.Count == 1) {
  369.                 XPathItem item = listItems[0];
  370.                 if (!item.IsNode)
  371.                     throw new XslTransformException(Res.XPath_NodeSetExpected, string.Empty);
  372.                
  373.                 if (item is RtfNavigator)
  374.                     throw new XslTransformException(Res.XPath_RtfInPathExpr, string.Empty);
  375.             }
  376.            
  377.             return XmlILStorageConverter.ItemsToNavigators(listItems);
  378.         }
  379.        
  380.        
  381.         //------------------------------------------------------------------------
  382.         // InferXsltType
  383.         //------------------------------------------------------------------------
  384.        
  385.         /// <summary>
  386.         /// Infer one of the Xslt types from "clrType" -- Boolean, Double, String, Node, Node*, Item*.
  387.         /// </summary>
  388.         static internal XmlQueryType InferXsltType(Type clrType)
  389.         {
  390.             if (clrType == BooleanType)
  391.                 return XmlQueryTypeFactory.BooleanX;
  392.             if (clrType == ByteType)
  393.                 return XmlQueryTypeFactory.DoubleX;
  394.             if (clrType == DecimalType)
  395.                 return XmlQueryTypeFactory.DoubleX;
  396.             if (clrType == DateTimeType)
  397.                 return XmlQueryTypeFactory.StringX;
  398.             if (clrType == DoubleType)
  399.                 return XmlQueryTypeFactory.DoubleX;
  400.             if (clrType == Int16Type)
  401.                 return XmlQueryTypeFactory.DoubleX;
  402.             if (clrType == Int32Type)
  403.                 return XmlQueryTypeFactory.DoubleX;
  404.             if (clrType == Int64Type)
  405.                 return XmlQueryTypeFactory.DoubleX;
  406.             if (clrType == IXPathNavigableType)
  407.                 return XmlQueryTypeFactory.NodeNotRtf;
  408.             if (clrType == SByteType)
  409.                 return XmlQueryTypeFactory.DoubleX;
  410.             if (clrType == SingleType)
  411.                 return XmlQueryTypeFactory.DoubleX;
  412.             if (clrType == StringType)
  413.                 return XmlQueryTypeFactory.StringX;
  414.             if (clrType == UInt16Type)
  415.                 return XmlQueryTypeFactory.DoubleX;
  416.             if (clrType == UInt32Type)
  417.                 return XmlQueryTypeFactory.DoubleX;
  418.             if (clrType == UInt64Type)
  419.                 return XmlQueryTypeFactory.DoubleX;
  420.             if (clrType == XPathNavigatorArrayType)
  421.                 return XmlQueryTypeFactory.NodeDodS;
  422.             if (clrType == XPathNavigatorType)
  423.                 return XmlQueryTypeFactory.NodeNotRtf;
  424.             if (clrType == XPathNodeIteratorType)
  425.                 return XmlQueryTypeFactory.NodeDodS;
  426.             if (clrType.IsEnum)
  427.                 return XmlQueryTypeFactory.DoubleX;
  428.             if (clrType == VoidType)
  429.                 return XmlQueryTypeFactory.Empty;
  430.            
  431.             return XmlQueryTypeFactory.ItemS;
  432.         }
  433.     }
  434. }

Developer Fusion