2

I have this schema:

<Root>
  <Customers>
    <Customer>
      <ID>123</ID>
      <Name>John</Name>
    </Customer>
  </Customers>
  <Order>
    <ID>ABC</ID>
    <Title>Boat</Title>
  </Order>
</Root>

I need to map the two different records into one repeating record like this:

<Root>
  <Data>
    <ID>123</ID>
    <Text>John</Text>
  </Data>
  <Data>
    <ID>ABC</ID>
    <Text>Boat</Text>
  </Data>
</Root>

I tried to create two table loopings (one for Customer, one for Order) and got:

<Root>
  <Data>
    <ID>ABC</ID>
    <Text>Boat</Text>
  </Data>
</Root>

Tried one table looping with two rows, and got the same. (Tried also with the Gated option to check for existance which made no difference)

In reality the schemas are huge, the map is super complex (not built by me), has a lot of functoids, and many wires. So I would like to avoid creating a custom XSL, which will be easier for this task, but harder to maintain. This is the only part I need to change.

Anybody ? Thanks.

3 Answers3

3

For complex mapping, using a custom XSLT almost always ends up being simpler and more maintainable than the spider-web we often find in BizTalk maps. However, as you stated, you need to avoid re-coding the complete map, as you are only changing a small section.

You should be able to use the 'Inline XSLT Call Template' script type in the Scripting Functoid to combine the best of BizTalk maps and custom XSLT.

Extending from Sean B. Durkin's answer, you will need to set up 2 Call Template functoids, the first one wired to your output 'Data' node

<xsl:template name="DataTemplate">
    <xsl:apply-templates select="//*[local-name()='Customer']|//*[local-name()='Order']" />
</xsl:template>

Your second Call Template will output the relevant data into the current output 'Data' node. Note, this second Functoid does not need to be wired to any node in your output document.

<xsl:template match="*[local-name()='Customer']|*[local-name()='Order']">
    <xsl:element name="Data">
      <xsl:element name="ID">
          <xsl:value-of select="*[local-name()='ID']"/>
      </xsl:element>
      <xsl:element name="Text">
          <xsl:value-of select="*[local-name()='Name']|*[local-name()='Title']" />
      </xsl:element>
    </xsl:element>
</xsl:template>
Brett
  • 1,127
  • 6
  • 11
  • Hi guys, thanks for your quick reply, Sean, your solution looks great if I used the custom XSL option, haven't tried it though. Brett, I tried it, wiring the two script functoids to the Data node, but I got the following output: 125 Name_0 ID_0 Title_0 Seems like it's getting there though. Trying to play with this solution a bit more. Will update if I can solve this. Any suggestions ? Thanks again. – Roei Finkelstein Sep 05 '12 at 06:37
  • I have updated my answer a little in response to your feedback. Additionally, you only want to wire the first Call Template functoid to the output document schema, the second one just sits there on the design surface, unconnected, but still gets called by the first functoid automagically. – Brett Sep 05 '12 at 06:38
  • Thanks for the quick answer :) got exactly what I needed. Now just have to apply this to the real thing... Good luck to me. Cheers again. – Roei Finkelstein Sep 05 '12 at 06:50
2

No need to use XSLT here. Simply drag a Looping functoid on the map. Connect both the Customer and the Order record as inputs to the functoid (yes, you can have multiple inputs). Connect the output of the functoid to the Data record. Then connect your fields directly (ID --> ID, Name --> Text). This will work.

The individual input records to a Looping functoid don't have to be repeating records in themselves. By connecting multiple inputs to the functoid, you are looping over the collection of instances.

Dan Toomey
  • 61
  • 5
  • This is the simplest solution and more maintainable for folks who don't have much XSLT experience. – Matt Milner May 15 '15 at 20:36
  • If you have a Pluralsight subscription, the 2nd clip in module 5 of this course covers this topic: http://www.pluralsight.com/courses/using-functoids-biztalk-2013-mapper – Dan Toomey Jul 02 '15 at 21:50
1
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
 <Root>
   <xsl:apply-templates select="*/Customers/Customer|*/Order"/>
 </Root>
</xsl:template>

<xsl:template match="Customer|Order">
 <Data>
   <ID><xsl:value-of select="ID" /></ID>
   <Text><xsl:value-of select="Name|Title" /></Text>
 </Data>
</xsl:template>

</xsl:stylesheet>
Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65