Search code examples
xslt-1.0biztalkbiztalk-2013

BizTalk Map: xslt 1.0 sum "Cannot implicitly convert type 'string' to 'int'"


Get error:

Cannot implicitly convert type 'string' to 'int'

on this code:

<TotalInvoiceCost>
    <xsl:value-of select="sum(//*[local-name()='InvoiceTotal'])" />
</TotalInvoiceCost>

Then tried this:

   <TotalInvoiceCost>
      <xsl:value-of select="sum(number(//*[local-name()='InvoiceTotal']))" />
   </TotalInvoiceCost>

but get this error:

Argument 1 of function 'sum()' cannot be converted to a node-set.

Cut Down Sample Data with Structure (all values are numeric):

<TAR210 xmlns="demo">
    <DummyHeaderGroup xmlns=""/>
    <Invoice xmlns="">
        <Level1>
            <InvoiceTotal>1075</InvoiceTotal>
        </Level1>
        <Level1>
            <InvoiceTotal>595</InvoiceTotal>
        </Level1>
    </Invoice>
</TAR210>

In http://www.xpathtester.com/xpath, this works fine:

sum(//*[local-name()="InvoiceTotal"])

Example of XSLT in context:

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
  exclude-result-prefixes="msxsl var userCSharp" version="1.0"
  xmlns:ns0="demo"
  xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">

  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />

  <xsl:template match="/">
    <ns0:TAR210>
      <DummyHeaderGroup>
        <Level0>
          <TotalInvoiceCost>
            <xsl:value-of select="sum(//*[local-name()='InvoiceTotal'])" />
          </TotalInvoiceCost>
        </Level0>
      </DummyHeaderGroup>
    </ns0:TAR210>
  </xsl:template>

</xsl:stylesheet>

Solution

  • Well, the real world program is typically more complex than what we post on the web when we have a problem; I tried to simplify. The error had nothing to do with the code I posted.

    To me, it seems like the biggest issue is that the error from the "Test Map" in Visual Studio doesn't give any hint to the line number with the error.

    <Level0>
      <BatchNumberLeaveBlank></BatchNumberLeaveBlank>
      <InvoiceSendDateCCYYMM>
        <!-- Get current CCYYMM -->
              <!-- Current-DateTime doesn't exist in XSLT 1.0, had to use C# 
              <xsl:value-of  select="concat(substring(current-dateTime(),1,4),substring(current-dateTime(),6,2))"/>
              --> 
              <xsl:value-of  select="userCSharp:GetDateCCYYMM()"/>
      </InvoiceSendDateCCYYMM>
      <DefaultValueN>N</DefaultValueN>
      <TotalInvoiceCost>...
    

    Then I had the C# code below:

      <msxsl:script language="C#" implements-prefix="userCSharp">
    <![CDATA[ int lineCount = 0;
    
    public int GetDateCCYYMM()
       {
           return DateTime.Now.ToString("yyyyMMdd");
       }
    
      ]]> 
      </msxsl:script>
    

    Obviously, the "public int" should have been "public string" above.

    The only way I know how to tackle these problems is the "divide and conquer" method. I made a copy of the XSLT, named it same with _Debug.xslt, changed the BizTalk map to use it instead, and started ripping out lines of code left and right until the error goes away. Even removing the call to the c# didn't remove the error, so it must have been running a .NET compile or syntax check on the code.