导航

Biztalk------XSLT脚本实现Sum,Sort复杂逻辑

Posted on 2009-07-28 15:02  鸡尾虾的壳  阅读(503)  评论(0编辑  收藏  举报

问题描述:在一些Biztalk Map中,需要基于Source中的复杂逻辑,而非某个存在的简单节点,在Target中对元素进行Sum, Sort操作。
解决方案:在Inline C#中定义全局集合对象保存中间计算结果,基于这个中间结果进行输出计算。

代码实例:
Inline C#:
System.Collections.Hashtable hsFreight=new System.Collections.Hashtable( );
System.Collections.Hashtable hsManifestQty=new System.Collections.Hashtable( );
System.Collections.Hashtable hsWeight=new System.Collections.Hashtable( );
public string GenerateGlobalHS()
{
    return "";
}
  
public string AddItem(string keyOfItem,string itemFreight,string itemManifestQty,string itemWeight)
{
   string tempItemFreight=itemFreight.Replace(",","");
   string tempManifestQty=itemManifestQty.Replace(",","");
   string tempWeight=itemWeight.Replace(",","");
   if(hsFreight.Contains(keyOfItem))
   {
      string currentSumOfFreight=(string)hsFreight[keyOfItem];
      double intItemFreight=0;
      if(itemFreight.Trim( )!="")
      {
         intItemFreight=double.Parse(tempItemFreight);
      }
      double latestSumOfFreight=double.Parse(currentSumOfFreight)+intItemFreight;
      hsFreight.Remove(keyOfItem);
      hsFreight.Add(keyOfItem,latestSumOfFreight.ToString( ));
      string currentSumOfManifestQty=(string)hsManifestQty[keyOfItem];
      double intItemManifestQty=0;
      if(itemManifestQty.Trim( )!="")
      {
         intItemManifestQty=double.Parse(tempManifestQty);
      }
      double latestSumOfManifestQty=double.Parse(currentSumOfManifestQty)+intItemManifestQty;
      hsManifestQty.Remove(keyOfItem);
      hsManifestQty.Add(keyOfItem,latestSumOfManifestQty.ToString( ));
      string currentSumOfWeight=(string)hsWeight[keyOfItem];
      double intItemWeight=0;
      if(itemWeight.Trim( )!="")
      {
         intItemWeight=double.Parse(tempWeight);
      }
      double latestSumOfWeight=double.Parse(currentSumOfWeight)+intItemWeight;
      hsWeight.Remove(keyOfItem);
      hsWeight.Add(keyOfItem,latestSumOfWeight.ToString( ));
   }
   else
   {
      if(itemFreight.Trim( )!="")
      {
         hsFreight.Add(keyOfItem,tempItemFreight);
      }
      if(itemManifestQty.Trim( )!="")
      {
         hsManifestQty.Add(keyOfItem,tempManifestQty);
      }
      if(itemWeight.Trim( )!="")
      {
         hsWeight.Add(keyOfItem,tempWeight);
      }
   }
   return "";
}
public string GetSumFreight(string keyItem)
{
       return (string)hsFreight[keyItem];
}
public string GetSumManifestQty(string keyItem)
{
     return (string)hsManifestQty[keyItem];
}
public string GetSumWeight(string keyItem)
{
      return (string)hsWeight[keyItem];
}


Inline XSLT Call Template:
<xsl:template name="FullTemplate">
   <xsl:param name="orginalF"/>
   <xsl:param name="outputF"/>
   <xsl:variable name="temp1" select="userCSharp:GenerateGlobalHS( )"/>
  
   <xsl:for-each select="s5:postadv_msg_root">
       <xsl:for-each select="s5:postadv_cntr">
           <xsl:for-each select="s5:postadv_item">
               <xsl:variable name="po" select="s0:po_num/s0:po_num"/>
               <xsl:variable name="container" select="../s5:cntr/s0:CNTR_NUM"/>
               <xsl:variable name="bl" select="s4:doc[s0:doc_type_code='OBL']/s0:doc_num"/>
               <xsl:variable name="key" select="concat($po,$container,$bl)"/>
               <xsl:variable name="freight" select="s4:ocean_freight/s0:amt"/>
               <xsl:variable name="manifestqty" select="s0:outer_uom_qty"/>
               <xsl:variable name="weight" select="s0:outer_uom_measurement/s0:wgt"/>
               <xsl:variable name="temp2" select="userCSharp:AddItem($key,$freight,$manifestqty,$weight)"/>
           </xsl:for-each>
      </xsl:for-each>
   </xsl:for-each>
     
   <xsl:for-each select="s5:postadv_msg_root/s5:postadv_cntr/s5:postadv_item">
               <xsl:sort  select="ScriptNS0:CodeConversionWithDefaultValue('olltrafficmode-hobbylobbytype',../s5:mov/s0:mov_type_code,'')"/>
               <xsl:sort  select="../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:vessel[1]/s0:vessel_name"/>
               <xsl:sort  select="concat(../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:vessel[1]/s0:vessel_code,../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:voyage_no)"/>
               <xsl:sort  select="ScriptNS0:toUpperCase(string(s4:fnd/s0:LOC_NAME/text()))"/>
               <xsl:sort  select="s4:vdr/s0:PARTNER_NAME/text()" />
               <xsl:sort select="s0:po_num/s0:po_num"/>
               <xsl:sort  select="../s5:cntr/s0:CNTR_NUM"/>
              
               <xsl:variable name="po" select="s0:po_num/s0:po_num"/>
               <xsl:variable name="container" select="../s5:cntr/s0:CNTR_NUM"/>
               <xsl:variable name="bl" select="s4:doc[s0:doc_type_code='OBL']/s0:doc_num"/>
               <xsl:variable name="key" select="concat($po,$container,$bl)"/>
               <xsl:variable name="eatDt" select="ScriptNS0:ConvertDatetimeFormat(s4:ship_window/s0:fnd_eta_date/s0:record_datetime,$orginalF,$outputF,'','')"/>
               <xsl:element name="PostItem">
                   <xsl:element name="Vessel">
                       <xsl:value-of select="../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:vessel[1]/s0:vessel_name"/>
                   </xsl:element>
                   <xsl:element name="Voy">
                       <xsl:value-of select="concat(../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:vessel[1]/s0:vessel_code,../s5:transportation[number(count(../s5:transportation))]/s0:voyage[1]/s0:voyage_no)"/>
                   </xsl:element>
                   <xsl:element name="FND">
                       <xsl:value-of select="ScriptNS0:toUpperCase(string(s4:fnd/s0:LOC_NAME/text()))"/>
                   </xsl:element>
                   <xsl:element name="ETA">
                       <xsl:value-of select="$eatDt"/>
                   </xsl:element>
                   <xsl:element name="Shipper">
                       <xsl:value-of select="s4:vdr/s0:PARTNER_NAME/text()" />
                   </xsl:element>
                   <xsl:element name="PO">
                       <xsl:value-of select="s0:po_num/s0:po_num"/>
                   </xsl:element>
                   <xsl:element name="Container">
                       <xsl:value-of select="../s5:cntr/s0:CNTR_NUM"/>
                   </xsl:element>
                   <xsl:element name="Container_Size">
                       <xsl:value-of select="../s5:cntr/s0:CNTR_CODE"/>
                   </xsl:element>
                   <xsl:element name="Type">
                       <xsl:value-of select="ScriptNS0:CodeConversionWithDefaultValue('olltrafficmode-hobbylobbytype',../s5:mov/s0:mov_type_code,'')"/>
                   </xsl:element>
                   <xsl:element name="BL">
                       <xsl:value-of select="s4:doc[s0:doc_type_code='OBL']/s0:doc_num"/>
                   </xsl:element>
                   <xsl:variable name="tempFreight" select="userCSharp:GetSumFreight($key)"/>
                   <xsl:element name="Freight">
                       <xsl:value-of select="ScriptNS1:NumberFixedPointFormat($tempFreight,1,0)"/>
                   </xsl:element>
                   <xsl:element name="Division">
                       <xsl:value-of select="userCSharp:division($po)"/>
                   </xsl:element>
                  
                   <xsl:variable name="tempManifest_qty" select="userCSharp:GetSumManifestQty($key)"/>
                   <xsl:element name="Manifest_qty">
                       <xsl:value-of select="ScriptNS1:NumberFixedPointFormat($tempManifest_qty,1,0)"/>
                   </xsl:element>
                  
                   <xsl:variable name="tempWeight" select="userCSharp:GetSumWeight($key)"/>
                   <xsl:element name="Weight">
                       <xsl:value-of select="ScriptNS1:NumberFixedPointFormat($tempWeight,1,0)"/>
                   </xsl:element>
               </xsl:element>
           </xsl:for-each>
</xsl:template>

External Assemble:ScriptNS0,ScriptNS1分别代表2个包含特殊处理逻辑的外部C# Call Library。

Note:<xsl:for-each select="s5:postadv_msg_root/s5:postadv_cntr/s5:postadv_item">如果拆分为3个for-each,逻辑语义是不同的。