XML 支持 - 处理 XML 有效负载

XML 支持 - 处理 XML 有效负载

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

您需要将此依赖项包含在您的项目中:spring-doc.cadn.net.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,包括java.lang.String,org.w3c.dom.Documentjavax.xml.transform.Source. 但是,在需要 DOM 表示形式的情况下(例如,为了评估 XPath 表达式),则Stringpayload 被转换为 required 类型,然后转换回String. 需要DocumentBuilder如果未提供命名空间感知实例,请创建一个命名空间感知实例。 当您需要更好地控制文档创建时,可以提供适当配置的DocumentBuilder.spring-doc.cadn.net.cn

命名空间支持

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

所有形式的 XPath 表达式都会导致创建一个XPathExpression使用 Springorg.springframework.xml.xpath.XPathExpressionFactory. 创建 XPath 表达式时,将使用 Classpath 上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。spring-doc.cadn.net.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-expression元素: 以下清单显示了xpath-expression元素:spring-doc.cadn.net.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。 同时指定此属性和map元素或ns-prefixns-uri属性。 自选。
4 允许您将命名空间前缀直接设置为 XPath 表达式元素上的属性。 如果您将ns-prefix,您还必须设置ns-uri属性。 自选。
5 允许您直接将命名空间 URI 设置为 XPath 表达式元素上的属性。 如果您将ns-uri,您还必须设置ns-prefix属性。 自选。
6 定义包含命名空间的映射。 只有一个mapchild 元素。 映射的键定义命名空间前缀,映射的值设置命名空间 URI。 同时指定此元素和map属性或设置ns-prefixns-uri属性。 自选。
为 XPath 表达式提供命名空间(可选)

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

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

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

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

您可能希望相同的表达式也适用于以下 XML 文件:spring-doc.cadn.net.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.cadn.net.cn

但是,之前的 XPath 表达式 (/order/orderItem) 失败。spring-doc.cadn.net.cn

为了解决此问题,您必须通过设置ns-prefixns-uri属性或通过设置namespace-map属性。 命名空间 URI 必须与 XML 文档中声明的命名空间匹配。 在前面的示例中,即http://www.example.org/orders.spring-doc.cadn.net.cn

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

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

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

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

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

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

转换 XML 有效负载

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

将 Transformer 配置为 Bean

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

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

解组转换器

UnmarshallingTransformer让 XMLSource通过使用 Spring OXM 的实现进行解组 Unmarshaller. Spring 的 Object/XML Mapping 支持提供了多种实现,这些实现通过使用 JAXBCastorJiBX 等支持编组和解组。 解组器需要Source. 如果消息负载不是Source,仍会尝试转换。 现在String,File,byte[]org.w3c.dom.Document支持有效负载。 要创建到Source中,您可以注入SourceFactory.spring-doc.cadn.net.cn

如果您没有显式设置SourceFactory,则UnmarshallingTransformer设置为DomSourceFactory.

从版本 5.0 开始,UnmarshallingTransformer还支持org.springframework.ws.mime.MimeMessage作为传入的负载。 当我们收到 raw 时,这可能很有用WebServiceMessage通过 SOAP 使用 MTOM 附件。 有关更多信息,请参阅 MTOM 支持spring-doc.cadn.net.cn

以下示例显示如何定义解组转换器:spring-doc.cadn.net.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 将对象图转换为 XMLMarshaller. 默认情况下,MarshallingTransformer返回DomResult. 但是,您可以通过配置替代项来控制结果的类型ResultFactoryStringResultFactory. 在许多情况下,将有效负载转换为替代 XML 格式会更方便。 为此,请配置ResultTransformer. Spring 集成提供了两种实现,一种转换为String另一个转换为Document. 下面的示例配置一个转换为文档的编组转换器:spring-doc.cadn.net.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>

默认情况下,MarshallingTransformer将 payload 对象传递给Marshaller. 但是,如果其布尔值extractPayload属性设置为false,则整个Message实例传递给Marshaller相反。 这对于Marshaller接口,但通常,当您委托给各种Marshaller实现。spring-doc.cadn.net.cn

XsltPayloadTransformer

XsltPayloadTransformer使用可扩展样式表语言转换 (XSLT) 转换 XML 负载。 转换器的构造函数需要传入 ResourceTemplates 的实例。 传入Templates实例允许对TransformerFactory用于创建模板实例。spring-doc.cadn.net.cn

UnmarshallingTransformerXsltPayloadTransformerSource. 因此,如果消息有效负载不是Source,仍会尝试转换。StringDocumentpayloads 直接受支持。spring-doc.cadn.net.cn

要创建到Source中,您可以注入SourceFactory.spring-doc.cadn.net.cn

如果SourceFactory未显式设置,则XsltPayloadTransformer设置为DomSourceFactory.

默认情况下,XsltPayloadTransformer创建一条消息Resultpayload 的 intent 与XmlPayloadMarshallingTransformer. 您可以通过提供ResultFactoryResultTransformer.spring-doc.cadn.net.cn

以下示例配置一个用作 XSLT 有效负载转换器的 Bean:spring-doc.cadn.net.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 开始,你可以使用构造函数参数来指定转换器工厂类名。 您可以使用transformer-factory-class属性。spring-doc.cadn.net.cn

ResultTransformer实现

MarshallingTransformerXsltPayloadTransformer让您指定一个ResultTransformer. 因此,如果封送处理或 XSLT 转换返回Result,您还可以选择使用ResultTransformer要转换Result转换为另一种格式。 Spring 集成提供了两个具体的ResultTransformer实现:spring-doc.cadn.net.cn

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

对于XsltPayloadTransformer. 默认情况下,如果输入有效负载是StringDocumentresultTransformer属性被忽略。spring-doc.cadn.net.cn

但是,如果输入负载是Source或任何其他类型,resultTransformer属性。 此外,您还可以设置alwaysUseResultFactoryproperty 设置为true,这也会导致指定的resultTransformer以供使用。spring-doc.cadn.net.cn

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

XML 转换器的命名空间支持

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

使用UnmarshallingTransformer

命名空间对UnmarshallingTransformer如下所示。 由于命名空间创建的是端点实例而不是转换器,因此您可以在元素中嵌套 Poller 来控制 input 通道的轮询。 以下示例显示了如何执行此作:spring-doc.cadn.net.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

编组转换器的命名空间支持需要一个input-channeloutput-channel和对marshaller. 您可以使用可选的result-type属性来控制创建的结果类型。 有效值为StringResultDomResult(默认值)。 以下示例配置编组转换器:spring-doc.cadn.net.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"/>

如果提供的结果类型不够用,则可以提供对ResultFactory作为设置result-type属性result-factory属性。 这result-typeresult-factory属性是互斥的。spring-doc.cadn.net.cn

在内部,StringResultDomResultresult 类型由ResultFactory实现:StringResultFactoryDomResultFactory分别。
使用XsltPayloadTransformer

命名空间支持XsltPayloadTransformer允许您传入Resource(为了创建Templates实例)或传入预先创建的Templates实例作为参考。 与编组转换器一样,您可以通过指定result-factoryresult-type属性。 当您需要在发送前转换结果时,您可以使用result-transformerattribute 来引用ResultTransformer.spring-doc.cadn.net.cn

如果指定result-factoryresult-type属性、alwaysUseResultFactory底层XsltPayloadTransformer设置为trueXsltPayloadTransformerParser.

以下示例配置两个 XSLT 转换器:spring-doc.cadn.net.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"/>

您可能需要有权访问Message数据,例如Messageheaders 来协助转换。 例如,您可能需要访问某些Messageheaders 并将它们作为参数传递给转换器(例如transformer.setParameter(..)). Spring 集成提供了两种便捷的方法来实现这一目标,如下例所示:spring-doc.cadn.net.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>

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

您还可以使用<xslt-param/>元素。 在该元素上,您可以设置expression属性或value属性。 这expression属性应该是任何有效的 SPEL 表达式,其中Message作为 expression 求值上下文的根对象。 这value属性(与任何value)允许您指定简单的标量值。 您还可以使用属性占位符(例如${some.value}). 因此,使用expressionvalue属性,您可以将 XSLT 参数映射到Message以及任何 Literal 值。spring-doc.cadn.net.cn

从 Spring Integration 3.0 开始,你现在可以通过在 3.0 中设置transformer-factory-class属性。spring-doc.cadn.net.cn

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

我们介绍了 result transformer 的使用ResultTransformer实现. 本节中的示例使用 XML 命名空间配置来说明几个特殊用例。 首先,我们定义ResultTransformer,如下例所示:spring-doc.cadn.net.cn

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

ResultTransformer接受StringResultDOMResult作为 input 进行转换,并将 input 转换为Document.spring-doc.cadn.net.cn

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

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

如果传入消息的有效负载的类型为Source,然后,作为第一步,Result通过使用ResultFactory. 由于我们没有指定ResultFactory,则默认的DomResultFactory,这意味着转换会生成一个DomResult.spring-doc.cadn.net.cn

但是,由于我们指定了ResultTransformer,则使用它,并且生成的Messagepayload 的类型为Document.spring-doc.cadn.net.cn

指定的ResultTransformer被忽略,替换为StringDocument负载。 如果传入消息的有效负载的类型为String,则 XSLT 转换后的有效负载是String. 同样,如果传入消息的有效负载的类型为Document,则 XSLT 转换后的有效负载为“Document”。

如果消息负载不是Source一个StringDocument作为后备选项,我们尝试使用默认的SourceFactory. 由于我们没有指定SourceFactory通过使用source-factory属性,则默认的DomSourceFactory被使用。 如果成功,则执行 XSLT 转换,就像有效负载的类型为Source,如前几段所述。spring-doc.cadn.net.cn

DomSourceFactory支持创建DOMSourceDocument一个FileString有效载荷。

下一个 transformer 声明添加了一个result-type属性,该属性使用StringResult作为其值。 这result-type在内部由StringResultFactory. 因此,您还可以添加对StringResultFactory,通过使用result-factory属性,这将是相同的。 以下示例显示了 transformer 声明:spring-doc.cadn.net.cn

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

因为我们使用ResultFactoryalwaysUseResultFactory属性的XsltPayloadTransformerclass 隐式设置为true. 因此,引用的ResultToDocumentTransformer被使用。spring-doc.cadn.net.cn

因此,如果您转换String,则生成的有效负载的类型为Document.spring-doc.cadn.net.cn

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

<xsl:output method="text"/>指示 XSLT 模板仅从输入源生成文本内容。 在这种特殊情况下,我们没有理由使用DomResult. 因此,XsltPayloadTransformer默认为StringResult如果名为method底层证券javax.xml.transform.Transformer返回text. 此强制执行独立于入站有效负载类型。 此行为仅可用,前提是您在result-type属性或result-factory属性<int-xml:xslt-transformer>元件。spring-doc.cadn.net.cn

使用 XPath 转换 XML 消息

在消息转换方面,XPath 是转换具有 XML 有效负载的消息的好方法。 为此,您可以使用<xpath-transformer/>元素。spring-doc.cadn.net.cn

简单的 XPath 转换

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

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

另请考虑以下几点Message:spring-doc.cadn.net.cn

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

将此消息发送到 'inputChannel' 后,之前配置的 XPath 转换器将此 XML 消息转换为简单的Message负载为“John Doe”,所有这些都基于xpath-expression属性。spring-doc.cadn.net.cn

XPath 还允许您将提取的元素简单转换为所需的类型。 有效的返回类型在javax.xml.xpath.XPathConstants并遵循javax.xml.xpath.XPath接口。spring-doc.cadn.net.cn

以下常量由XPathConstants类:BOOLEAN,DOM_OBJECT_MODEL,NODE,NODESET,NUMBERSTRING.spring-doc.cadn.net.cn

您可以使用evaluation-type属性的<xpath-transformer/>元素,如下例所示(两次):spring-doc.cadn.net.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.NodeMapper(由XPathOperations映射的实现Node对象)。 要提供对NodeMapper中,您可以使用node-mapper属性,如下例所示:spring-doc.cadn.net.cn

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

以下示例显示了NodeMapper与前面的示例一起使用的实现:spring-doc.cadn.net.cn

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

XML 负载转换器

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

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

以下示例显示了XmlPayloadConverter与前面的示例一起使用的实现:spring-doc.cadn.net.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();
  }
}

如果您未提供此引用,则DefaultXmlPayloadConverter被使用。 在大多数情况下,它应该足够了,因为它可以从Node,Document,Source,File,String,InputStreambyte[]负载。 如果您需要扩展该默认实现的功能之外,则 upstreamTransformer可能比在此处提供对此策略的自定义实现的引用更好。spring-doc.cadn.net.cn

拆分 XML 消息

XPathMessageSplitter支持带有StringDocument负载。 拆分器使用提供的 XPath 表达式将负载拆分为多个节点。 默认情况下,这会导致每个Node实例成为新消息的有效负载。 当每条消息都应该是一个Document中,您可以设置createDocuments旗。 其中 aStringpayload 传入,则 payload 会被转换,然后被分割,然后再转换回String消息。 XPath 拆分器实现MessageHandler因此,应与相应的端点一起配置(有关更简单的配置替代方案,请参阅以下示例后面的命名空间支持示例)。 以下示例配置一个 Bean,该 Bean 使用XPathMessageSplitter:spring-doc.cadn.net.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.cadn.net.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 开始,XPathMessageSplitter公开outputProperties(例如OutputKeys.OMIT_XML_DECLARATION) 属性的javax.xml.transform.Transformer实例时,请求payload不是类型org.w3c.dom.Node. 以下示例定义了一个属性,并将其与output-properties财产:spring-doc.cadn.net.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>

起始version 4.2XPathMessageSplitter暴露一个iterator选项作为booleanflag(默认为true). 这允许在下游流中 “流式处理” 拆分节点。 使用iteratormode 设置为true,则每个节点在迭代时都会进行转换。 什么时候false,在开始将拆分节点发送到输出通道之前,首先转换所有条目。 (您可以将差异视为“转换、发送、转换、发送”与“转换、转换、发送、发送”。 有关更多信息,请参阅 Splitterspring-doc.cadn.net.cn

使用 XPath 路由 XML 消息

与基于 SPEL 的路由器类似, Spring 集成提供了对基于 XPath 表达式的路由消息的支持,这允许你创建具有 input 通道但没有输出通道的消息端点。 相反,一个或多个 output channel 是动态确定的。 以下示例说明如何创建此类路由器:spring-doc.cadn.net.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 进行评估NODESET并转换为List<String>,表示频道名称。 通常,此类列表包含单个通道名称。 但是,根据 XPath 表达式的结果,如果 XPath 表达式返回多个值,则 XPath 路由器也可以具有收件人列表路由器的特征。 在这种情况下,List<String>包含多个频道名称。 因此,消息将发送到列表中的所有通道。spring-doc.cadn.net.cn

因此,假设传递给以下 router 配置的 XML 文件包含许多responder子元素,则消息将发送到所有这些通道:spring-doc.cadn.net.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/respondersexpression 会生成两个值 (responderAresponderB),但您不想将响应方名称与通道名称耦合,则可以提供其他映射配置,例如:spring-doc.cadn.net.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 表达式的默认计算类型为NODESET,该函数将转换为List<String>of channel names,用于处理单通道场景以及多通道场景。spring-doc.cadn.net.cn

尽管如此,某些 XPath 表达式的计算结果可能是 typeString从一开始。 例如,请考虑以下 XPath 表达式:spring-doc.cadn.net.cn

name(./node())

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

对于这些场景,您可以使用evaluate-as-string属性,用于管理评估类型。 是的FALSE默认情况下。 但是,如果将其设置为TRUEString使用 evaluation type 。spring-doc.cadn.net.cn

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

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

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

例如,如果我们想根据根节点的名称进行路由,我们可以使用以下配置:spring-doc.cadn.net.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 路由器支持XmlPayloadConverter策略,并在配置xpath-router元素中,可以通过converter属性。spring-doc.cadn.net.cn

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

XPath 标头扩充器

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

以下清单显示了所有可用的配置参数:spring-doc.cadn.net.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 值。 默认值为true. 如果 null 值应触发删除相应的标头,请将此项设置为false. 自选。
6 与 Header Enricher 一起使用的 Poller 。 自选。
7 要扩充的标头的名称。 命令的。
8 XPath 评估所需的结果类型。 如果您没有设置header-typeattribute,这是 header 值的类型。 允许使用以下值:BOOLEAN_RESULT,STRING_RESULT,NUMBER_RESULT,NODE_RESULTNODE_LIST_RESULT. 如果未设置,则它在内部默认为XPathEvaluationType.STRING_RESULT. 自选。
9 标头值类型的完全限定类名。 XPath 评估的结果通过以下方式转换为此类型ConversionService. 这允许,例如,一个NUMBER_RESULT(double) 转换为Integer. 该类型可以声明为原始 (例如int),但结果始终是等效的包装器类(例如Integer). 相同的集成ConversionService有效负载类型转换中讨论的转换,因此通过向服务添加自定义转换器来支持转换为自定义类型。 自选。
10 布尔值,用于指示此标头值是否应覆盖输入中已存在的同名现有标头值Message.
11 XPath 表达式作为String. 您必须设置此属性或xpath-expression-ref,但不能同时访问两者。
12 XPath 表达式引用。 您必须设置此属性或xpath-expression,但不能同时访问两者。

使用 XPath 过滤器

此组件定义基于 XPath 的消息过滤器。 在内部,这些组件使用MessageFilter,它包装了AbstractXPathMessageSelector.spring-doc.cadn.net.cn

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

要使用 XPath 过滤器,您至少必须通过声明xpath-expression元素中引用 XPath 表达式,或者在xpath-expression-ref属性。spring-doc.cadn.net.cn

如果提供的 XPath 表达式的计算结果为boolean值,则无需其他配置参数。 但是,如果 XPath 表达式的计算结果为String,您应该设置match-value属性,则与评估结果匹配。spring-doc.cadn.net.cn

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

  • exact:对应于equalsjava.lang.String. 底层实现使用StringValueTestXPathMessageSelectorspring-doc.cadn.net.cn

  • case-insensitive:对应于equals-ignore-casejava.lang.String. 底层实现使用StringValueTestXPathMessageSelectorspring-doc.cadn.net.cn

  • regex:匹配作 1java.lang.String. 底层实现使用RegexTestXPathMessageSelectorspring-doc.cadn.net.cn

当提供 'regex' 的 'match-type' 值时,使用match-valueattribute 必须是有效的正则表达式。spring-doc.cadn.net.cn

以下示例显示了xpath-filter元素:spring-doc.cadn.net.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-value. 默认值为exact. 自选。
5 要与 XPath 评估结果匹配的字符串值。 如果未设置此属性,则 XPath 计算必须生成布尔结果。 自选。
6 将匹配的邮件调度到的通道。 自选。
7 默认情况下,此属性设置为false和被拒绝的消息(那些与过滤条件不匹配的消息)将被静默丢弃。 但是,如果设置为true,则消息拒绝会导致错误情况和异常向上游传播到调用方。 自选。
8 对要评估的 XPath 表达式实例的引用。
9 此子元素设置要计算的 XPath 表达式。 如果不包含此元素,则必须将xpath-expression-ref属性。 此外,您只能包含一个xpath-expression元素。
10 用于 XPath 过滤器的 Poller。 自选。

#xpath SPEL 函数

Spring 集成,从 3.0 版本开始,提供了内置的#xpathSPEL 函数调用该函数的XPathUtils.evaluate(…​)static 方法。 此方法将org.springframework.xml.xpath.XPathExpression. 下面的清单显示了一些使用示例:spring-doc.cadn.net.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()还支持第三个可选参数,用于转换 XPath 评估的结果。 它可以是 String 常量 (string,boolean,number,node,node_listdocument_list) 或org.springframework.xml.xpath.NodeMapper实例。 默认情况下,#xpathSPEL 函数返回一个StringXPath 评估的表示形式。spring-doc.cadn.net.cn

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

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

XML 验证过滤器

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

未通过验证的消息可以被静默丢弃,也可以转发到可定义的discard-channel. 此外,你可以配置此过滤器以抛出Exception以防验证失败。spring-doc.cadn.net.cn

以下清单显示了所有可用的配置参数:spring-doc.cadn.net.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.Resource接口。 您可以设置此属性或xml-validator属性,但不能同时实现两者。 自选。
6 设置 Schema 类型。 可以是xml-schemarelax-ng. 自选。 如果未设置,则默认为xml-schema,在内部转换为org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML.
7 如果true一个MessageRejectedException如果提供的 Message 的有效负载验证失败,则引发。 默认为false如果未设置。 自选。
8 对自定义的引用org.springframework.integration.xml.XmlPayloadConverter策略。 自选。
9 对自定义的引用sorg.springframework.xml.validation.XmlValidator策略。 您可以设置此属性或schema-location属性,但不能同时实现两者。 自选。
10 用于 XPath 过滤器的 Poller。 自选。