0

I have something like below as input xml. As you can see, the node MIF can come multiple times (one or two times).

<Transactions>
    <Events>
        <Properties>
            <ENT_SUB_TYP />
            <MIF_ACT_PER>Not app</MIF_ACT_PER>
        </Properties>
    </Events>
</Transactions>
<Transactions>
    <Events>
        <Properties> 
            <ENT_SUB_TYP />
            <MIF_ACT_PER>3</MIF_ACT_PER>
        </Properties>
    </Events>
</Transactions>
<Transactions>
    <Events>
        <Properties>
            <ENT_SUB_TYP />
            <MIF_ACT_PER>6</MIF_ACT_PER>
        </Properties>
    </Events>
</Transactions>
<Transactions>
    <Events>
        <Properties>
            <ENT_SUB_TYP />
            <MIF_ACT_PER>3</MIF_ACT_PER>
            <MIF_ACT_PER>6</MIF_ACT_PER>
        </Properties>
    </Events>
</Transactions>

The corresponding JSON output file is supposed to look something like below:

{
  "Transactions": [
    {
      "Events": [
        {
          "Properties": [
            {
              "ENT_SUB_TYP": [
                "NOT_APP"
              ]
            },
            {
              "MIF_ACT_PER": [
                "NOT_APP"
              ]
            }
          ]
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": [
            
            {
              "ENT_SUB_TYP": [
                "NOT_APP"
              ]
            },
            {
              "MIF_ACT_PER": [
                "3"
              ]
            }
          ]
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": [
            
            {
              "ENT_SUB_TYP": [
                "NOT_APP"
              ]
            },
            {
              "MIF_ACT_PER": [
                "6"
              ]
            }
          ]
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": [
            
            {
              "ENT_SUB_TYP": [
                "NOT_APP"
              ]
            },
            {
              "MIF_ACT_PER": [
                "3",
                "6"
              ]
            }
          ]
        }
      ]
    }
  ]
}

Now, I do think that the output schema (showing only the interesting part) is supposed to become something like below but I am only guessing. I dont know how the regular BizTalk JSON translator interprets the output schema.

<Properties>
    <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
</Properties>
<Properties>    
    <MIF_ACT_PER>3</MIF_ACT_PER>
    <MIF_ACT_PER>6</MIF_ACT_PER>
</Properties>

How can I do this in the mapper? No matter how I try I just cant figure out how to use the functoids. And I dont understand XSLT so that goes out of the window as well (at least for me. If anyone understands how to, ie. use xslt and and the scripting functoid, that would be good as well). Any help to solve this issue is greatly appreciated!

Update: This picture represents the faulty output which gives me the '3' and '6' in their own properties node whereas, as stated before, I would like to have them in in one properties node. enter image description here

Update 2: According to Mr. Dijkgraaf's suggestion I am updating the post. Hopefully this time it will be clear enough to understand my issue and also my confusion.

The four example input below are barebones of the real input examples I use during development. Data has been masked.

<?xml version="1.0" encoding="utf-8"?>
<ns0:Masterdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://Masterdata/">
  <EntityType xmlns="">CRD</EntityType>
  <Transactions xmlns="">
    <EntityType>CRD</EntityType>
    <Events>
      <Properties>
        <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
        <MIF_ACT_PER>NOT_APP</MIF_ACT_PER>
      </Properties>
    </Events>
  </Transactions>
</ns0:Masterdata>


<?xml version="1.0" encoding="utf-8"?>
<ns0:Masterdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://Masterdata/">
  <EntityType xmlns="">CRD</EntityType>
  <Transactions xmlns="">
    <EntityType>CRD</EntityType>
    <Events>
      <Properties>
        <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
        <MIF_ACT_PER>3</MIF_ACT_PER>
      </Properties>
    </Events>
  </Transactions>
</ns0:Masterdata>


<?xml version="1.0" encoding="utf-8"?>
<ns0:Masterdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://Masterdata/">
  <EntityType xmlns="">CRD</EntityType>
  <Transactions xmlns="">
    <EntityType>CRD</EntityType>
    <Events>
      <Properties>
        <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
        <MIF_ACT_PER>6</MIF_ACT_PER>
      </Properties>
    </Events>
  </Transactions>
</ns0:Masterdata>


<?xml version="1.0" encoding="utf-8"?>
<ns0:Masterdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns0="http://Masterdata/">
  <EntityType xmlns="">CRD</EntityType>
  <Transactions xmlns="">
    <EntityType>CRD</EntityType>
    <Events>
      <Properties>
        <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
        <MIF_ACT_PER>3</MIF_ACT_PER>
        <MIF_ACT_PER>6</MIF_ACT_PER>
      </Properties>
    </Events>
  </Transactions>
</ns0:Masterdata>

Now, the output of the mapping using the above example with the '4' and '6' gives me below:

<ns0:Masterdata xmlns:ns0="http://Masterdata">
    <Transactions>
        <EntityType>CRD</EntityType>
        <Events>            
            <Properties>
                <ENT_SUB_TYP>NOT_APP</ENT_SUB_TYP>
            </Properties>
            <Properties>
                <MIF_ACT_PER>3</MIF_ACT_PER>
            </Properties>
            <Properties>
                <MIF_ACT_PER>6</MIF_ACT_PER>
            </Properties>
        </Events>
    </Transactions>
</ns0:Masterdata>

The mapping is exactly as the picture in the first update shows. And that mapping gives me, if I use the last example file that contains both the '4' and '6', the JSON below.

{
  "Transactions": [
    {
      "EntityType": "CRD",
      "Events": [
        {
          "Properties": [            
            {
              "ENT_SUB_TYP": [
                "NOT_APP"
              ]
            },
            {
              "MIF_ACT_PER": [
                "3"
              ]
            },
            {
              "MIF_ACT_PER": [
                "6"
              ]
            }
          ]
        }
      ]
    }
  ]
}

Now, regarding the source schema and target schema in the mapping, this is what I did. The source schema worked as a blueprint for the target schema. As you can see, the target schema in the mapping does contain a choice node. So this means that nodes that have data in them (in other words do fulfill the logical string functoid requirement) will be sent to the target and output xml.

Regarding the source and target schema, I really wish that I could share them with you. But a confidentialty clause prevents me from doing that.

I think I could perhaps create a dummy schema but then I am not sure that I would actually be able to implement your suggested solution to the real schema. There really isn't anything particular at all with the schemas except for the choice node in the target schema. I really hope this will be enough.

I have tried to follow Mr. Dijkgraafs solution as to make the target schema as simple as possible but there really is nothing to simplify. (Yes, I am the first to admit that I am far from an expert but still, I do have a few years of experience.)

What can be said about the mapping then? The target system requires every property in the source schema to come as a child node of a properties node. It is easier to show it than to explain it. See picture below.

enter image description here

I am doing something wrong regarding the looping functoid (which results in the 4 and 6 coming in their own Properties node instead of them both coming in one).

I can also tell that my value mapping functoid looks like this: enter image description here

Finally, I hope this will be enough but I am open to suggestions if anyone needs more input. And also, thanks a lot for your patience with me and my incomplete descriptions.

Emperor 2052
  • 517
  • 1
  • 5
  • 14
  • *"I dont understand XSLT so that goes out of the window"* So why tag the question as `xslt`?? – michael.hor257k May 19 '22 at 16:12
  • 1
    Indeed. Spare a thought for your readers. You've added the question to the inbox of everyone who's here to help people with XSLT questions, and right at the end, when we've spent a couple of minutes understanding the problem, you mention that you're not interested in an XSLT solution. That's no way to win friends. – Michael Kay May 19 '22 at 16:27
  • The first thing you need to get right is the schema to get the JSON output you want. Otherwise any mapping you are doing is going to be wrong. So start of by creating the schema, and dropping an XML payload in and pass it through the JSON Encoder, to ensure that the schema is correct. Then try and map it. – Dijkgraaf May 19 '22 at 21:19
  • Also your input XML doesn't have a root node, which is invalid. – Dijkgraaf May 19 '22 at 21:55
  • Hi all. I owe you guys an apology. What I meant with 'out the window' is that I am not able to create the xslt myself. I am interested in an solution (ie. the scripting functoid that creates inline xslt). So sorry for my bad english. I will make sure to edit the question. Regarding the root-node, I thought it would be easier if I try to keep the schema as clean as poosible. There is a lot of namespaces and somewhat confidential things that 'clutter' and I dont want to share. Once again apologies if that makes it more difficult for you guys to understand. I will update ASAP. – Emperor 2052 May 20 '22 at 08:25
  • See my answer below. There is NO NEED for concatenating using XSLT to get an array, the JSON Encoder will do it for you. – Dijkgraaf May 20 '22 at 13:52
  • Thanks a lot, @Dijkgraaf. I am trying to implement your solution but it does not really work for me. The reason seems to be that every node (in the example I gave that is ENT_SUB_TYP) on the source schema is bound to a looping functoid that is connected to the Properties node on the target schema. So if I use your example, the MIF_ACT_PER node is coming out on every ENT_SUB_TYP as well. This is really confusing. As you state, the mapping shouldn't really be that difficult. I updated with a picture to perhaps try to show a bit more. – Emperor 2052 May 20 '22 at 15:44
  • Then you need to give us a proper example of you input XML and expected output. Even better would be example schemas and what mapping you have tried so far and explaining the issue you are having. Also with a schema you expect to go through the JSON encoder, you want to keep it as simple as possible, it doesn't look like you are doing that. Like I said earlier, get your schema that you are going to use in the JSON encoder right first, and after that, try to do the mapping. – Dijkgraaf May 20 '22 at 23:26
  • @Dijkgraaf, I hope the updates are good enough and easy understandable. Thanks for all your efforts helping me with this issue. I can not express me gratitude enough towards you and your patience. – Emperor 2052 May 23 '22 at 08:19

1 Answers1

0

No concatenation needed, you just need to define your schema correctly and the JSON Encoder will put the repeating elements into arrays.

First of all your sample input XML doesn't have a root node, so I'm going to add one as well as a namespace, as without it the JSON Encoder does not use the schema definition and instead gives slightly inconsistent results. If your input doesn't have a namespace, you can have one schema to parse the input, and a second schema that you map to that does have the namespace, or have a Pipeline component add the namespace.

Input

<ns0:Transaction xmlns:ns0="https://SO72306470">
    <Transactions>
        <Events>
            <Properties>
                <ENT_SUB_TYP />
                <MIF_ACT_PER>Not app</MIF_ACT_PER>
            </Properties>
        </Events>
    </Transactions>
    <Transactions>
        <Events>
            <Properties> 
                <ENT_SUB_TYP />
                <MIF_ACT_PER>3</MIF_ACT_PER>
            </Properties>
        </Events>
    </Transactions>
    <Transactions>
        <Events>
            <Properties>
                <ENT_SUB_TYP />
                <MIF_ACT_PER>6</MIF_ACT_PER>
            </Properties>
        </Events>
    </Transactions>
    <Transactions>
        <Events>
            <Properties>
                <ENT_SUB_TYP />
                <MIF_ACT_PER>3</MIF_ACT_PER>
                <MIF_ACT_PER>6</MIF_ACT_PER>
            </Properties>
        </Events>
    </Transactions>
</ns0:Transaction>

Schema that matches this.

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://Scratch2.SO72306470_JSON" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" targetNamespace="http://Scratch2.SO72306470_JSON" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Transactions">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="Events">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Properties">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element minOccurs="0" maxOccurs="unbounded" name="ENT_SUB_TYP" type="xs:string" />
                    <xs:element minOccurs="0" maxOccurs="unbounded" name="MIF_ACT_PER" type="xs:string" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Then it is a fairly simple map where map back to the same schema and you just need a bit of logic to set the ENT_SUB_TYPE when it is empty.

BizTalk Map

And a Send Pipeline with the JSON Encoder, and where you set the RemoveOuterEnvelope to True

Drop through the file and the output is.

{
  "Transactions": [
    {
      "Events": [
        {
          "Properties": {
            "ENT_SUB_TYP": [
              "NOT_APP"
            ],
            "MIF_ACT_PER": [
              "Not app"
            ]
          }
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": {
            "ENT_SUB_TYP": [
              "NOT_APP"
            ],
            "MIF_ACT_PER": [
              "3"
            ]
          }
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": {
            "ENT_SUB_TYP": [
              "NOT_APP"
            ],
            "MIF_ACT_PER": [
              "6"
            ]
          }
        }
      ]
    },
    {
      "Events": [
        {
          "Properties": {
            "ENT_SUB_TYP": [
              "NOT_APP"
            ],
            "MIF_ACT_PER": [
              "3",
              "6"
            ]
          }
        }
      ]
    }
  ]
}
Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54