Search code examples
biztalkbiztalk-mapper

Mapping multiple source structures to a single looping destination structure in BizTalk


I am trying to map parts of the following source structure that has two sets of properties - one flat and one looped:

Source Document

<root>
  <flat>
    <prop1>foo</prop1>
    <prop2>bar</prop2>
    ...
  </flat>
  <loop>
    <prop>
      <qual>propA</qual>
      <data>baz</data>
      <more>blah</more>
    </prop>
    <prop>
      <qual>propB</qual>
      <data>qux</data>
      <more>bhal</more>
    </prop>
    ...
  </loop>
</root>

Specifically, the flat part is the PO1 segment of an X12 850 EDI document, and the looping properties are the subsequent REF segments.

These should be mapped to a looping destination structure of key-value pairs that looks like this:

Destination Document

<root>
  <props>
    <prop>
      <name>prop1</name>
      <value>foo</value>
    </prop>
    <prop>
      <name>propA</name>
      <value>baz</value>
    </prop>
  </props>
</root>

I would like to map only some of the values, depending on the property name.

What I've Tried

I have successfully mapped the flat portion to the destination using a table looping functoid and two table extractor functoids:

Flat properties mapped to options

I have also successfully mapped the looping portion to the destination using a looping functoid and some equality checks to select only certain qual values:

Looped properties mapped to options

When I attempt to include both of these mappings at the same time, the map succeeds, but doesn't generate the combined output.

The Question

How I can I map both sections of the source document to the same looping section in the destination document?

Update 1

Turns out I had oversimplified the problem; the flat group of properties actually contains the property name in one node and the value in another node. This is what they actually look like:

<flat>
  <name1>prop1</name1>
  <value1>foo</value1>
  <name2>prop2</name2>
  <value2>bar</value2>
  ...
</flat>

The concept of @Dijkgraaf's answer still works with this change if you use a Value Mapping (Flattening) functoid to get the property name from the correct location.


Solution

  • Usually the only way to solve this is with either

    • Inline Custom XSLT via the Scripting Functoid
    • Custom XSLT setting Custom XSLT Path for the whole map
    • Having an intermediate schema that contains two Option nodes and having two maps. The first that maps the flat structure to one node and the looping to the second. Then a second map that loops across both and maps to to the same node.
    • In your case however, you need to have both (prop1,prop2,..) and the looping prop linked to the same looping functoid, and linking to the name and value and setting the link properties on the links from prop1,prop2 etc. to Copy name instead of value.

    enter image description here enter image description here

    With your sample input that gives

    <root>
        <props>
            <prop>
                <name>prop1</name>
                <value>foo</value>
            </prop>
            <prop>
                <name>prop2</name>
                <value>bar</value>
            </prop>
            <prop>
                <name>propA</name>
                <value>baz</value>
            </prop>
            <prop>
                <name>propB</name>
                <value>qux</value>
            </prop>
        </props>
    </root>