0

Trying to configure a schema so that it will always provide every element, regardless of whether it's populated or not.

I've tried setting the minOccurs to 1 and nillable to true on all elements in the schema, but it still doesn't make a difference. I've tested by passing through a message where the date element in the schema is null, but it still removes the element from the received message.

The payload is picked up via a WCF-SQL Typed Polling port, with the created message then sent direct into the message box for picking up downstream (the process creates a canonical payload accepted by multiple other downstream integrations).

Schema Example;

<xs:element minOccurs="1" name="account_id" nillable="true" type="xs:string" /> 
<xs:element minOccurs="1" name="hus_id" nillable="true" type="xs:string" /> 
<xs:element minOccurs="1" name="date_left" nillable="true" type="xs:date" />

WCF-SQL (Typed Polling) Source Data Example;

account_id - '267336302'
hus_id - ''
date_left - NULL

Received Message Example;

<account_id>267336302</account_id>
<hus_id/>

I've looked over the theory behind it, and in the first two pargraphs of this linked article, it's implied that these settings should make a difference.

BizTalk Mapper: Working With Nillable Values (xsi:nil=”true”) (Sandro's WordPress blog)

Can anyone suggest how I receiving the message with all elements as required (null value or not).

mrc85
  • 73
  • 10
  • Can you give an example schema and payload, and how you are receiving it? e.g. what your pipeline is and if any maps? – Dijkgraaf Jun 09 '22 at 19:04

1 Answers1

0

I was unable to re-produce the issue you are having.

I created a simple schema with on element which is a nillable date.

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://Scratch2.Schema.SO72560754" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" targetNamespace="http://Scratch2.Schema.SO72560754" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="NillableDate" nillable="true" type="xs:date" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

I made a second schema the same except I named the filed simply date.

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://Scratch2.Schema.SO72560754_out" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" targetNamespace="http://Scratch2.Schema.SO72560754_out" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Date" nillable="true" type="xs:date" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

And mapped the two together and deployed it to BizTalk.

I passed the following message through BizTalk with a XMLReceive Pipeline and the map on the Inbound Maps on the Receive Port.

<ns1:Root xmlns:ns1="http://Scratch2.Schema.SO72560754" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <NillableDate xsi:nil="true" />
</ns1:Root>

And got the expected output with the date field still there and being Nill.

<ns0:Root xmlns:ns0="http://Scratch2.Schema.SO72560754_out" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Date xsi:nil="true" />
</ns0:Root>

Note

  1. that there is a difference between empty field (either <Date/> or <Date></Date>) and a field that is Nill (<Date xsi:nil="true" />). If you are doing XML validation the empty dates would fail.
  2. MinOccurs = 1 is the default value if nothing is specified.
  3. If both source and destination elements are mandatory (e.g. must be there), then you don't need to do anything fancy, just map them as you would any other fields and no functoids necessary. It is only if the source is optional and the destination is mandatory that you have to do some fancy workarounds.

SQL

Yes, with the SQL Bindings, if the field is NULL then it will omit the field. A quick and dirty fix would be just to add some concatenate functoids in the map as below and have it concatenate to an empty string. This will produce a XML payload like below. Note: This would fail if you tried to validate it against the schema as an empty string is not a valid date, and also any numeric fields would also fail, but by default, BizTalk does not validate unless you tell it to.

enter image description here

<ns0:Root xmlns:ns0="http://Scratch2.Schema.SO72560754">
    <account_id>267336302 </account_id>
    <hus_id/>
    <date_left/>
</ns0:Root>

If you want to get XML that validates then you can follow Sandro's example, but all you have to do is rather than is the IsNill functoid, is to use the Logical Date Functoid and adjust the logic accordingly (as it inverts the true/false).

Map with logic for missing date

That will produce

<ns0:Root xmlns:ns0="http://Scratch2.Schema.SO72560754" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <account_id>267336302</account_id> 
  <hus_id /> 
  <date_left xsi:nil="true" /> 
</ns0:Root>

You could also use the Logical String and Logical Number functoids if you have fields of that type that you also want to have nillable="true" on.

Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54
  • Thanks, I've edited my original post with examples of the source data, the schema and the output. So based on the above, could the XML Validation be interpreting date_left as an empty string, and cutting it out completely? – mrc85 Jun 10 '22 at 07:31
  • narrowed this down further to the problemn being with the source. Its coming from a typed polling WCF-SQL stored procedure where the date field is null. Min Occurs and nillable are set on this, could that be part of the problem? – mrc85 Jun 22 '22 at 14:27
  • @mrc85 Updated it for the SQL Adapter – Dijkgraaf Jul 05 '22 at 02:56
  • 1
    Thanks - in the end, I amended the source SQL sp, simply swapping out the omitting value with a case statement for another field in its placed (date_left for expected_completion_date). Crude approach, but the service owner is happy with the result! – mrc85 Jul 06 '22 at 07:56