BizTalk envelope schema self-closing node
我创建了一个 BizTalk 接收位置,它有一个订阅发送端口,该端口接受封装的消息并仅使用 XML 接收管道拆分成单独的消息。
1 2 3 4 5 6 | <?xml version="1.0" encoding="utf-8"?> <MyEnvelope xmlns="MyNameSpace"> <MyData>ABC</MyData> <MyData>DEF</MyData> <MyData>GHI</MyData> </MyEnvelope> |
保存为
1 2 | <?xml version="1.0" encoding="utf-8"?> <MyData xmlns="MyNameSpace">ABC</MyData> |
,
1 2 | <?xml version="1.0" encoding="utf-8"?> <MyData xmlns="MyNameSpace">DEF</MyData> |
和
1 2 | <?xml version="1.0" encoding="utf-8"?> <MyData xmlns="MyNameSpace">GHI</MyData> |
太棒了。
但是,当消息中没有元素时,服务会发送带有自动关闭和空信封的消息:
1 2 | <?xml version="1.0" encoding="utf-8"?> <MyEnvelope xmlns="MyNameSpace"/> |
我收到错误消息
Source:"XML disassembler" Receive Port:"InLocation" URI:
"c:\\MyLocation*.xml" Reason: Unexpected event ("eos") in state
"processing_header".
如果我手动创建不自动关闭的消息:
1 2 | <?xml version="1.0" encoding="utf-8"?> <MyEnvelope xmlns="MyNameSpace"></MyEnvelope> |
我没有错误。我的处理不受这些错误的影响,但它一定会对性能产生一些影响,并且会在 Group Hub 暂停实例视图中乱扔垃圾。
BizTalk 似乎将自闭合节点解释为空白而不是 null。这似乎与我尝试调用没有参数的服务有关,我需要发送一个自关闭节点但 BizTalk 什么都不发送。
处理没有内容的信封一定是一个常见问题。如何配置我的应用程序以使用自闭合信封节点接收和忽略这些消息?
他们似乎经常改变处理空白的行为。请参阅 BizTalk 中默认空白行为的更改。我不确定您的问题是否相关,但值得一看。它没有提到 BizTalk 2013,但设置在主机中。如果您执行此配置设置,则需要专门为其设置主机,这样它就不会影响其他现有应用程序(如果有)。
安装以下更新之一会导致 BizTalk 更改默认行为以在映射期间保留 XML 中的空白:
在某些环境中,转换删除空格可能是首选。为了恢复这种行为,可以采取以下步骤:
在 BizTalk 2010 中,这是在主机级别设置的:
在 BizTalk 2009 和 2006 R2 中,此值在每台计算机级别设置:
a€¢ HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\BizTalk Server\\\\3.0\\\\Administration
对于基于 x64 的计算机,请单击以下注册表子项:
a€¢ HKEY_LOCAL_MACHINE\\\\Software\\\\Microsoft\\\\BizTalk Server\\\\3.0\\\\Administration
a€¢ HKEY_LOCAL_MACHINE\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\BizTalk Server\\\\3.0\\\\Administration
我知道这是一个老问题,但我也遇到过同样的事情(特别是在返回空结果集的 SQL XML 轮询/过程中)。通常我通过确保如果 SQL 返回一个空的结果集(优化 Data Available 语句)就不会调用它来绕过它,但有时它并不完全可能或万无一失。最后,我在解码阶段编写了一个自定义管道组件。它旨在执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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; } |
我没有看到或验证过这种行为,但我相信你;)。
除非您每小时获得 10K 文件或类似情况,否则不要担心异常对性能的影响。
为防止出现错误,您必须取消或重新格式化管道组件中的消息。
另一个(非常)迟到的答案。它并没有真正回答 OP 的问题,但是由于我在这里谷歌搜索错误消息并最终导致我找到了这个解决方案,所以我想无论如何我都会回答,以防它帮助其他人。
如果你能像我一样控制信封的结构,你可以给信封添加另一个层次,如果它是自动关闭的,它不会导致错误。
所以,这会导致错误:
1 | <MyEnvelope xmlns="MyNameSpace" /> |
但这不会:
1 2 3 | <MyEnvelope xmlns="MyNameSpace"> <Body /> </MyEnvelope> |
将模式的 Body XPath 设置为此嵌套级别,它应该可以正常处理。
1 2 3 4 5 6 7 | <MyEnvelope xmlns="MyNameSpace"> <Body> <MyData>ABC</MyData> <MyData>DEF</MyData> <MyData>GHI</MyData> </Body> </MyEnvelope> |