You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			377 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			377 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // <copyright file="XsltConvert.cs" company="Microsoft">
 | |
| //     Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| // </copyright>                                                                
 | |
| // <owner current="true" primary="true">Microsoft</owner>
 | |
| //------------------------------------------------------------------------------
 | |
| using System;
 | |
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.Xml.XPath;
 | |
| using System.Xml.Xsl;
 | |
| using System.Xml.Schema;
 | |
| using System.Diagnostics;
 | |
| using System.ComponentModel;
 | |
| 
 | |
| namespace System.Xml.Xsl.Runtime {
 | |
|     using Res           = System.Xml.Utils.Res;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Contains conversion routines used by Xslt.  These conversions fall into several categories:
 | |
|     ///   1. Internal type to internal type: These are conversions from one of the five Xslt types to another
 | |
|     ///      of the five types.
 | |
|     ///   2. External type to internal type: These are conversions from any of the Xsd types to one of the five
 | |
|     ///      Xslt types.
 | |
|     ///   3. Internal type to external type: These are conversions from one of the five Xslt types to any of
 | |
|     ///      of the Xsd types.
 | |
|     /// </summary>
 | |
|     [EditorBrowsable(EditorBrowsableState.Never)]
 | |
|     public static class XsltConvert {
 | |
|         internal static readonly Type BooleanType = typeof(bool);
 | |
|         internal static readonly Type ByteArrayType = typeof(byte[]);
 | |
|         internal static readonly Type ByteType = typeof(byte);
 | |
|         internal static readonly Type DateTimeType = typeof(DateTime);
 | |
|         internal static readonly Type DecimalType = typeof(decimal);
 | |
|         internal static readonly Type DoubleType = typeof(double);
 | |
|         internal static readonly Type ICollectionType = typeof(ICollection);
 | |
|         internal static readonly Type IEnumerableType = typeof(IEnumerable);
 | |
|         internal static readonly Type IListType = typeof(IList);
 | |
|         internal static readonly Type Int16Type = typeof(short);
 | |
|         internal static readonly Type Int32Type = typeof(int);
 | |
|         internal static readonly Type Int64Type = typeof(long);
 | |
|         internal static readonly Type IXPathNavigableType = typeof(IXPathNavigable);
 | |
|         internal static readonly Type ObjectType = typeof(object);
 | |
|         internal static readonly Type SByteType = typeof(sbyte);
 | |
|         internal static readonly Type SingleType = typeof(float);
 | |
|         internal static readonly Type StringType = typeof(string);
 | |
|         internal static readonly Type TimeSpanType = typeof(TimeSpan);
 | |
|         internal static readonly Type UInt16Type = typeof(ushort);
 | |
|         internal static readonly Type UInt32Type = typeof(uint);
 | |
|         internal static readonly Type UInt64Type = typeof(ulong);
 | |
|         internal static readonly Type UriType = typeof(Uri);
 | |
|         internal static readonly Type VoidType = typeof(void);
 | |
|         internal static readonly Type XmlAtomicValueType = typeof(XmlAtomicValue);
 | |
|         internal static readonly Type XmlQualifiedNameType = typeof(XmlQualifiedName);
 | |
|         internal static readonly Type XPathItemType = typeof(XPathItem);
 | |
|         internal static readonly Type XPathNavigatorArrayType = typeof(XPathNavigator[]);
 | |
|         internal static readonly Type XPathNavigatorType = typeof(XPathNavigator);
 | |
|         internal static readonly Type XPathNodeIteratorType = typeof(XPathNodeIterator);
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // ToBoolean (internal type to internal type)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static bool ToBoolean(XPathItem item) {
 | |
|             XsltLibrary.CheckXsltValue(item);
 | |
| 
 | |
|             if (item.IsNode)
 | |
|                 return true;
 | |
| 
 | |
|             Type itemType = item.ValueType;
 | |
| 
 | |
|             if (itemType == StringType) {
 | |
|                 return item.Value.Length != 0;
 | |
|             }
 | |
|             else if (itemType == DoubleType) {
 | |
|                 // (x < 0 || 0 < x)  ==  (x != 0) && !Double.IsNaN(x)
 | |
|                 double dbl = item.ValueAsDouble;
 | |
|                 return dbl < 0 || 0 < dbl;
 | |
|             }
 | |
|             else {
 | |
|                 Debug.Assert(itemType == BooleanType, "Unexpected type of atomic sequence " + itemType.ToString());
 | |
|                 return item.ValueAsBoolean;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static bool ToBoolean(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 0)
 | |
|                 return false;
 | |
| 
 | |
|             return ToBoolean(listItems[0]);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // ToDouble (internal type to internal type)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static double ToDouble(string value) {
 | |
|             return XPathConvert.StringToDouble(value);
 | |
|         }
 | |
| 
 | |
|         public static double ToDouble(XPathItem item) {
 | |
|             XsltLibrary.CheckXsltValue(item);
 | |
| 
 | |
|             if (item.IsNode)
 | |
|                 return XPathConvert.StringToDouble(item.Value);
 | |
| 
 | |
|             Type itemType = item.ValueType;
 | |
| 
 | |
|             if (itemType == StringType) {
 | |
|                 return XPathConvert.StringToDouble(item.Value);
 | |
|             }
 | |
|             else if (itemType == DoubleType) {
 | |
|                 return item.ValueAsDouble;
 | |
|             }
 | |
|             else {
 | |
|                 Debug.Assert(itemType == BooleanType, "Unexpected type of atomic sequence " + itemType.ToString());
 | |
|                 return item.ValueAsBoolean ? 1d : 0d;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static double ToDouble(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 0)
 | |
|                 return Double.NaN;
 | |
| 
 | |
|             return ToDouble(listItems[0]);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // ToNode (internal type to internal type)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static XPathNavigator ToNode(XPathItem item) {
 | |
|             XsltLibrary.CheckXsltValue(item);
 | |
| 
 | |
|             if (!item.IsNode) {
 | |
|                 // Create Navigator over text node containing string value of item
 | |
|                 XPathDocument doc = new XPathDocument();
 | |
|                 XmlRawWriter writer = doc.LoadFromWriter(XPathDocument.LoadFlags.AtomizeNames, string.Empty);
 | |
|                 writer.WriteString(ToString(item));
 | |
|                 writer.Close();
 | |
|                 return doc.CreateNavigator();
 | |
|             }
 | |
| 
 | |
|             RtfNavigator rtf = item as RtfNavigator;
 | |
|             if (rtf != null)
 | |
|                 return rtf.ToNavigator();
 | |
| 
 | |
|             return (XPathNavigator) item;
 | |
|         }
 | |
| 
 | |
|         public static XPathNavigator ToNode(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 1)
 | |
|                 return ToNode(listItems[0]);
 | |
| 
 | |
|             throw new XslTransformException(Res.Xslt_NodeSetNotNode, string.Empty);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // ToNodes (internal type to internal type)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static IList<XPathNavigator> ToNodeSet(XPathItem item) {
 | |
|             return new XmlQueryNodeSequence(ToNode(item));
 | |
|         }
 | |
| 
 | |
|         public static IList<XPathNavigator> ToNodeSet(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 1)
 | |
|                 return new XmlQueryNodeSequence(ToNode(listItems[0]));
 | |
| 
 | |
|             return XmlILStorageConverter.ItemsToNavigators(listItems);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // ToString (internal type to internal type)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static string ToString(double value) {
 | |
|             return XPathConvert.DoubleToString(value);
 | |
|         }
 | |
| 
 | |
|         public static string ToString(XPathItem item) {
 | |
|             XsltLibrary.CheckXsltValue(item);
 | |
| 
 | |
|             // Use XPath 1.0 rules to convert double to string
 | |
|             if (!item.IsNode && item.ValueType == DoubleType)
 | |
|                 return XPathConvert.DoubleToString(item.ValueAsDouble);
 | |
| 
 | |
|             return item.Value;
 | |
|         }
 | |
| 
 | |
|         public static string ToString(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 0)
 | |
|                 return string.Empty;
 | |
| 
 | |
|             return ToString(listItems[0]);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // External type to internal type
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static string ToString(DateTime value) {
 | |
|             return (new XsdDateTime(value, XsdDateTimeFlags.DateTime)).ToString();
 | |
|         }
 | |
| 
 | |
|         public static double ToDouble(decimal value) {
 | |
|             return (double) value;
 | |
|         }
 | |
| 
 | |
|         public static double ToDouble(int value) {
 | |
|             return (double) value;
 | |
|         }
 | |
| 
 | |
|         public static double ToDouble(long value) {
 | |
|             return (double) value;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // Internal type to external type
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static decimal ToDecimal(double value) {
 | |
|             checked { return (decimal) value; }
 | |
|         }
 | |
| 
 | |
|         public static int ToInt(double value) {
 | |
|             checked { return (int) value; }
 | |
|         }
 | |
| 
 | |
|         public static long ToLong(double value) {
 | |
|             checked { return (long) value; }
 | |
|         }
 | |
| 
 | |
|         public static DateTime ToDateTime(string value) {
 | |
|             return (DateTime)(new XsdDateTime(value, XsdDateTimeFlags.AllXsd));
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // External type to external type
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         internal static XmlAtomicValue ConvertToType(XmlAtomicValue value, XmlQueryType destinationType) {
 | |
|             Debug.Assert(destinationType.IsStrict && destinationType.IsAtomicValue, "Can only convert to strict atomic type.");
 | |
| 
 | |
|             // This conversion matrix should match the one in XmlILVisitor.GetXsltConvertMethod
 | |
|             switch (destinationType.TypeCode) {
 | |
|                 case XmlTypeCode.Boolean:
 | |
|                     switch (value.XmlType.TypeCode) {
 | |
|                         case XmlTypeCode.Boolean:
 | |
|                         case XmlTypeCode.Double:
 | |
|                         case XmlTypeCode.String:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToBoolean(value));
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case XmlTypeCode.DateTime:
 | |
|                     if (value.XmlType.TypeCode == XmlTypeCode.String)
 | |
|                         return new XmlAtomicValue(destinationType.SchemaType, ToDateTime(value.Value));
 | |
|                     break;
 | |
| 
 | |
|                 case XmlTypeCode.Decimal:
 | |
|                     if (value.XmlType.TypeCode == XmlTypeCode.Double)
 | |
|                         return new XmlAtomicValue(destinationType.SchemaType, ToDecimal(value.ValueAsDouble));
 | |
|                     break;
 | |
| 
 | |
|                 case XmlTypeCode.Double:
 | |
|                     switch (value.XmlType.TypeCode) {
 | |
|                         case XmlTypeCode.Boolean:
 | |
|                         case XmlTypeCode.Double:
 | |
|                         case XmlTypeCode.String:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble(value));
 | |
| 
 | |
|                         case XmlTypeCode.Decimal:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble((decimal) value.ValueAs(DecimalType, null)));
 | |
| 
 | |
|                         case XmlTypeCode.Int:
 | |
|                         case XmlTypeCode.Long:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToDouble(value.ValueAsLong));
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case XmlTypeCode.Int:
 | |
|                 case XmlTypeCode.Long:
 | |
|                     if (value.XmlType.TypeCode == XmlTypeCode.Double)
 | |
|                         return new XmlAtomicValue(destinationType.SchemaType, ToLong(value.ValueAsDouble));
 | |
|                     break;
 | |
| 
 | |
|                 case XmlTypeCode.String:
 | |
|                     switch (value.XmlType.TypeCode) {
 | |
|                         case XmlTypeCode.Boolean:
 | |
|                         case XmlTypeCode.Double:
 | |
|                         case XmlTypeCode.String:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToString(value));
 | |
| 
 | |
|                         case XmlTypeCode.DateTime:
 | |
|                             return new XmlAtomicValue(destinationType.SchemaType, ToString(value.ValueAsDateTime));
 | |
|                     }
 | |
|                     break;
 | |
|             }
 | |
| 
 | |
|             Debug.Fail("Conversion from " + value.XmlType.QualifiedName.Name + " to " + destinationType + " is not supported.");
 | |
|             return value;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // EnsureXXX methods (TreatAs)
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         public static IList<XPathNavigator> EnsureNodeSet(IList<XPathItem> listItems) {
 | |
|             XsltLibrary.CheckXsltValue(listItems);
 | |
| 
 | |
|             if (listItems.Count == 1) {
 | |
|                 XPathItem item = listItems[0];
 | |
|                 if (!item.IsNode)
 | |
|                     throw new XslTransformException(Res.XPath_NodeSetExpected, string.Empty);
 | |
| 
 | |
|                 if (item is RtfNavigator)
 | |
|                     throw new XslTransformException(Res.XPath_RtfInPathExpr, string.Empty);
 | |
|             }
 | |
| 
 | |
|             return XmlILStorageConverter.ItemsToNavigators(listItems);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //------------------------------------------------------------------------
 | |
|         // InferXsltType
 | |
|         //------------------------------------------------------------------------
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Infer one of the Xslt types from "clrType" -- Boolean, Double, String, Node, Node*, Item*.
 | |
|         /// </summary>
 | |
|         internal static XmlQueryType InferXsltType(Type clrType) {
 | |
|             if (clrType == BooleanType) return XmlQueryTypeFactory.BooleanX;
 | |
|             if (clrType == ByteType) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == DecimalType) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == DateTimeType) return XmlQueryTypeFactory.StringX;
 | |
|             if (clrType == DoubleType) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == Int16Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == Int32Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == Int64Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == IXPathNavigableType) return XmlQueryTypeFactory.NodeNotRtf;
 | |
|             if (clrType == SByteType) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == SingleType) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == StringType) return XmlQueryTypeFactory.StringX;
 | |
|             if (clrType == UInt16Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == UInt32Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == UInt64Type) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == XPathNavigatorArrayType) return XmlQueryTypeFactory.NodeSDod;
 | |
|             if (clrType == XPathNavigatorType) return XmlQueryTypeFactory.NodeNotRtf;
 | |
|             if (clrType == XPathNodeIteratorType) return XmlQueryTypeFactory.NodeSDod;
 | |
|             if (clrType.IsEnum) return XmlQueryTypeFactory.DoubleX;
 | |
|             if (clrType == VoidType) return XmlQueryTypeFactory.Empty;
 | |
| 
 | |
|             return XmlQueryTypeFactory.ItemS;
 | |
|         }
 | |
|     }
 | |
| }
 |