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.

有帮助吗?

解决方案

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>

其他提示

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.

<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>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top