2

I am debatching an incoming xml messages in BizTalk receive pipeline using an envelope schema. The debatching works well for any xml that contains the sub message I am trying to debatch but fails if the message does not contain any sub message.

I have set the "min occurs" to 0 and nillable = true in the schema for the elements that are in the xpath for debatching. In the sample below the "entry" and "resource" elements have min occurs set to 0, which I thought would let the debatching function work when there is nothing to be debatched.

Here is the annotation for the envelope schema.

<xs:annotation>
   <xs:appinfo>
     <schemaInfo xmlns="http://schemas.microsoft.com/BizTalk/2003" is_envelope="yes"/>
   </xs:appinfo>
</xs:annotation>
<xs:element name="Bundle">
   <xs:annotation>
      <xs:appinfo>
         <recordInfo xmlns="http://schemas.microsoft.com/BizTalk/2003" body_xpath="/*[local-name()='Bundle' and namespace-uri()='']/*[local-name()='entry' and namespace-uri()='']/*[local-name()='resource' and namespace-uri()='']"/>
     </xs:appinfo>
</xs:annotation>

Example message with no messages to debatch

<Bundle >
   <type value="searchset"/>
   <total value="0"/>
</Bundle>

Example of xpath for debatching when sub messages are present.

<Bundle >
   <type value="searchset"/>
   <total value="46"/>
   <entry>
       <resource>
           <Encounter>

Any message that contains the entry/resource/encounters element debatches successfully, but the messages that do not contain the "entry" element ( has no messages to debatch) throw the error below.

Reason: This Disassembler cannot retrieve body nodes using this XPath: "/[local-name()='Bundle' and namespace-uri()='']/[local-name()='entry' and namespace-uri()='']/[local-name()='resource' and namespace-uri()='']". /[local-name()='Bundle' and namespace-uri()='']/[local-name()='entry' and namespace-uri()='']/[local-name()='resource' and namespace-uri()='']

I would expect the messages with nothing to debatch to simply "disappear", but instead I end up with an error in group hub. Any ideas or suggestion on how to get rid of this error would be greatly appreciated.

Ed Bangga
  • 12,879
  • 4
  • 16
  • 30
David
  • 139
  • 1
  • 13

2 Answers2

2

You can use below body_xpath to extract only the 'Bundle' with 'entry' records

body_xpath="/*[local-name()='Bundle' and namespace-uri()=''][*[local-name()='entry' and namespace-uri()=''][count(*)>0]]/*[local-name()='entry' and namespace-uri()='']/*[local-name()='resource' and namespace-uri()='']"

or

body_xpath="/*[local-name()='Bundle' and namespace-uri()=''][*[local-name()='entry' and namespace-uri()=''][count(*)&gt;0]]/*[local-name()='entry' and namespace-uri()='']/*[local-name()='resource' and namespace-uri()='']"
Ed Bangga
  • 12,879
  • 4
  • 16
  • 30
  • This makes sense now that I see it. I didn't know it was possible to do so much with the body_xpath. Thanks – David Aug 20 '19 at 23:41
  • Trying to apply this solution but get "Unexpected XPath format" when trying to debatch in XMLReceive pipeline. I am using auto-generated typedprocedure schemas, trying to specify response as envelope with zero-to-may results. – JERKER May 11 '20 at 08:44
  • This is the xpath I am trying to use (BizTalk 2016, works in many xpath testers online): /*[local-name()='bizTalk_SelectOrdersResponse' and namespace-uri()='http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo'][*[local-name()='StoredProcedureResultSet0' and namespace-uri()='http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo'][count(*)>0]]/*[local-name()='StoredProcedureResultSet0' and namespace-uri()='http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo'] – JERKER May 11 '20 at 09:48
  • Solution was to build a new decode pipeline component and custom pipeline to add Body XPath node if missing from the XML before XML Disassembler is run. So, mission to add as less custom code as possible failed. – JERKER May 14 '20 at 08:55
1

That is because you are pointing the body at the resource node, which does not even exists when there is no message to debatch. You need to be pointing at the a node that always exists in the envelope under which the body messages occur.

What you probably need is the following for emtpy

<Bundle >
   <type value="searchset"/>
   <total value="0"/>
   <entries/>
</Bundle>

and the following for messages.

<Bundle >
   <type value="searchset"/>
   <total value="46"/>
   <entries>
       <entry>
           <resource>
               <Encounter>

And point your body_xpath at entries.

Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54
  • I don't have control over the API I'm calling but I'll see if I can get the provider of the API to change the response to contain the empty element, It would be much easier to deal with. Thanks! – David Aug 20 '19 at 23:47
  • Is there no way to get typedprocedure-calls to handle when procedure returns zero rows? You could think that a WCF-SQL-adapter should be able to handle this...? – JERKER May 12 '20 at 10:12
  • @JERKER It does handle this last I checked. If you have an issue with it, post a question about it. Or is this to do with your question https://stackoverflow.com/questions/61651801/biztalk-orchestration-to-receive-multiple-messages-from-xmlreceive-pipeline-from – Dijkgraaf May 12 '20 at 20:25
  • @Dijkgraaf Works for typedpolling, since you have PollingAvailable to make sure Polling statement always return rows. But for typedprocedure it omits elements with no data, making Body XPath crash when trying to debatch. I think, as to this example, WCF-SQL adapter should have kept/created element if schema tells it is mandatory. But it does not, so debatching fails. – JERKER May 13 '20 at 06:41
  • Solution was to build a new decode pipeline component and custom pipeline to add Body XPath node if missing from the XML before XML Disassembler is run. So, mission to add as less custom code as possible failed. – JERKER May 14 '20 at 08:56