Reputation: 578
I have created a BizTalk receive location which has a subscribing send port which accepts an enveloped message and splits into separate messages just using the XML Receive Pipeline.
<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace">
<MyData>ABC</MyData>
<MyData>DEF</MyData>
<MyData>GHI</MyData>
</MyEnvelope>
Gets saved as
<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns="MyNameSpace">ABC</MyData>
,
<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns="MyNameSpace">DEF</MyData>
and
<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns="MyNameSpace">GHI</MyData>
which is great.
However, when there are no elements in the message the service sends the message with self-closing and empty envelope:
<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace"/>
And I get the error message
Source: "XML disassembler" Receive Port: "InLocation" URI: "c:\MyLocation*.xml" Reason: Unexpected event ("eos") in state "processing_header".
If I manually create a message which is not self-closing:
<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace"></MyEnvelope>
I get no error. My processing is unaffected by the errors but it must have some performance impact and litters the Group Hub suspended instances view.
It seems that BizTalk interprets self-closing nodes as whitespace instead of null. This seems linked to my issues with attempting to call a service with no parameters where I need to send a self-closing node but BizTalk just sends nothing.
It must be a common issue to handle an envelope with no content. How can I configure my application to pick up and ignore these messages with self-closing envelope nodes?
Upvotes: 5
Views: 1748
Reputation: 1372
Another (very) late answer. It doesn't really answer the OP's question, but since I got here googling the error message and it eventually led me to this solution, I thought I'd answer anyway in case it helps anyone else.
If you have control over the envelope's structure like I did, you can just add another level to the envelope, and it won't result in an error if that's self-closing.
So, this will result in an error:
<MyEnvelope xmlns="MyNameSpace" />
But this won't:
<MyEnvelope xmlns="MyNameSpace">
<Body />
</MyEnvelope>
Set the Body XPath of the schema to this nested level and it should process just fine.
<MyEnvelope xmlns="MyNameSpace">
<Body>
<MyData>ABC</MyData>
<MyData>DEF</MyData>
<MyData>GHI</MyData>
</Body>
</MyEnvelope>
Upvotes: 1
Reputation: 21641
I know this is an old question, but I've encountered the same thing (particularly in SQL XML polling/procedures where an empty resultset is returned). Usually I get around it by making sure SQL isn't called if it would return an empty result set (refine the Data Available statement), but sometimes it's just not entirely possible or foolproof. In the end, I've written a custom pipeline component in the decode stage. It's meant to do the following:
Stream origStream = pInMsg.BodyPart.GetOriginalDataStream();
try
{
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.CheckCharacters = false;
readerSettings.CloseInput = false;
XmlReader reader = XmlReader.Create(origStream, readerSettings);
pContext.ResourceTracker.AddResource(reader);
reader.MoveToContent();
IDocumentSpec docSpec = pContext.GetDocumentSpecByType(reader.NamespaceURI + "#" + reader.LocalName);
if (!string.IsNullOrWhiteSpace(docSpec.GetBodyPath()) && reader.IsEmptyElement) // this is an envelope schema with an empty root node
{
XmlWriterSettings writerSettings = new XmlWriterSettings();
writerSettings.CheckCharacters = false;
writerSettings.OmitXmlDeclaration = true;
MemoryStream ms = new MemoryStream(); // for such a small stream, MemoryStream is perfectly fine - normally use VirtualStream.
pContext.ResourceTracker.AddResource(ms);
XmlWriter writer = XmlWriter.Create(ms, writerSettings);
pContext.ResourceTracker.AddResource(writer);
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
writer.WriteFullEndElement();
writer.Flush();
ms.Position = 0;
pInMsg.BodyPart.Data = ms;
}
}
catch (Exception e)
{
// swallow exception
System.Diagnostics.Debug.WriteLine(e.ToString());
}
finally // make sure we're somewhat well behaved
{
if (pInMsg.BodyPart.Data.CanSeek == true)
pInMsg.BodyPart.Data.Position = 0;
}
Upvotes: 2
Reputation: 11527
Every so often they seem to change the behaviour of how white space is treated. See Change in Default Whitespace Behavior in BizTalk. I'm not sure if your issue is related or not but worth a look. It doesn't mention BizTalk 2013 however but the setting is there in the Host. If you do this configuration setting it would pay to set up a host specially for it so that it has no impact on other existing applications if any.
Installing one of the following updates results in BizTalk changing default behavior to preserve whitespace within the XML during mapping:
In some environments, it may be preferred that the transform remove whitespace. In order to revert to this behavior, the following steps can be taken:
In BizTalk 2010, this is set at the host level:
In BizTalk 2009 and 2006 R2 this value is set at a per-machine level:
Upvotes: 3
Reputation: 11040
I have not seen or verified this behavior but I'll trust you ;).
Don't worry about the performance hit of the Exceptions unless you're getting 10K files per hours or something like that.
To prevent the errors, you'll have to quash or reformat the message in a Pipeline Component.
Upvotes: 2