2017-01-17 10 views
0

У меня есть два входных CSV файлы один за член и один на благо они выглядят, как показано ниже enter image description hereBizTalk отображение XSLT

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> 

Benefit 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 

Это моя карта enter image description here Но это бросает выход как

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. Любая помощь с этим оценивается

+1

Возможно, вы неоднократно публиковали этот вопрос несколько разными формулировками. Если вам нужна помощь в решении проблемы XSLT, включите источник __XML__ (например, ваш собственный плоский файл через BizTalk) и ваш ожидаемый вывод __XML__, а также ваш XSLT (который, как представляется, включен сюда и в некоторых других сообщениях) , Пожалуйста, вернитесь назад и удалите похожие вопросы, если они не являются конструктивными ... –

+0

@DanField Я удалил свой предыдущий вопрос, прежде чем я разместил его здесь. Я редактировал свой вопрос с помощью входных XML. Пожалуйста, помогите мне с этим – trx

ответ

1

Ok. Так что ваше входное сообщение, как писал не совсем то, что было бы выглядеть в формате 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. Вот как пользовательский 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:key s (Muenchian grouping) - сделайте некоторое исследование по этому вопросу, если вы собираетесь использовать это на больших результирующих документах; но если ваши документы выглядят так, как вы обычно отправляли здесь, вы должны быть в порядке. Если честно, если они будут существенно большими, я бы посоветовал рефакторинг вещей у источника, а не пытаться решить все это с помощью XSLT - ограничивая, какой бы процесс не производил плоские файлы, если это возможно (возможно, больше работайте в SQL, если это происходит из SQL, чтобы фактически объединить некоторые данные и/или страницу через него) или написать пользовательский компонент на C#, чтобы обрабатывать их слияние более эффективно, чем в XSLT-движке.

+0

Спасибо a Dan. Я очень новичок в XSLT-сопоставлении. На моей текущей карте следует удалить все ссылки между схемой ввода и вывода и просто использовать XSLT-код. Как вы сказали, источником является представление из базы данных Oracle, а запись участника - почти 2000 записей, а преимущества - 12000 записей. – trx

+0

При использовании пользовательского компонента C#. Может ли это использоваться при отображении. – trx

+0

Я бы полностью избегал карты для этого тома. XSLT не будет хорошо масштабироваться, карта будет использовать массу памяти. Вы должны искать лучшие способы подготовить свои данные в SQL или обработать их в потоковом компоненте конвейера, используя что-то вроде 'XmlReader'. –