/// <summary>
/// Convert from the Clr type of "value" to the default Clr type that ILGen uses to represent the xml type, using
/// the conversion rules of the xml type.
/// </summary>
internal object ChangeTypeXsltResult(XmlQueryType xmlType, object value)
{
if (value == null)
{
throw new XslTransformException(SR.Xslt_ItemNull, string.Empty);
}
switch (xmlType.TypeCode)
{
case XmlTypeCode.String:
if (value.GetType() == XsltConvert.DateTimeType)
{
value = XsltConvert.ToString((DateTime)value);
}
break;
case XmlTypeCode.Double:
if (value.GetType() != XsltConvert.DoubleType)
{
value = ((IConvertible)value).ToDouble(null);
}
break;
case XmlTypeCode.Node:
if (!xmlType.IsSingleton)
{
XPathArrayIterator iter = value as XPathArrayIterator;
// Special-case XPathArrayIterator in order to avoid copies
if (iter != null && iter.AsList is XmlQueryNodeSequence)
{
value = iter.AsList as XmlQueryNodeSequence;
}
else
{
// Iterate over list and ensure it only contains nodes
XmlQueryNodeSequence seq = new XmlQueryNodeSequence();
IList list = value as IList;
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
seq.Add(EnsureNavigator(list[i]));
}
}
else
{
foreach (object o in (IEnumerable)value)
{
seq.Add(EnsureNavigator(o));
}
}
value = seq;
}
// Always sort node-set by document order
value = ((XmlQueryNodeSequence)value).DocOrderDistinct(_docOrderCmp);
}
break;
case XmlTypeCode.Item:
{
Type sourceType = value.GetType();
IXPathNavigable navigable;
// If static type is item, then infer type based on dynamic value
switch (XsltConvert.InferXsltType(sourceType).TypeCode)
{
case XmlTypeCode.Boolean:
value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Boolean), value));
break;
case XmlTypeCode.Double:
value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Double), ((IConvertible)value).ToDouble(null)));
break;
case XmlTypeCode.String:
if (sourceType == XsltConvert.DateTimeType)
{
value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), XsltConvert.ToString((DateTime)value)));
}
else
{
value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), value));
}
break;
case XmlTypeCode.Node:
// Support XPathNavigator[]
value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value);
break;
case XmlTypeCode.Item:
// Support XPathNodeIterator
if (value is XPathNodeIterator)
{
value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value);
break;
}
// Support IXPathNavigable and XPathNavigator
navigable = value as IXPathNavigable;
if (navigable != null)
{
if (value is XPathNavigator)
{
value = new XmlQueryNodeSequence((XPathNavigator)value);
}
else
{
value = new XmlQueryNodeSequence(navigable.CreateNavigator());
}
break;
}
throw new XslTransformException(SR.Xslt_UnsupportedClrType, sourceType.Name);
}
break;
}
}
#if FEATURE_COMPILED_XSL
Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()), "Xml type " + xmlType + " is not represented in ILGen as " + value.GetType().Name);
#endif
return(value);
}