SI <int-xml:xpath-filter /> 行为

SI <int-xml:xpath-filter /> behavior

我有一个场景,我正在根据 xpath 值过滤 xml 负载。

<int:channel id="documentReceiptFilterChannel" />
<int:chain input-channel="documentReceiptFilterChannel" output-channel="nullChannel">
    <!-- Filter to discard message if <statusCode> value is 'EMLOK' -->
    <int-xml:xpath-filter match-type="regex" match-value="^(?!\bEMLOK\b).*$" discard-channel="nullChannel">
        <int-xml:xpath-expression expression="//*[local-name()='statusCode']" />
    </int-xml:xpath-filter>
    <int:service-activator expression="@opsLogger.logError('TransactionId=' + headers.correlationId, ' Msg=' + @opsExceptionUtils.createOPSExceptionInstance(#root))" />
</int:chain>

有效载荷如下:

<?xml version="1.0" encoding="UTF-8"?>
<GetDocumentReceiptReply xmlns="http://example.org"
                                xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <mergeReceiptDeliveryStatus>
      <statusCode>EMLOK</statusCode>
   </mergeReceiptDeliveryStatus>
</GetDocumentReceiptReply>

我的要求是,当 <statusCode>EMLOK</statusCode> 元素可用时,丢弃消息,因此 nullChannel 被提及为 discard-channel。 但是还有其他任何值,继续链中的下一步并进行错误记录 - <int:service-activator expression="@opsLogger.logError().

只要负载中存在 <statusCode> 元素,上述设置就可以正常工作。但不适用于以下情况:

  1. <statusCode></statusCode>
  2. <statusCode/>
  3. <statusCode> 缺失
  4. 或任何其他 xml 有效载荷

为了摆脱命名空间问题,xpath 表达式形成为 <int-xml:xpath-expression expression="//*[local-name()='statusCode']" />。 xpath 值与正则表达式匹配 match-type="regex" match-value="^(?!\bEMLOK\b).*$" (For value != 'EMLOK').

<int-xml:xpath-expression /> 评估失败时会发生什么?

我唯一的要求是,如果存在 <statusCode>EMLOK</statusCode>,则丢弃该消息,否则,在日志文件中记录错误。 (并且不抛出将传播到错误通道的异常)。

您可以编写 AbstractXPathMessageSelector 的自定义子类并委托给 BooleanTestXPathMessageSelectorRegexTestXPathMessageSelector,或者简单地使用 2 个过滤器...

<int:chain input-channel="documentReceiptFilterChannel" output-channel="errors">
    <int-xml:xpath-filter discard-channel="errors">
        <int-xml:xpath-expression expression="//*[local-name()='statusCode']" />
    </int-xml:xpath-filter>
    <int-xml:xpath-filter match-type="regex" match-value="^(?!\bEMLOK\b).*$">
        <int-xml:xpath-expression expression="//*[local-name()='statusCode']" />
    </int-xml:xpath-filter>
</int:chain>

<int:service-activator 
    expression="@opsLogger.logError('TransactionId=' + headers.correlationId, ' Msg=' + @opsExceptionUtils.createOPSExceptionInstance(#root))" />

请注意,您不需要丢弃到 nullChannel - 仅省略丢弃通道会导致丢弃。通过第二个过滤器的消息进入链的输出通道。

自定义选择器会更高效一些,因为只需要一次转换为节点。