windowsdelphixsltmsxmlmsxml6

What is the biggest number that MSXML can handle in XSLT?


When doing some numerical calculations in XSL templates I stumbled over the fact that a value of 3.600.000.000 which represents the number of microseconds in an hour can be represented in MSXML v6 when running as a 32-bit application, but not when running as a 64-bit application.

What is the biggest number which can be represented by XSLT in 32-bit, and in 64-bit mode? Why is it different?

For reference the XSL template I used for testing was:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

   <xsl:variable name="hours" select="1.0"/>
   <xsl:variable name="minutes" select="number(60.0 * $hours)"/>
   <xsl:variable name="seconds" select="number(60.0 * $minutes)"/>
   <xsl:variable name="milliseconds" select="number(1000.0 * $seconds)"/>
   <xsl:variable name="microseconds" select="number(1000.0 * $milliseconds)"/>

   <xsl:template match="/">
      <output>
         <value>
            <xsl:value-of select="round($microseconds)"/>
         </value>
      </output>
   </xsl:template>

</xsl:stylesheet>

Delphi function to perform XSL transformation:

function TransformMsXmlDocument( XmlDoc, XslDoc: iXmlDomDocument2 ) : UnicodeString;
var
   XslDoc2 : iXmlDomDocument2;
   XslTemplate : iXslTemplate;
   XslProcessor : iXslProcessor;
begin
   XslDoc2 := CoFreeThreadedDomDocument60.Create();
   XslDoc2.Async := FALSE;
   XslDoc2.SetProperty('AllowDocumentFunction', TRUE);
   XslDoc2.Load(XslDoc);

   XslTemplate := CoXslTemplate60.Create();
   XslTemplate.Stylesheet := XslDoc2;
   XslProcessor := XslTemplate.CreateProcessor();
   XslProcessor.Input := XmlDoc;

   XslProcessor.Transform();
   Result := XslProcessor.Output;
end;

When performing the transformation within a 32-bit application the generated output is:

<?xml version="1.0"?>
<output>
<value>3600000000</value>
</output>

When performing the transformation within a 64-bit application an exception is thrown:

OLE error C0000090


Solution

  • As pointed out by Martin Honnen in the comment section, XSL Transformation uses the expression language defined by XPath. In XPath 1.0 numbers are defined to use the double-precision 64-bit IEEE 754 number type. The largest decimal number is 1.7976931348623157e+308 with about 15 significant digits, see en.wikipedia.org/wiki/Double-precision_floating-point_format.

    The different output between running MSXML in 32-bit and 64-bit mode can be caused by subtle differences in how floating point exceptions are handled by default in Delphi compared to C compilers. In Delphi before version 12 "Athens" some float operations (like division by zero) do trigger an exception by default, while in C they do not. For compatibility with MSXML libraries float exceptions should be disabled using SetExceptionMask on application startup (Note: calling this function is not thread-safe).