Exemplo n.º 1
0
 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));
         }
     }
 }
Exemplo n.º 2
0
 private static bool CompareNodeSetAndValue(ComparisonOperator op, IList <XPathNavigator> 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);
     }
 }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Convert from the Clr type of "value" to Clr type "destinationType" using V1 Xslt rules.
        /// These rules include converting any Rtf values to Nodes.
        /// </summary>
        internal object ChangeTypeXsltArgument(XmlQueryType xmlType, object value, Type destinationType)
        {
#if FEATURE_COMPILED_XSL
            Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()),
                         "Values passed to ChangeTypeXsltArgument should be in ILGen's default Clr representation.");
#endif
            Debug.Assert(destinationType == XsltConvert.ObjectType || !destinationType.IsAssignableFrom(value.GetType()),
                         "No need to call ChangeTypeXsltArgument since value is already assignable to destinationType " + destinationType);

            switch (xmlType.TypeCode)
            {
            case XmlTypeCode.String:
                if (destinationType == XsltConvert.DateTimeType)
                {
                    value = XsltConvert.ToDateTime((string)value);
                }
                break;

            case XmlTypeCode.Double:
                if (destinationType != XsltConvert.DoubleType)
                {
                    value = Convert.ChangeType(value, destinationType, CultureInfo.InvariantCulture);
                }
                break;

            case XmlTypeCode.Node:
                Debug.Assert(xmlType != XmlQueryTypeFactory.Node && xmlType != XmlQueryTypeFactory.NodeS,
                             "Rtf values should have been eliminated by caller.");

                if (destinationType == XsltConvert.XPathNodeIteratorType)
                {
                    value = new XPathArrayIterator((IList)value);
                }
                else if (destinationType == XsltConvert.XPathNavigatorArrayType)
                {
                    // Copy sequence to XPathNavigator[]
                    IList <XPathNavigator> seq      = (IList <XPathNavigator>)value;
                    XPathNavigator[]       navArray = new XPathNavigator[seq.Count];

                    for (int i = 0; i < seq.Count; i++)
                    {
                        navArray[i] = seq[i];
                    }

                    value = navArray;
                }
                break;

            case XmlTypeCode.Item:
            {
                // Only typeof(object) is supported as a destination type
                if (destinationType != XsltConvert.ObjectType)
                {
                    throw new XslTransformException(SR.Xslt_UnsupportedClrType, destinationType.Name);
                }

                // Convert to default, backwards-compatible representation
                //   1. NodeSet: System.Xml.XPath.XPathNodeIterator
                //   2. Rtf: System.Xml.XPath.XPathNavigator
                //   3. Other:   Default V1 representation
                IList <XPathItem> seq = (IList <XPathItem>)value;
                if (seq.Count == 1)
                {
                    XPathItem item = seq[0];

                    if (item.IsNode)
                    {
                        // Node or Rtf
                        RtfNavigator rtf = item as RtfNavigator;
                        if (rtf != null)
                        {
                            value = rtf.ToNavigator();
                        }
                        else
                        {
                            value = new XPathArrayIterator((IList)value);
                        }
                    }
                    else
                    {
                        // Atomic value
                        value = item.TypedValue;
                    }
                }
                else
                {
                    // Nodeset
                    value = new XPathArrayIterator((IList)value);
                }
                break;
            }
            }

            Debug.Assert(destinationType.IsAssignableFrom(value.GetType()), "ChangeType from type " + value.GetType().Name + " to type " + destinationType.Name + " failed");
            return(value);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Get a late-bound extension object from the external argument list.  Bind to a method on the object and invoke it,
        /// passing "args" as arguments.
        /// </summary>
        public IList <XPathItem> InvokeXsltLateBoundFunction(string name, string namespaceUri, IList <XPathItem>[] args)
        {
            object instance;

            object[]     objActualArgs;
            XmlQueryType xmlTypeFormalArg;
            Type         clrTypeFormalArg;
            object       objRet;

            // Get external object instance from argument list (throw if either the list or the instance doesn't exist)
            instance = (_argList != null) ? _argList.GetExtensionObject(namespaceUri) : null;
            if (instance == null)
            {
                throw new XslTransformException(SR.XmlIl_UnknownExtObj, namespaceUri);
            }

            // Bind to a method on the instance object
            if (_extFuncsLate == null)
            {
                _extFuncsLate = new XmlExtensionFunctionTable();
            }

            // Bind to the instance, looking for a matching method (throws if no matching method)
            XmlExtensionFunction extFunc = _extFuncsLate.Bind(name, namespaceUri, args.Length, instance.GetType(), XmlQueryRuntime.LateBoundFlags);

            // Create array which will contain the actual arguments
            objActualArgs = new object[args.Length];

            for (int i = 0; i < args.Length; i++)
            {
                // 1. Assume that the input value can only have one of the following 5 Xslt types:
                //      xs:double, xs:string, xs:boolean, node* (can be rtf)
                // 2. Convert each Rtf value to a NodeSet containing one node.  Now the value may only have one of the 4 Xslt types.
                // 3. Convert from one of the 4 Xslt internal types to the Xslt internal type which is closest to the formal
                //    argument's Xml type (inferred from the Clr type of the formal argument).

                xmlTypeFormalArg = extFunc.GetXmlArgumentType(i);
                switch (xmlTypeFormalArg.TypeCode)
                {
                case XmlTypeCode.Boolean: objActualArgs[i] = XsltConvert.ToBoolean(args[i]); break;

                case XmlTypeCode.Double: objActualArgs[i] = XsltConvert.ToDouble(args[i]); break;

                case XmlTypeCode.String: objActualArgs[i] = XsltConvert.ToString(args[i]); break;

                case XmlTypeCode.Node:
                    if (xmlTypeFormalArg.IsSingleton)
                    {
                        objActualArgs[i] = XsltConvert.ToNode(args[i]);
                    }
                    else
                    {
                        objActualArgs[i] = XsltConvert.ToNodeSet(args[i]);
                    }
                    break;

                case XmlTypeCode.Item:
                    objActualArgs[i] = args[i];
                    break;

                default:
                    Debug.Fail("This XmlTypeCode should never be inferred from a Clr type: " + xmlTypeFormalArg.TypeCode);
                    break;
                }

                // 4. Change the Clr representation to the Clr type of the formal argument
                clrTypeFormalArg = extFunc.GetClrArgumentType(i);
                if (xmlTypeFormalArg.TypeCode == XmlTypeCode.Item || !clrTypeFormalArg.IsAssignableFrom(objActualArgs[i].GetType()))
                {
                    objActualArgs[i] = _runtime.ChangeTypeXsltArgument(xmlTypeFormalArg, objActualArgs[i], clrTypeFormalArg);
                }
            }

            // 1. Invoke the late bound method
            objRet = extFunc.Invoke(instance, objActualArgs);

            // 2. Convert to IList<XPathItem>
            if (objRet == null && extFunc.ClrReturnType == XsltConvert.VoidType)
            {
                return(XmlQueryNodeSequence.Empty);
            }

            return((IList <XPathItem>)_runtime.ChangeTypeXsltResult(XmlQueryTypeFactory.ItemS, objRet));
        }
Exemplo n.º 6
0
 /// <summary>
 /// Infer an Xml type from a Clr type using Xslt inference rules
 /// </summary>
 private XmlQueryType InferXmlType(Type clrType)
 {
     return(XsltConvert.InferXsltType(clrType));
 }