XML 支持 - 处理 XML 有效负载

XML 支持 - 处理 XML 有效负载

Spring 集成的 XML 支持通过以下组件扩展了 Spring 集成的核心:spring-doc.cn

您需要将此依赖项包含在您的项目中:spring-doc.cn

Maven 系列
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-xml</artifactId>
    <version>6.0.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-xml:6.0.9"

这些组件使在 Spring Integration 中处理 XML 消息变得更加简单。 消息收发组件使用以多种格式表示的 XML,包括 、 和 的实例。 但是,如果需要 DOM 表示形式(例如,为了评估 XPath 表达式),则有效负载将转换为所需的类型,然后转换回 . 需要实例的组件将创建一个命名空间感知实例(如果您未提供实例)。 当您需要更好地控制文档创建时,可以提供适当配置的 实例。java.lang.Stringorg.w3c.dom.Documentjavax.xml.transform.SourceStringStringDocumentBuilderDocumentBuilderspring-doc.cn

命名空间支持

Spring 集成 XML 模块中的所有组件都提供名称空间支持。 为了启用名称空间支持,你需要导入 Spring 集成 XML 模块的模式。 以下示例显示了一个典型的设置:spring-doc.cn

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/xml
    https://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd">
</beans>

XPath 表达式

Spring 集成 XML 模块中的许多组件都可以使用 XPath 表达式。 这些组件中的每一个要么引用已定义为顶级元素的 XPath 表达式,要么使用嵌套元素。<xpath-expression/>spring-doc.cn

所有形式的 XPath 表达式都会导致创建使用 Spring 的 an 。 创建 XPath 表达式时,将使用 Classpath 上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。XPathExpressionorg.springframework.xml.xpath.XPathExpressionFactoryspring-doc.cn

在内部, Spring 集成使用 Spring Web Services 项目 (https://www.spring.io/spring-ws) 提供的 XPath 功能。 具体来说,我们使用 Spring Web Services XML 模块 (spring-xml-x.x.x.jar)。 要更深入地了解,请参阅 https://docs.spring.io/spring-ws/docs/current/reference/#xpath 中的相应文档。

以下是元素的所有可用配置参数的概述: 下面的清单显示了该元素的可用属性:xpath-expressionxpath-expressionspring-doc.cn

<int-xml:xpath-expression expression="" (1)
          id=""                         (2)
          namespace-map=""              (3)
          ns-prefix=""                  (4)
          ns-uri="">                    (5)
    <map></map>                         (6)
</int-xml:xpath-expression>
1 定义 XPath 表达式。 必填。
2 基础 Bean 定义的标识符。 它是 的实例。 自选。org.springframework.xml.xpath.XPathExpression
3 对包含命名空间的映射的引用。 映射的键定义命名空间前缀,映射的值设置命名空间 URI。 同时指定此属性和元素或 and 属性是无效的。 自选。mapns-prefixns-uri
4 允许您将命名空间前缀直接设置为 XPath 表达式元素上的属性。 如果设置了 ,则还必须设置该属性。 自选。ns-prefixns-uri
5 允许您直接将命名空间 URI 设置为 XPath 表达式元素上的属性。 如果设置了 ,则还必须设置该属性。 自选。ns-urins-prefix
6 定义包含命名空间的映射。 只允许一个子元素。 映射的键定义命名空间前缀,映射的值设置命名空间 URI。 同时指定此元素和属性或设置 and 属性都是无效的。 自选。mapmapns-prefixns-uri
为 XPath 表达式提供命名空间(可选)

对于 XPath 表达式元素,您可以提供名称空间信息作为配置参数。 您可以使用以下选项之一来定义命名空间:spring-doc.cn

所有三个选项都是互斥的。 只能设置一个选项。spring-doc.cn

下面的示例显示了使用 XPath 表达式的几种不同方法,包括前面提到的用于设置 XML 命名空间的选项:spring-doc.cn

<int-xml:xpath-filter id="filterReferencingXPathExpression"
                      xpath-expression-ref="refToXpathExpression"/>

<int-xml:xpath-expression id="refToXpathExpression" expression="/name"/>

<int-xml:xpath-filter id="filterWithoutNamespace">
    <int-xml:xpath-expression expression="/name"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithOneNamespace">
    <int-xml:xpath-expression expression="/ns1:name"
                              ns-prefix="ns1" ns-uri="www.example.org"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithTwoNamespaces">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type">
        <map>
            <entry key="ns1" value="www.example.org/one"/>
            <entry key="ns2" value="www.example.org/two"/>
        </map>
    </int-xml:xpath-expression>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithNamespaceMapReference">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type"
                              namespace-map="defaultNamespaces"/>
</int-xml:xpath-filter>

<util:map id="defaultNamespaces">
    <util:entry key="ns1" value="www.example.org/one"/>
    <util:entry key="ns2" value="www.example.org/two"/>
</util:map>
将 XPath 表达式与默认命名空间一起使用

使用默认命名空间时,您可能会遇到行为与预期不同的情况。 假设我们有以下 XML 文档(表示两本书的订单):spring-doc.cn

<?xml version="1.0" encoding="UTF-8"?>
<order>
    <orderItem>
        <isbn>0321200683</isbn>
        <quantity>2</quantity>
    </orderItem>
    <orderItem>
        <isbn>1590596439</isbn>
        <quantity>1</quantity>
    </orderItem>
</order>

本文档不声明命名空间。 因此,应用以下 XPath 表达式将按预期工作:spring-doc.cn

<int-xml:xpath-expression expression="/order/orderItem" />

您可能希望相同的表达式也适用于以下 XML 文件:spring-doc.cn

<?xml version="1.0" encoding="UTF-8"?>
<order xmlns="http://www.example.org/orders">
	<orderItem>
		<isbn>0321200683</isbn>
		<quantity>2</quantity>
	</orderItem>
	<orderItem>
		<isbn>1590596439</isbn>
		<quantity>1</quantity>
	</orderItem>
</order>

前面的示例看起来与前面的示例完全相同,但声明了一个默认命名空间。spring-doc.cn

但是,在这种情况下,前面的 XPath 表达式 () 会失败。/order/orderItemspring-doc.cn

要解决此问题,必须通过设置 and 属性或设置属性来提供命名空间前缀和命名空间 URI。 命名空间 URI 必须与 XML 文档中声明的命名空间匹配。 在前面的示例中,即 。ns-prefixns-urinamespace-maphttp://www.example.org/ordersspring-doc.cn

但是,您可以任意选择命名空间前缀。 事实上,提供空字符串实际上是有效的。 (但是,不允许使用 null。 如果命名空间前缀由空字符串组成,则 Xpath 表达式必须使用冒号 (“:”) 来指示默认命名空间。 如果省略冒号,则 XPath 表达式不匹配。 以下 XPath 表达式与前面示例中的 XML 文档匹配:spring-doc.cn

<int-xml:xpath-expression expression="/:order/:orderItem"
    ns-prefix="" ns-uri="https://www.example.org/prodcuts"/>

您还可以提供任何其他任意选择的命名空间前缀。 以下 XPath 表达式(使用命名空间前缀)也匹配:myorderspring-doc.cn

<int-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
    ns-prefix="myorder" ns-uri="https://www.example.org/prodcuts"/>

命名空间 URI 是真正重要的信息,而不是前缀。 Jaxen 很好地总结了这一点:spring-doc.cn

在 XPath 1.0 中,所有无前缀的名称都是非限定的。 不要求 XPath 表达式中使用的前缀与所查询的文档中使用的前缀相同。 只需要匹配命名空间 URI,不需要匹配前缀。

转换 XML 有效负载

本节介绍如何转换 XML 负载spring-doc.cn

将 Transformer 配置为 Bean

本节将解释以下转换器的工作原理以及如何将它们配置为 bean:spring-doc.cn

所有 XML 转换器都扩展了 AbstractTransformerAbstractPayloadTransformer,因此实现了 Transformer。 在 Spring 集成中将 XML 转换器配置为 bean 时,通常会将它与MessageTransformingHandler一起配置。 这允许将转换器用作终端节点。 最后,我们讨论命名空间支持,它允许将转换器配置为 XML 中的元素。Transformerspring-doc.cn

解组转换器

UnmarshallingTransformer 允许使用 Spring OXM 的实现对 XML 进行解组。 Spring 的 Object/XML Mapping 支持提供了多种实现,这些实现通过使用 JAXBCastorJiBX 等支持编组和解组。 解组器需要 的实例。 如果消息有效负载不是 的实例,则仍会尝试进行转换。 目前支持 、 、 和 payloads。 要创建到 的自定义转换,您可以注入 SourceFactory 的实现。SourceUnmarshallerSourceSourceStringFilebyte[]org.w3c.dom.DocumentSourcespring-doc.cn

如果未显式设置,则默认情况下,该属性将设置为DomSourceFactorySourceFactoryUnmarshallingTransformer

从版本 5.0 开始,还支持 作为传入的有效负载。 当我们通过 SOAP 收到带有 MTOM 附件的原始文件时,这可能很有用。 有关更多信息,请参阅 MTOM 支持UnmarshallingTransformerorg.springframework.ws.mime.MimeMessageWebServiceMessagespring-doc.cn

以下示例显示如何定义解组转换器:spring-doc.cn

<bean id="unmarshallingTransformer" class="o.s.i.xml.transformer.UnmarshallingTransformer">
    <constructor-arg>
        <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            <property name="contextPath" value="org.example" />
        </bean>
    </constructor-arg>
</bean>
MarshallingTransformer

MarshallingTransformer 允许使用 Spring OXM 将对象图转换为 XML。 默认情况下,会返回一个 . 但是,您可以通过配置替代项来控制结果的类型,例如 . 在许多情况下,将有效负载转换为替代 XML 格式会更方便。 为此,请配置 . Spring 集成提供了两种实现,一种是转换为 ,另一种是转换为 。 下面的示例配置一个转换为文档的编组转换器:MarshallerMarshallingTransformerDomResultResultFactoryStringResultFactoryResultTransformerStringDocumentspring-doc.cn

<bean id="marshallingTransformer" class="o.s.i.xml.transformer.MarshallingTransformer">
    <constructor-arg>
        <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            <property name="contextPath" value="org.example"/>
        </bean>
    </constructor-arg>
    <constructor-arg>
        <bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
    </constructor-arg>
</bean>

默认情况下,会将 payload 对象传递给 . 但是,如果其 boolean 属性设置为 ,则整个实例将传递给 。 这对于接口的某些自定义实现可能很有用,但通常,当您委托给各种实现中的任何一个时,有效负载是用于封送的适当源对象。MarshallingTransformerMarshallerextractPayloadfalseMessageMarshallerMarshallerMarshallerspring-doc.cn

XsltPayloadTransformer

XsltPayloadTransformer 使用可扩展样式表语言转换 (XSLT) 转换 XML 负载。 转换器的构造函数需要传入 ResourceTemplates 的实例。 传入实例允许对用于创建模板实例的 进行更好的配置。TemplatesTransformerFactoryspring-doc.cn

UnmarshallingTransformer 一样,它会对 的实例执行实际的 XSLT 转换。 因此,如果消息有效负荷不是 的实例,则仍会尝试进行转换。 和 payloads 直接支持。XsltPayloadTransformerSourceSourceStringDocumentspring-doc.cn

要创建到 的自定义转换,您可以注入 SourceFactory 的实现。Sourcespring-doc.cn

如果未显式设置a,则默认情况下,该上的属性设置为DomSourceFactorySourceFactoryXsltPayloadTransformer

默认情况下,会创建一条带有 Result 负载的消息,类似于 . 您可以通过提供 ResultFactoryResultTransformer 来自定义它。XsltPayloadTransformerXmlPayloadMarshallingTransformerspring-doc.cn

以下示例配置一个用作 XSLT 有效负载转换器的 Bean:spring-doc.cn

<bean id="xsltPayloadTransformer" class="o.s.i.xml.transformer.XsltPayloadTransformer">
  <constructor-arg value="classpath:org/example/xsl/transform.xsl"/>
  <constructor-arg>
    <bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
  </constructor-arg>
</bean>

从 Spring Integration 3.0 开始,你可以使用构造函数参数来指定转换器工厂类名。 您可以在使用 namespace 时使用 attribute 来执行此操作。transformer-factory-classspring-doc.cn

使用实现ResultTransformer

和 都允许您指定 ResultTransformer。 因此,如果封送处理或 XSLT 转换返回 Result,则还可以选择使用 a 将其转换为另一种格式。 Spring 集成提供了两个具体的实现:MarshallingTransformerXsltPayloadTransformerResultTransformerResultResultTransformerspring-doc.cn

默认情况下,始终返回 Result。 通过指定 ,您可以自定义返回的负载类型。MarshallingTransformerResultTransformerspring-doc.cn

对于 . 默认情况下,如果输入有效负载是 或 Document 的实例,则会忽略该属性。XsltPayloadTransformerStringresultTransformerspring-doc.cn

但是,如果输入负载是 Source 或任何其他类型,则会应用该属性。 此外,您还可以将该属性设置为 ,这也会导致使用指定的 。resultTransformeralwaysUseResultFactorytrueresultTransformerspring-doc.cn

有关更多信息和示例,请参阅命名空间配置和结果转换器spring-doc.cn

XML 转换器的命名空间支持

Spring 集成 XML 名称空间中提供了对所有 XML 转换器的名称空间支持,前面显示了该名称空间的模板。 对 transformers 的命名空间支持根据提供的输入通道的类型创建 or 的实例。 命名空间支持旨在通过允许创建使用一个元素的端点和转换器来减少 XML 配置的数量。EventDrivenConsumerPollingConsumerspring-doc.cn

使用UnmarshallingTransformer

命名空间支持 如下所示。 由于命名空间创建的是端点实例而不是转换器,因此您可以在元素中嵌套 Poller 来控制 input 通道的轮询。 以下示例显示了如何执行此操作:UnmarshallingTransformerspring-doc.cn

<int-xml:unmarshalling-transformer id="defaultUnmarshaller"
    input-channel="input" output-channel="output"
    unmarshaller="unmarshaller"/>

<int-xml:unmarshalling-transformer id="unmarshallerWithPoller"
    input-channel="input" output-channel="output"
    unmarshaller="unmarshaller">
    <int:poller fixed-rate="2000"/>
<int-xml:unmarshalling-transformer/>
使用MarshallingTransformer

编组转换器的命名空间支持需要 、 、 和对 的引用 。 您可以使用 optional 属性来控制创建的结果类型。 有效值为 or(默认值)。 以下示例配置编组转换器:input-channeloutput-channelmarshallerresult-typeStringResultDomResultspring-doc.cn

<int-xml:marshalling-transformer
     input-channel="marshallingTransformerStringResultFactory"
     output-channel="output"
     marshaller="marshaller"
     result-type="StringResult" />

<int-xml:marshalling-transformer
    input-channel="marshallingTransformerWithResultTransformer"
    output-channel="output"
    marshaller="marshaller"
    result-transformer="resultTransformer" />

<bean id="resultTransformer" class="o.s.i.xml.transformer.ResultToStringTransformer"/>

如果提供的结果类型不够用,则可以提供对自定义实现的引用,作为使用该属性设置属性的替代方法。 和 属性是互斥的。ResultFactoryresult-typeresult-factoryresult-typeresult-factoryspring-doc.cn

在内部,和 result 类型分别由实现 StringResultFactoryDomResultFactory 表示。StringResultDomResultResultFactory
使用XsltPayloadTransformer

的命名空间支持允许您传入 (以创建 Templates 实例) 或传入预先创建的实例作为引用。 与封送转换器一样,您可以通过指定 the 或 属性来控制结果输出的类型。 当您需要在发送之前转换结果时,您可以使用属性来引用 .XsltPayloadTransformerResourceTemplatesresult-factoryresult-typeresult-transformerResultTransformerspring-doc.cn

如果指定 或 属性,则基础 XsltPayloadTransformer 上的属性将由 XsltPayloadTransformerParser 设置为。result-factoryresult-typealwaysUseResultFactorytrue

以下示例配置两个 XSLT 转换器:spring-doc.cn

<int-xml:xslt-transformer id="xsltTransformerWithResource"
    input-channel="withResourceIn" output-channel="output"
    xsl-resource="org/springframework/integration/xml/config/test.xsl"/>

<int-xml:xslt-transformer id="xsltTransformerWithTemplatesAndResultTransformer"
    input-channel="withTemplatesAndResultTransformerIn" output-channel="output"
    xsl-templates="templates"
    result-transformer="resultTransformer"/>

您可能需要有权访问数据(如标题),以便协助进行转换。 例如,您可能需要访问某些标头并将它们作为参数传递给转换器(例如,)。 Spring 集成提供了两种便捷的方法来实现这一目标,如下例所示:MessageMessageMessagetransformer.setParameter(..)spring-doc.cn

<int-xml:xslt-transformer id="paramHeadersCombo"
    input-channel="paramHeadersComboChannel" output-channel="output"
    xsl-resource="classpath:transformer.xslt"
    xslt-param-headers="testP*, *foo, bar, baz">

    <int-xml:xslt-param name="helloParameter" value="hello"/>
    <int-xml:xslt-param name="firstName" expression="headers.fname"/>
</int-xml:xslt-transformer>

如果消息标头名称与参数名称一一匹配,则可以使用该属性。 在该文档中,您可以使用通配符进行简单的模式匹配。 它支持以下简单模式样式:、、*xxx 和 .xslt-param-headersxxx*xxxxxx*yyyspring-doc.cn

您还可以使用 element. 在该元素上,您可以设置 attribute 或 attribute。 该属性应该是任何有效的 SPEL 表达式,并且是表达式评估上下文的根对象。 该属性(与 Spring bean 中的 any 一样)允许您指定简单的标量值。 您还可以使用属性占位符(如 )。 因此,使用 和 属性,您可以将 XSLT 参数映射到 的任何可访问部分以及任何文本值。<xslt-param/>expressionvalueexpressionMessagevaluevalue${some.value}expressionvalueMessagespring-doc.cn

从 Spring Integration 3.0 开始,你现在可以通过设置属性来指定 transformer 工厂类名。transformer-factory-classspring-doc.cn

命名空间配置和结果转换器

我们在 使用 ResultTransformer 实现 中介绍了如何使用结果转换器。 本节中的示例使用 XML 命名空间配置来说明几个特殊用例。 首先,我们定义 ,如下例所示:ResultTransformerspring-doc.cn

<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>

这将接受 a 或 a 作为输入,并将输入转换为 .ResultTransformerStringResultDOMResultDocumentspring-doc.cn

现在我们可以声明 transformer,如下所示:spring-doc.cn

<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
    xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>

如果传入消息的 payload 类型为 ,则第一步是使用 来确定的。 由于我们没有指定 a ,因此使用默认值,这意味着转换产生 .SourceResultResultFactoryResultFactoryDomResultFactoryDomResultspring-doc.cn

但是,由于我们指定了 ,因此会使用它,并且生成的有效负载是 类型。ResultTransformerMessageDocumentspring-doc.cn

指定的 is ignored with or payloads. 如果传入消息的有效负载是 type ,则 XSLT 转换后的有效负载为 . 同样,如果传入消息的有效负载是 type ,则 XSLT 转换后的有效负载为 'Document'。ResultTransformerStringDocumentStringStringDocument

如果消息有效负载不是 a 、 a 或 a 作为回退选项,我们尝试使用默认的 SourceFactory 创建“Source”。 由于我们没有使用该属性显式指定,因此使用默认的 DomSourceFactory。 如果成功,则执行 XSLT 转换,就像有效负载的类型为 ,如前面段落所述。SourceStringDocumentSourceFactorysource-factorySourcespring-doc.cn

支持从 、 a 或 有效负荷 创建 。DomSourceFactoryDOMSourceDocumentFileString

下一个 transformer 声明添加一个用作其值的属性。 在内部由 . 因此,您还可以使用 attribute 添加对 , 的引用,该属性本来是相同的。 以下示例显示了 transformer 声明:result-typeStringResultresult-typeStringResultFactoryStringResultFactoryresult-factoryspring-doc.cn

<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
		xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
		result-type="StringResult"/>

因为我们使用 a ,所以类的属性被隐式设置为 。 因此,使用引用的 .ResultFactoryalwaysUseResultFactoryXsltPayloadTransformertrueResultToDocumentTransformerspring-doc.cn

因此,如果转换 类型的有效负载 ,则生成的有效负载为 Document 类型。Stringspring-doc.cn

XsltPayloadTransformer<xsl:output method="text"/>

<xsl:output method="text"/>指示 XSLT 模板仅从输入源生成文本内容。 在这种特殊情况下,我们没有理由使用 . 因此, XsltPayloadTransformer 默认为如果调用的基础的 output 属性返回 。 此强制执行独立于入站有效负载类型。 只有您设置组件的 if 属性或属性时,此行为才可用。DomResultStringResultmethodjavax.xml.transform.Transformertextresult-typeresult-factory<int-xml:xslt-transformer>spring-doc.cn

使用 XPath 转换 XML 消息

在消息转换方面,XPath 是转换具有 XML 有效负载的消息的好方法。 您可以通过使用 element 定义 XPath 转换器来实现此目的。<xpath-transformer/>spring-doc.cn

简单的 XPath 转换

请考虑以下转换器配置:spring-doc.cn

<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
      xpath-expression="/person/@name" />

另请考虑以下几点:Messagespring-doc.cn

Message<?> message =
  MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();

将此消息发送到 'inputChannel' 后,之前配置的 XPath 转换器将此 XML 消息转换为有效负载为 'John Doe' 的简单消息,所有这些都基于属性中指定的简单 XPath 表达式。Messagexpath-expressionspring-doc.cn

XPath 还允许您将提取的元素简单转换为所需的类型。 有效的返回类型在接口指定的转换规则中定义并遵循这些规则。javax.xml.xpath.XPathConstantsjavax.xml.xpath.XPathspring-doc.cn

以下常量由类定义: 、 、 、 、 和 。XPathConstantsBOOLEANDOM_OBJECT_MODELNODENODESETNUMBERSTRINGspring-doc.cn

您可以使用 element 的属性来配置所需的类型,如下例所示(两次):evaluation-type<xpath-transformer/>spring-doc.cn

<int-xml:xpath-transformer input-channel="numberInput" xpath-expression="/person/@age"
                           evaluation-type="NUMBER_RESULT" output-channel="output"/>

<int-xml:xpath-transformer input-channel="booleanInput"
                           xpath-expression="/person/@married = 'true'"
                           evaluation-type="BOOLEAN_RESULT" output-channel="output"/>

节点映射器

如果需要为 XPath 表达式提取的节点提供自定义映射,则可以提供对 (实现用于基于每个节点映射对象的接口)的实现的引用。 要提供对 的引用 ,可以使用 该属性,如下例所示:org.springframework.xml.xpath.NodeMapperXPathOperationsNodeNodeMappernode-mapperspring-doc.cn

<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
                           node-mapper="testNodeMapper" output-channel="output"/>

以下示例显示了与上述示例配合使用的实现:NodeMapperspring-doc.cn

class TestNodeMapper implements NodeMapper {
  public Object mapNode(Node node, int nodeNum) throws DOMException {
    return node.getTextContent() + "-mapped";
  }
}

XML 负载转换器

您还可以使用 的实现来提供更精细的转换。 以下示例演示如何定义一个:org.springframework.integration.xml.XmlPayloadConverterspring-doc.cn

<int-xml:xpath-transformer input-channel="customConverterInput"
                           output-channel="output" xpath-expression="/test/@type"
                           converter="testXmlPayloadConverter" />

以下示例显示了与上述示例配合使用的实现:XmlPayloadConverterspring-doc.cn

class TestXmlPayloadConverter implements XmlPayloadConverter {
  public Source convertToSource(Object object) {
    throw new UnsupportedOperationException();
  }
  //
  public Node convertToNode(Object object) {
    try {
      return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
          new InputSource(new StringReader("<test type='custom'/>")));
    }
    catch (Exception e) {
      throw new IllegalStateException(e);
    }
  }
  //
  public Document convertToDocument(Object object) {
    throw new UnsupportedOperationException();
  }
}

如果您未提供此引用,则使用 the。 在大多数情况下,它应该就足够了,因为它可以从 、 和 payload 转换。 如果您需要扩展该默认实现的功能之外,则 upstream 可能比在此处提供对此策略的自定义实现的引用更好。DefaultXmlPayloadConverterNodeDocumentSourceFileStringInputStreambyte[]Transformerspring-doc.cn

拆分 XML 消息

XPathMessageSplitter支持具有 OR 负载的消息。 拆分器使用提供的 XPath 表达式将负载拆分为多个节点。 默认情况下,这会导致每个实例都成为新消息的有效负载。 当每条消息都应该为 时,您可以设置标志。 在传入有效负载的情况下,有效负载将被转换,然后被拆分,然后再转换回多个消息。 XPath 拆分器实现,因此应与适当的端点一起配置(有关更简单的配置替代方案,请参阅以下示例后面的命名空间支持示例)。 以下示例配置一个 bean,该 bean 使用 :StringDocumentNodeDocumentcreateDocumentsStringStringMessageHandlerXPathMessageSplitterspring-doc.cn

<bean id="splittingEndpoint"
      class="org.springframework.integration.endpoint.EventDrivenConsumer">
    <constructor-arg ref="orderChannel" />
    <constructor-arg>
        <bean class="org.springframework.integration.xml.splitter.XPathMessageSplitter">
            <constructor-arg value="/order/items" />
            <property name="documentBuilder" ref="customisedDocumentBuilder" />
            <property name="outputChannel" ref="orderItemsChannel" />
        </bean>
    </constructor-arg>
</bean>

XPath splitter 命名空间支持允许您创建具有 input 通道和 output 通道的消息端点,如下例所示:spring-doc.cn

<!-- Split the order into items and create a new message for each item node -->
<int-xml:xpath-splitter id="orderItemSplitter"
                       input-channel="orderChannel"
                       output-channel="orderItemsChannel">
    <int-xml:xpath-expression expression="/order/items"/>
</int-xml:xpath-splitter>

<!-- Split the order into items, create a new document for each item-->
<int-xml:xpath-splitter id="orderItemDocumentSplitter"
                       input-channel="orderChannel"
                       output-channel="orderItemsChannel"
                       create-documents="true">
    <int-xml:xpath-expression expression="/order/items"/>
    <int:poller fixed-rate="2000"/>
</int-xml:xpath-splitter>

从版本 4.2 开始,当请求不是 type 时,会公开实例的(例如 )属性。 以下示例定义一个属性并将其与该属性一起使用:XPathMessageSplitteroutputPropertiesOutputKeys.OMIT_XML_DECLARATIONjavax.xml.transform.Transformerpayloadorg.w3c.dom.Nodeoutput-propertiesspring-doc.cn

<util:properties id="outputProperties">
	<beans:prop key="#{T (javax.xml.transform.OutputKeys).OMIT_XML_DECLARATION}">yes</beans:prop>
</util:properties>

<xpath-splitter input-channel="input"
             output-properties="outputProperties">
    <xpath-expression expression="/orders/order"/>
</xpath-splitter>

从 开始,将选项公开为标志(默认为 )。 这允许在下游流中 “流式处理” 拆分节点。 将 mode 设置为 后,每个节点在迭代时都会变换。 When ,在开始将拆分节点发送到输出通道之前,首先转换所有条目。 (您可以将差异视为“转换、发送、转换、发送”与“转换、转换、发送、发送”。 有关更多信息,请参阅 Splitterversion 4.2XPathMessageSplitteriteratorbooleantrueiteratortruefalsespring-doc.cn

使用 XPath 路由 XML 消息

与基于 SPEL 的路由器类似, Spring 集成提供了对基于 XPath 表达式的路由消息的支持,这允许你创建具有 input 通道但没有输出通道的消息端点。 相反,一个或多个 output channel 是动态确定的。 以下示例说明如何创建此类路由器:spring-doc.cn

<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/order/type"/>
</int-xml:xpath-router>
有关 Router 之间通用属性的概述,请参阅 Common Router Parameters

在内部,XPath 表达式作为 type 计算并转换为表示通道名称的 a。 通常,此类列表包含单个通道名称。 但是,根据 XPath 表达式的结果,如果 XPath 表达式返回多个值,则 XPath 路由器也可以具有收件人列表路由器的特征。 在这种情况下,将包含多个频道名称。 因此,消息将发送到列表中的所有通道。NODESETList<String>List<String>spring-doc.cn

因此,假设传递给以下 router 配置的 XML 文件包含许多表示通道名称的子元素,则消息将发送到所有这些通道:responderspring-doc.cn

<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/request/responders"/>
</int-xml:xpath-router>

如果返回的值不直接表示通道名称,则可以指定其他映射参数以将这些返回的值映射到实际的通道名称。 例如,如果表达式产生两个值 ( 和 ),但您不想将响应方名称与通道名称耦合,则可以提供其他映射配置,例如:/request/respondersresponderAresponderBspring-doc.cn

<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/request/responders"/>
    <int-xml:mapping value="responderA" channel="channelA"/>
    <int-xml:mapping value="responderB" channel="channelB"/>
</int-xml:xpath-router>

如前所述,XPath 表达式的默认计算类型是 ,它被转换为通道名称的 a,它处理单通道场景以及多通道场景。NODESETList<String>spring-doc.cn

尽管如此,某些 XPath 表达式可能从一开始就计算为 type。 例如,请考虑以下 XPath 表达式:Stringspring-doc.cn

name(./node())

此表达式返回根节点的名称。 如果使用的是默认评估类型,则会导致异常。NODESETspring-doc.cn

对于这些方案,您可以使用 attribute ,它允许您管理评估类型。 这是默认的。 但是,如果将其设置为 ,则使用评估类型。evaluate-as-stringFALSETRUEStringspring-doc.cn

XPath 1.0 指定了 4 种数据类型:spring-doc.cn

当 XPath Router 使用 optional 属性计算表达式时,返回值由 XPath 规范中定义的函数确定。 这意味着,如果表达式选择多个节点,它将返回第一个节点的字符串值。evaluate-as-stringstring()spring-doc.cn

有关详细信息,请参阅:spring-doc.cn

例如,如果我们想根据根节点的名称进行路由,我们可以使用以下配置:spring-doc.cn

<int-xml:xpath-router id="xpathRouterAsString"
        input-channel="xpathStringChannel"
        evaluate-as-string="true">
    <int-xml:xpath-expression expression="name(./node())"/>
</int-xml:xpath-router>

XML 负载转换器

对于 XPath 路由器,您还可以指定在 XPath 评估之前转换负载时要使用的 Converter。 因此,XPath Router 支持策略的自定义实现,并且在 XML 中配置元素时,可以通过属性提供对此类实现的引用。XmlPayloadConverterxpath-routerconverterspring-doc.cn

如果未明确提供此引用,则使用 the。 在大多数情况下,它应该足够了,因为它可以从 Node、Document、Source、File 和 String 类型的有效负载进行转换。 如果你需要扩展该默认实现的能力,那么在大多数情况下,上游 Transformer 通常是更好的选择,而不是在此处提供对此策略的自定义实现的引用。DefaultXmlPayloadConverterspring-doc.cn

XPath 标头扩充器

XPath 报头扩充器定义一个报头扩充器消息转换器,该转换器根据消息有效负荷计算 XPath 表达式,并将计算结果插入到消息报头中。spring-doc.cn

以下清单显示了所有可用的配置参数:spring-doc.cn

<int-xml:xpath-header-enricher default-overwrite="true"    (1)
                               id=""                       (2)
                               input-channel=""            (3)
                               output-channel=""           (4)
                               should-skip-nulls="true">   (5)
    <int:poller></int:poller>                              (6)
    <int-xml:header name=""                                (7)
                    evaluation-type="STRING_RESULT"        (8)
                    header-type="int"                      (9)
                    overwrite="true"                       (10)
                    xpath-expression=""                    (11)
                    xpath-expression-ref=""/>              (12)
</int-xml:xpath-header-enricher>
1 指定是否覆盖现有标头值的默认布尔值。 它仅对不提供自己的 'overwrite' 属性的子元素生效。 如果未设置 'default- overwrite' 属性,则指定的标头值不会覆盖任何具有相同标头名称的现有标头值。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此终端节点的接收消息通道。 自选。
4 将扩充消息发送到的通道。 自选。
5 指定是否应跳过 null 值,例如可能从表达式计算返回的 null 值。 默认值为 . 如果 null 值应触发删除相应的标头,请将此项设置为 。 自选。truefalse
6 与 Header Enricher 一起使用的 Poller 。 自选。
7 要扩充的标头的名称。 命令的。
8 XPath 评估所需的结果类型。 如果未设置属性,则这是标头值的类型。 允许使用以下值: 、 和 。 如果未设置,则它在内部默认为 。 自选。header-typeBOOLEAN_RESULTSTRING_RESULTNUMBER_RESULTNODE_RESULTNODE_LIST_RESULTXPathEvaluationType.STRING_RESULT
9 标头值类型的完全限定类名。 XPath 评估的结果由 转换为此类型。 例如,这允许将 a (双精度) 转换为 . 该类型可以声明为基元(如 ),但结果始终是等效的包装类(如 )。 有效负载类型转换中讨论的相同集成用于转换,因此通过向服务添加自定义转换器来支持转换为自定义类型。 自选。ConversionServiceNUMBER_RESULTIntegerintIntegerConversionService
10 布尔值,用于指示此报头值是否应覆盖同名的现有报头值(如果 input 中已存在)。Message
11 XPath 表达式为 . 您必须设置此属性或两者,但不能同时设置两者。Stringxpath-expression-ref
12 XPath 表达式引用。 您必须设置此属性或两者,但不能同时设置两者。xpath-expression

使用 XPath 过滤器

此组件定义基于 XPath 的消息过滤器。 在内部,这些组件使用包装 .MessageFilterAbstractXPathMessageSelectorspring-doc.cn

有关更多详细信息,请参阅筛选器

要使用 XPath 过滤器,您至少必须通过声明元素或在属性中引用 XPath 表达式来提供 XPath 表达式。xpath-expressionxpath-expression-refspring-doc.cn

如果提供的 XPath 表达式的计算结果为值,则不需要其他配置参数。 但是,如果 XPath 表达式的计算结果为 ,则应设置与计算结果匹配的属性。booleanStringmatch-valuespring-doc.cn

match-type有三个选项:spring-doc.cn

  • exact:对应于 on 。 底层实现使用equalsjava.lang.StringStringValueTestXPathMessageSelectorspring-doc.cn

  • case-insensitive:对应于 on 。 底层实现使用equals-ignore-casejava.lang.StringStringValueTestXPathMessageSelectorspring-doc.cn

  • regex:匹配操作 1 。 底层实现使用java.lang.StringRegexTestXPathMessageSelectorspring-doc.cn

当提供 'regex' 的 'match-type' 值时,与该属性一起提供的值必须是有效的正则表达式。match-valuespring-doc.cn

以下示例显示了该元素的所有可用属性:xpath-filterspring-doc.cn

<int-xml:xpath-filter discard-channel=""                      (1)
                      id=""                                   (2)
                      input-channel=""                        (3)
                      match-type="exact"                      (4)
                      match-value=""                          (5)
                      output-channel=""                       (6)
                      throw-exception-on-rejection="false"    (7)
                      xpath-expression-ref="">                (8)
    <int-xml:xpath-expression ... />                          (9)
    <int:poller ... />                                        (10)
</int-xml:xpath-filter>
1 消息通道,您希望发送被拒绝的消息。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此终端节点的接收消息通道。 自选。
4 要在 XPath 评估结果和 . 默认值为 . 自选。match-valueexact
5 要与 XPath 评估结果匹配的字符串值。 如果未设置此属性,则 XPath 计算必须生成布尔结果。 自选。
6 将匹配的邮件调度到的通道。 自选。
7 默认情况下,此属性设置为 ,并且被拒绝的消息(与过滤条件不匹配的消息)将被静默丢弃。 但是,如果设置为 ,则消息拒绝会导致错误情况,并将异常向上游传播到调用方。 自选。falsetrue
8 对要评估的 XPath 表达式实例的引用。
9 此子元素设置要计算的 XPath 表达式。 如果不包含此元素,则必须设置 该属性。 此外,您只能包含一个元素。xpath-expression-refxpath-expression
10 用于 XPath 过滤器的 Poller。 自选。

#xpath SPEL 函数

Spring 集成,从版本 3.0 开始,提供了内置的 SPEL 函数,该函数调用静态方法。 此方法委托给 . 下面的清单显示了一些使用示例:#xpathXPathUtils.evaluate(…​)org.springframework.xml.xpath.XPathExpressionspring-doc.cn

<transformer expression="#xpath(payload, '/name')"/>

<filter expression="#xpath(payload, headers.xpath, 'boolean')"/>

<splitter expression="#xpath(payload, '//book', 'document_list')"/>

<router expression="#xpath(payload, '/person/@age', 'number')">
    <mapping channel="output1" value="16"/>
    <mapping channel="output2" value="45"/>
</router>

还支持第三个可选参数,用于转换 XPath 评估的结果。 它可以是 String 常量 (、 、 、 和 )之一,也可以是一个实例。 默认情况下,SPEL 函数返回 XPath 评估的表示形式。#xpath()stringbooleannumbernodenode_listdocument_listorg.springframework.xml.xpath.NodeMapper#xpathStringspring-doc.cn

要启用 SPEL 函数,可以将 添加到 Classpath 中。 你不需要从 Spring 集成 XML 名称空间声明任何组件。#xpathspring-integration-xml.jar

有关详细信息,请参阅“Spring 表达式语言 (SpEL)”。spring-doc.cn

XML 验证过滤器

XML 验证筛选器允许您根据提供的架构实例验证传入消息。 支持以下 Schema 类型:spring-doc.cn

未通过验证的消息可以静默丢弃,也可以转发到可定义的 . 此外,您还可以配置此过滤器以在验证失败时引发 if。discard-channelExceptionspring-doc.cn

以下清单显示了所有可用的配置参数:spring-doc.cn

<int-xml:validating-filter discard-channel=""                    (1)
                           id=""                                 (2)
                           input-channel=""                      (3)
                           output-channel=""                     (4)
                           schema-location=""                    (5)
                           schema-type="xml-schema"              (6)
                           throw-exception-on-rejection="false"  (7)
                           xml-converter=""                      (8)
                           xml-validator="">                     (9)
    <int:poller .../>                                            (10)
</int-xml:validating-filter>
1 消息通道,您希望发送被拒绝的消息。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此终端节点的接收消息通道。 自选。
4 消息通道,您希望发送接受的消息。 自选。
5 设置要验证消息有效负载的架构的位置。 内部使用接口。 您可以设置此属性或属性,但不能同时设置两者。 自选。org.springframework.core.io.Resourcexml-validator
6 设置 Schema 类型。 可以是 或 。 自选。 如果未设置,则默认为 ,内部转换为 。xml-schemarelax-ngxml-schemaorg.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML
7 如果 ,如果提供的 Message 的有效负载验证失败,则抛出 a。 如果未设置,则默认为。 自选。trueMessageRejectedExceptionfalse
8 对自定义策略的引用。 自选。org.springframework.integration.xml.XmlPayloadConverter
9 对自定义策略的引用。 您可以设置此属性或属性,但不能同时设置两者。 自选。sorg.springframework.xml.validation.XmlValidatorschema-location
10 用于 XPath 过滤器的 Poller。 自选。