BizTalk XSLT 映射

BizTalk XSLT mapping

我有两个输入 csv 文件,一个用于会员,一个用于福利,它们如下所示

成员xml长得像

  <Root xmlns="http://TestTwoInput.MemberSchema">
  <Record xmlns="">
  <EmployeeID>12</EmployeeID> 
  <MemberText>MEMBER</MemberText> 
  <SPID>007609952</SPID> 
  <MPID>007609952</MPID> 
  <SAID>12</SAID> 
  <ACode>05</ACode> 
  </Record>
  <Record xmlns="">
  <EmployeeID>14</EmployeeID> 
  <MemberText>MEMBER</MemberText> 
  <SPID>004482352</SPID> 
  <MPID>004482352</MPID> 
  <SAID>14</SAID> 
  <ACode>05</ACode> 
  </Record>
  </Root>

好处xml看起来像

 <Root xmlns="http://TestTwoInput.BenefitSchema">
 <Record xmlns="">
  <EmployeeID>12</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>MEA</BCode> 
  <ELR>001</ELR> 
  <Control>0100189</Control> 
  </Record>
 <Record xmlns="">
  <EmployeeID>12</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>DEN</BCode> 
  <ELR>002</ELR> 
  <Control>0100189</Control> 
  </Record>
 <Record xmlns="">
  <EmployeeID>14</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>DEN</BCode> 
  <ELR>002</ELR> 
  <Control>0100189</Control> 
  </Record>
 <Record xmlns="">
  <EmployeeID>14</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>MEA</BCode> 
  <ELR>001</ELR> 
  <Control>0100189</Control> 
  </Record>
 <Record xmlns="">
  <EmployeeID>14</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>MEA</BCode> 
  <ELR>001</ELR> 
  <Control>0100189</Control> 
  </Record>
 <Record xmlns="">
  <EmployeeID>14</EmployeeID> 
  <BenefitText>BENEFIT</BenefitText> 
  <BCode>DEN</BCode> 
  <ELR>002</ELR> 
  <Control>0100189</Control> 
  </Record>
  </Root>

两个输入都有 EmployeeID 字段。我需要将这两个文件映射到一个输出,就像每个成员及其 Benefit

12,MEMBER,007609952,007609952,12,05
12,BENEFIT,MEA,001,0100189
12,BENEFIT,DEN,002,0100189
14,MEMBER,004482352,004482352,14,05
14,BENEFIT,DEN,002,0100189
14,BENEFIT,MEA,001,0100189
14,BENEFIT,MEA,001,0100189
14,BENEFIT,DEN,002,0100189

这是我的地图 但这会抛出像

这样的输出
12,MEMBER,007609952,007609952,12,05
12,BENEFIT,MEA,001,0100189
12,BENEFIT,DEN,002,0100189
,,,,
,,,,
,,,,
,,,,
14,MEMBER,004482352,004482352,14,05
12,BENEFIT,MEA,001,0100189
12,BENEFIT,DEN,002,0100189
,,,,
,,,,
,,,,
,,,,

在 XSLT 下进行映射

<?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 s1 s0 s2 userCSharp" version="1.0" xmlns:s1="http://TestTwoInput.BenefitSchema" xmlns:ns0="http://TestTwoInput.OutputSchema" xmlns:s0="http://TestTwoInput.MemberSchema" xmlns:s2="http://schemas.microsoft.com/BizTalk/2003/aggschema" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
 <xsl:apply-templates select="/s2:Root" />
</xsl:template>
<xsl:template match="/s2:Root">
<ns0:Root>
  <xsl:for-each select="InputMessagePart_0/s0:Root/Record">
    <Record>
      <Member>
        <EID>
          <xsl:value-of select="EmployeeID/text()" />
        </EID>
        <Text>
          <xsl:value-of select="MemberText/text()" />
        </Text>
        <SPID>
          <xsl:value-of select="SPID/text()" />
        </SPID>
        <MPID>
          <xsl:value-of select="MPID/text()" />
        </MPID>
        <SIAD>
          <xsl:value-of select="SAID/text()" />
        </SIAD>
        <ACode>
          <xsl:value-of select="ACode/text()" />
        </ACode>
      </Member>
      <xsl:for-each select="../../../InputMessagePart_1/s1:Root/Record">
        <xsl:variable name="var:v1" select="userCSharp:LogicalEq(string(EmployeeID/text()) , string(../../../InputMessagePart_0/s0:Root/Record/EmployeeID/text()))" />
        <xsl:variable name="var:v3" select="string(EmployeeID/text())" />
        <xsl:variable name="var:v4" select="string(../../../InputMessagePart_0/s0:Root/Record/EmployeeID/text())" />
        <xsl:variable name="var:v5" select="userCSharp:LogicalEq($var:v3 , $var:v4)" />
        <Benefit>
          <xsl:if test="string($var:v1)='true'">
            <xsl:variable name="var:v2" select="EmployeeID/text()" />
            <ID>
              <xsl:value-of select="$var:v2" />
            </ID>
          </xsl:if>
          <xsl:if test="string($var:v5)='true'">
            <xsl:variable name="var:v6" select="BenefitText/text()" />
            <Text>
              <xsl:value-of select="$var:v6" />
            </Text>
          </xsl:if>
          <xsl:if test="string($var:v5)='true'">
            <xsl:variable name="var:v7" select="BCode/text()" />
            <BCode>
              <xsl:value-of select="$var:v7" />
            </BCode>
          </xsl:if>
          <xsl:if test="string($var:v5)='true'">
            <xsl:variable name="var:v8" select="ELR/text()" />
            <ELR>
              <xsl:value-of select="$var:v8" />
            </ELR>
          </xsl:if>
          <xsl:if test="string($var:v5)='true'">
            <xsl:variable name="var:v9" select="Control/text()" />
            <Control>
              <xsl:value-of select="$var:v9" />
            </Control>
          </xsl:if>
        </Benefit>
      </xsl:for-each>
    </Record>
   </xsl:for-each>
  </ns0:Root>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp"><![CDATA[
public bool LogicalEq(string val1, string val2)
{
bool ret = false;
double d1 = 0;
double d2 = 0;
if (IsNumeric(val1, ref d1) && IsNumeric(val2, ref d2))
{
    ret = d1 == d2;
}
else
{
    ret = String.Compare(val1, val2, StringComparison.Ordinal) == 0;
}
return ret;
}

public bool IsNumeric(string val)
{
 if (val == null)
 {
    return false;
 }
double d = 0;
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}

public bool IsNumeric(string val, ref double d)
{
if (val == null)
{
    return false;
}
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}


]]></msxsl:script>
</xsl:stylesheet>

我不确定如何通过XSLT 实现输出。非常感谢任何帮助

好的。因此,您发布的输入消息与 aggschema 格式中的样子并不完全相同,它应该是这样的:

<Root xmlns="http://schemas.microsoft.com/BizTalk/2003/aggschema">
  <InputMessagePart_0 xmlns="">
    <Root xmlns="http://TestTwoInput.MemberSchema">
      <Record xmlns="">
        <EmployeeID>12</EmployeeID>
        <MemberText>MEMBER</MemberText>
        <SPID>007609952</SPID>
        <MPID>007609952</MPID>
        <SAID>12</SAID>
        <ACode>05</ACode>
      </Record>
      <Record xmlns="">
        <EmployeeID>14</EmployeeID>
        <MemberText>MEMBER</MemberText>
        <SPID>004482352</SPID>
        <MPID>004482352</MPID>
        <SAID>14</SAID>
        <ACode>05</ACode>
      </Record>
    </Root>
  </InputMessagePart_0>
  <InputMessagePart_1 xmlns="">
    <Root xmlns="http://TestTwoInput.BenefitSchema">
      <Record xmlns="">
        <EmployeeID>12</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>MEA</BCode>
        <ELR>001</ELR>
        <Control>0100189</Control>
      </Record>
      <Record xmlns="">
        <EmployeeID>12</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>DEN</BCode>
        <ELR>002</ELR>
        <Control>0100189</Control>
      </Record>
      <Record xmlns="">
        <EmployeeID>14</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>DEN</BCode>
        <ELR>002</ELR>
        <Control>0100189</Control>
      </Record>
      <Record xmlns="">
        <EmployeeID>14</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>MEA</BCode>
        <ELR>001</ELR>
        <Control>0100189</Control>
      </Record>
      <Record xmlns="">
        <EmployeeID>14</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>MEA</BCode>
        <ELR>001</ELR>
        <Control>0100189</Control>
      </Record>
      <Record xmlns="">
        <EmployeeID>14</EmployeeID>
        <BenefitText>BENEFIT</BenefitText>
        <BCode>DEN</BCode>
        <ELR>002</ELR>
        <Control>0100189</Control>
      </Record>
    </Root>
  </InputMessagePart_1>
</Root>

这种情况并不真正严格要求 Muenchian 分组,它只需要对 for-each(BizTalk 中的循环函数)进行更多控制,BizTalk 不允许通过标准映射设计器进行控制。如果您查看输出 XSLT,您会注意到它在 for-each 循环的嵌套方式以及它如何尝试测试 EmployeeID 节点之间的相等性方面做了一些 non-sensical 的事情.以下是自定义 XSLT 的外观,正确嵌套(并删除 BizTalk 生成的和不必要的变量):

<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 s1 s0 s2 userCSharp" version="1.0" xmlns:s1="http://TestTwoInput.BenefitSchema" xmlns:ns0="http://TestTwoInput.OutputSchema" xmlns:s0="http://TestTwoInput.MemberSchema" xmlns:s2="http://schemas.microsoft.com/BizTalk/2003/aggschema" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
  <xsl:output omit-xml-declaration="yes" indent="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="/s2:Root" />
  </xsl:template>
  <xsl:template match="/s2:Root">
    <ns0:Root>
      <xsl:for-each select="InputMessagePart_0/s0:Root/Record">        
        <Record>
          <Member>
            <EID>
              <xsl:value-of select="EmployeeID/text()" />
            </EID>
            <Text>
              <xsl:value-of select="MemberText/text()" />
            </Text>
            <SPID>
              <xsl:value-of select="SPID/text()" />
            </SPID>
            <MPID>
              <xsl:value-of select="MPID/text()" />
            </MPID>
            <SIAD>
              <xsl:value-of select="SAID/text()" />
            </SIAD>
            <ACode>
              <xsl:value-of select="ACode/text()" />
            </ACode>
          </Member>
          <xsl:variable name="empID" select="EmployeeID" />
          <xsl:for-each select="../../../InputMessagePart_1/s1:Root/Record[EmployeeID = $empID]">
            <Benefit>              
              <ID>
                <xsl:value-of select="EmployeeID/text()" />
              </ID>
              <Text>
                <xsl:value-of select="BenefitText/text()" />
              </Text>
              <BCode>
                <xsl:value-of select="BCode/text()" />
              </BCode>
              <ELR>
                <xsl:value-of select="ELR/text()" />
              </ELR>
              <Control>
                <xsl:value-of select="Control/text()" />
              </Control>
            </Benefit>
          </xsl:for-each>
        </Record>
      </xsl:for-each>
    </ns0:Root>
  </xsl:template>
</xsl:stylesheet>

这将为您提供以下输出:

<ns0:Root xmlns:ns0="http://TestTwoInput.OutputSchema">
   <Record>
      <Member>
         <EID>12</EID>
         <Text>MEMBER</Text>
         <SPID>007609952</SPID>
         <MPID>007609952</MPID>
         <SIAD>12</SIAD>
         <ACode>05</ACode>
      </Member>
      <Benefit>
         <ID>12</ID>
         <Text>BENEFIT</Text>
         <BCode>MEA</BCode>
         <ELR>001</ELR>
         <Control>0100189</Control>
      </Benefit>
      <Benefit>
         <ID>12</ID>
         <Text>BENEFIT</Text>
         <BCode>DEN</BCode>
         <ELR>002</ELR>
         <Control>0100189</Control>
      </Benefit>
   </Record>
   <Record>
      <Member>
         <EID>14</EID>
         <Text>MEMBER</Text>
         <SPID>004482352</SPID>
         <MPID>004482352</MPID>
         <SIAD>14</SIAD>
         <ACode>05</ACode>
      </Member>
      <Benefit>
         <ID>14</ID>
         <Text>BENEFIT</Text>
         <BCode>DEN</BCode>
         <ELR>002</ELR>
         <Control>0100189</Control>
      </Benefit>
      <Benefit>
         <ID>14</ID>
         <Text>BENEFIT</Text>
         <BCode>MEA</BCode>
         <ELR>001</ELR>
         <Control>0100189</Control>
      </Benefit>
      <Benefit>
         <ID>14</ID>
         <Text>BENEFIT</Text>
         <BCode>MEA</BCode>
         <ELR>001</ELR>
         <Control>0100189</Control>
      </Benefit>
      <Benefit>
         <ID>14</ID>
         <Text>BENEFIT</Text>
         <BCode>DEN</BCode>
         <ELR>002</ELR>
         <Control>0100189</Control>
      </Benefit>
   </Record>
</ns0:Root>

这里有一个上面的 XSLTransform 可以玩:http://xsltransform.net/3NSSEvs

您可能会通过使用一些 xsl:keys(Muenchian 分组)获得更好的性能 - 如果您打算在更大的文档结果集上​​使用它,请对此进行一些研究;但如果您的文件看起来像您通常发送到这里的文件,那么您应该没问题。老实说,如果它们变得非常大,我会建议在源代码处进行重构,而不是尝试使用 XSLT 来解决所有问题——如果可能的话,限制生成平面文件的任何过程(如果可能的话,可能在 SQL 中做更多的工作)这是来自 SQL 通过它实际合并一些数据 and/or 页面),或者用 C# 编写一个自定义组件来处理合并它们比 XSLT 引擎最终能够更有效地完成.