Transforming XML Payloads
本节介绍如何转换 XML 有效负载
This section covers how to transform XML payloads
Configuring Transformers as Beans
本节将解释以下转换器的作用以及如何将其配置为 bean:
This section will explain the workings of the following transformers and how to configure them as beans:
所有 XML 转换器都扩展 AbstractTransformer
或 AbstractPayloadTransformer
,因此实现了 Transformer
。在 Spring Integration 中将 XML 转换器配置为 bean 时,通常会将 Transformer
与 MessageTransformingHandler
一起配置。这让转换器能够用作端点。最后,我们将讨论命名空间支持,它允许将转换器配置为 XML 中的元素。
All the XML transformers extend either AbstractTransformer
or AbstractPayloadTransformer
and therefore implement Transformer
.
When configuring XML transformers as beans in Spring Integration, you would normally configure the Transformer
in conjunction with a MessageTransformingHandler
.
This lets the transformer be used as an endpoint.
Finally, we discuss the namespace support, which allows for configuring the transformers as elements in XML.
UnmarshallingTransformer
UnmarshallingTransformer
允许使用 Spring OXM Unmarshaller
的实现对 XML Source
进行非编组。Spring 的 Object/XML Mapping 支持提供了一些实现,支持使用 JAXB、 Castor、 JiBX 等进行编组和非编组。解编组器需要 Source
的实例。如果消息有效负载不是 Source
的实例,仍然会尝试转换。目前,支持 String
、File
、byte[]
和 org.w3c.dom.Document
有效负载。若要创建到 Source
的自定义转换,可以注入 SourceFactory
的实现。
An UnmarshallingTransformer
lets an XML Source
be unmarshalled by using implementations of the Spring OXM Unmarshaller
.
Spring’s Object/XML Mapping support provides several implementations that support marshalling and unmarshalling by using JAXB, Castor, JiBX, and others.
The unmarshaller requires an instance of Source
.
If the message payload is not an instance of Source
, conversion is still attempted.
Currently, String
, File
, byte[]
and org.w3c.dom.Document
payloads are supported.
To create a custom conversion to a Source
, you can inject an implementation of a SourceFactory
.
如果您没有明确设置 |
If you do not explicitly set a |
从 5.0 版本开始,UnmarshallingTransformer
还支持 org.springframework.ws.mime.MimeMessage
作为传入有效负载。当我们收到带有 SOAP 的 MTOM 附件的原始 WebServiceMessage
时,这可能有用。有关详细信息,请参见 MTOM Support。
Starting with version 5.0, the UnmarshallingTransformer
also supports an org.springframework.ws.mime.MimeMessage
as the incoming payload.
This can be useful when we receive a raw WebServiceMessage
with MTOM attachments over SOAP .
See MTOM Support for more information.
以下示例显示了如何定义一个取消编组转换器:
The following example shows how to define an unmarshalling transformer:
<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>
Using MarshallingTransformer
MarshallingTransformer
允许使用 Spring OXM Marshaller
将对象图转换成 XML。默认情况下,MarshallingTransformer
返回 DomResult
。但可以通过配置其他 ResultFactory
(如 StringResultFactory
)来控制结果类型。很多时候,将有效负载转换成其他 XML 格式会更方便。为此,请配置 ResultTransformer
。Spring 集成提供了两个实现,一个转换成 String
,另一个转换成 Document
。以下示例配置了一个将文档转换的编组转换器:
The MarshallingTransformer
lets an object graph be converted into XML by using a Spring OXM Marshaller
.
By default, the MarshallingTransformer
returns a DomResult
.
However, you can control the type of result by configuring an alternative ResultFactory
, such as StringResultFactory
.
In many cases, it is more convenient to transform the payload into an alternative XML format.
To do so, configure a ResultTransformer
.
Spring integration provides two implementations, one that converts to String
and another that converts to Document
.
The following example configures a marshalling transformer that transforms to a document:
<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
将有效负载对象传递给 Marshaller
。但是,如果其布尔 extractPayload
属性设置为 false
,则整个 Message
实例将被传递给 Marshaller
。这对 Marshaller
接口的某些自定义实现可能很有用,但通常情况下,有效负载是在委托给任何各种 Marshaller
实现时编组的合适源对象。
By default, the MarshallingTransformer
passes the payload object to the Marshaller
.
However, if its boolean extractPayload
property is set to false
, the entire Message
instance is passed to the Marshaller
instead.
That may be useful for certain custom implementations of the Marshaller
interface, but, typically, the payload is the appropriate source object for marshalling when you delegate to any of the various Marshaller
implementations.
XsltPayloadTransformer
XsltPayloadTransformer
使用 Extensible Stylesheet Language Transformations(XSLT)转换 XML 有效负载。转换器的构造函数需要传递 Resource 或 Templates 实例。传递 Templates
实例允许对用于创建模板实例的 TransformerFactory
进行更高级别的配置。
The XsltPayloadTransformer
transforms XML payloads by using Extensible Stylesheet Language Transformations (XSLT).
The transformer’s constructor requires an instance of either Resource or Templates to be passed in.
Passing in a Templates
instance allows for greater configuration of the TransformerFactory
used to create the template instance.
与 UnmarshallingTransformer
一样,XsltPayloadTransformer
对 Source
实例执行实际 XSLT 转换。因此,如果消息有效负载不是 Source
的实例,系统仍会尝试转换。直接支持 String
和 Document
有效负载。
As with the UnmarshallingTransformer
, the XsltPayloadTransformer
does the actual XSLT transformation against instances of Source
.
Therefore, if the message payload is not an instance of Source
, conversion is still attempted.
String
and Document
payloads are supported directly.
若要创建到 Source
的自定义转换,可以注入 SourceFactory
的实现。
To create a custom conversion to a Source
, you can inject an implementation of a SourceFactory
.
如果未明确设置`SourceFactory`,则`XsltPayloadTransformer`上的属性默认设置为 link:https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/source/DomSourceFactory.html[ |
If a |
默认情况下,XsltPayloadTransformer
会创建一条包含 Result
有效负载的消息,类似于 XmlPayloadMarshallingTransformer
。可以通过提供 ResultFactory
或 ResultTransformer
来自定义此消息。
By default, the XsltPayloadTransformer
creates a message with a Result
payload, similar to the XmlPayloadMarshallingTransformer
.
You can customize this by providing a ResultFactory
or a ResultTransformer
.
以下示例配置了一个作为 XSLT 有效负载变换器的 bean:
The following example configures a bean that works as an XSLT payload transformer:
<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
属性来执行此操作。
Starting with Spring Integration 3.0, you can specify the transformer factory class name by using a constructor argument.
You can do so by using the transformer-factory-class
attribute when you use the namespace.
Using ResultTransformer
Implementations
MarshallingTransformer
和 XsltPayloadTransformer
都允许您指定 ResultTransformer
。因此,如果编组或 XSLT 转换返回 Result
,您可以选择还使用 ResultTransformer
将 Result
转换为另一种格式。Spring Integration 提供了两个具体的 ResultTransformer
实现:
Both the MarshallingTransformer
and the XsltPayloadTransformer
let you specify a ResultTransformer
.
Thus, if the marshalling or XSLT transformation returns a Result
, you have the option to also use a ResultTransformer
to transform the Result
into another format.
Spring Integration provides two concrete ResultTransformer
implementations:
默认情况下,MarshallingTransformer
始终返回 Result
。通过指定 ResultTransformer
,您可以自定义返回的有效负载类型。
By default, the MarshallingTransformer
always returns a Result
.
By specifying a ResultTransformer
, you can customize the type of payload returned.
对于 XsltPayloadTransformer
,该行为稍微复杂一些。默认情况下,如果输入有效负载是 String
或 Document
的实例,则将忽略 resultTransformer
属性。
The behavior is slightly more complex for the XsltPayloadTransformer
.
By default, if the input payload is an instance of String
or Document
the resultTransformer
property is ignored.
但是,如果输入有效负载是 Source
或任何其他类型,则将应用 resultTransformer
属性。此外,您可以将 alwaysUseResultFactory
属性设置为 true
,这还会导致使用指定的 resultTransformer
。
However, if the input payload is a Source
or any other type, the resultTransformer
property is applied.
Additionally, you can set the alwaysUseResultFactory
property to true
, which also causes the specified resultTransformer
to be used.
有关更多信息和示例,请参阅 Namespace Configuration and Result Transformers。
For more information and examples, see Namespace Configuration and Result Transformers.
Namespace Support for XML Transformers
Spring Integration XML 命名空间中提供了对所有 XML 变换器的命名空间支持,该命名空间的模板前面已经[显示,xpath-namespace-support]。针对变换器的命名空间支持会根据提供的输入通道的类型创建一个 EventDrivenConsumer
或 PollingConsumer
实例。命名空间支持旨在通过允许创建端点和使用一个元素的变换器来减少 XML 配置量。
Namespace support for all XML transformers is provided in the Spring Integration XML namespace, a template for which was xpath-namespace-support.
The namespace support for transformers creates an instance of either EventDrivenConsumer
or PollingConsumer
, according to the type of the provided input channel.
The namespace support is designed to reduce the amount of XML configuration by allowing the creation of an endpoint and transformer that use one element.
Using an UnmarshallingTransformer
UnmarshallingTransformer
的命名空间支持如下所示。由于命名空间创建端点实例而不是变换器,因此可以将轮询器嵌套在元素中以控制对输入通道的轮询。以下示例展示了如何执行此操作:
The namespace support for the UnmarshallingTransformer
is shown below.
Since the namespace create an endpoint instance rather than a transformer, you can nest a poller within the element to control the polling of the input channel.
The following example shows how to do so:
<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/>
Using a MarshallingTransformer
编组变换器的命名空间支持需要 input-channel
、output-channel
以及对 marshaller
的引用。可以使用可选的 result-type
属性来控制所创建结果的类型。有效值是 StringResult
或 DomResult
(默认值)。以下示例配置了一个编组变换器:
The namespace support for the marshalling transformer requires an input-channel
, an output-channel
, and a reference to a marshaller
.
You can use the optional result-type
attribute to control the type of result created.
Valid values are StringResult
or DomResult
(the default).
The following example configures a marshalling transformer:
<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-type
属性 result-factory
属性。result-type
和 result-factory
属性是互斥的。
Where the provided result types do not suffice, you can provide a reference to a custom implementation of ResultFactory
as an alternative to setting the result-type
attribute by using the result-factory
attribute.
The result-type
and result-factory
attributes are mutually exclusive.
在内部, |
Internally, the |
Using an XsltPayloadTransformer
XsltPayloadTransformer
的命名空间支持允许您传入 Resource
(以创建 Templates
实例)或作为引用传入一个预先创建的 Templates
实例。与编组转换器一样,您可以通过指定 result-factory
或 result-type
属性来控制结果输出的类型。在发送之前需要转换结果时,可以使用 result-transformer
属性来引用 ResultTransformer
的实现。
Namespace support for the XsltPayloadTransformer
lets you either pass in a Resource
(in order to create the Templates
instance) or pass in a pre-created Templates
instance as a reference.
As with the marshalling transformer, you can control the type of the result output by specifying either the result-factory
or the result-type
attribute.
When you need to convert result before sending, you can use a result-transformer
attribute to reference an implementation of ResultTransformer
.
如果您指定 result-factory`或`result-type`属性,`alwaysUseResultFactory`在底层 link:https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/transformer/XsltPayloadTransformer.html[`XsltPayloadTransformer`上的属性由 link:https://docs.spring.io/spring-integration/api/org/springframework/integration/xml/config/XsltPayloadTransformerParser.html[`XsltPayloadTransformerParser`设置为`true
。
If you specify the result-factory
or the result-type
attribute, the alwaysUseResultFactory
property on the underlying XsltPayloadTransformer
is set to true
by the XsltPayloadTransformerParser
.
以下示例配置了两个 XSLT 变换器:
The following example configures two XSLT transformers:
<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
数据(例如 Message
头),以协助转换。例如,可能需要访问某些 Message
头,并将它们作为参数传递给变换器(例如,transformer.setParameter(..)
)。Spring Integration 提供了两种方便的方法来实现此目的,如下面的示例所示:
You may need to have access to Message
data, such as the Message
headers, in order to assist with transformation.
For example, you may need to get access to certain Message
headers and pass them on as parameters to a transformer (for example, transformer.setParameter(..)
).
Spring Integration provides two convenient ways to accomplish this, as the following example shows:
<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
, *xxx
和 xxx*yyy
。
If message header names match one-to-one to parameter names, you can use the xslt-param-headers
attribute.
In it, you can use wildcards for simple pattern matching.
It supports the following simple pattern styles: xxx*
, xxx
, *xxx
, and xxx*yyy
.
还可以使用 <xslt-param/>
元素配置单个 XSLT 参数。在该元素上,可以设置 expression
属性或 value
属性。expression
属性应该是任何有效的 SpEL 表达式,其中 Message
是表达式的评估上下文的根对象。value
属性(就像 Spring bean 中的任何 value
一样)允许你指定简单的标量值。你还可以使用属性占位符(例如 ${some.value}
)。因此,通过 expression
和 value
属性,可以将 XSLT 参数映射到 Message
的任何可访问部分,以及任何文字值。
You can also configure individual XSLT parameters by using the <xslt-param/>
element.
On that element, you can set the expression
attribute or the value
attribute.
The expression
attribute should be any valid SpEL expression with the Message
being the root object of the expression evaluation context.
The value
attribute (as with any value
in Spring beans) lets you specify simple scalar values.
You can also use property placeholders (such as ${some.value}
).
So, with the expression
and value
attributes, you can map XSLT parameters to any accessible part of the Message
as well as any literal value.
从 Spring Integration 3.0 开始,现在可以通过设置 transformer-factory-class
属性来指定变换器工厂类名。
Starting with Spring Integration 3.0, you can now specify the transformer factory class name by setting the transformer-factory-class
attribute.
Namespace Configuration and Result Transformers
我们在 Using ResultTransformer
Implementations 中介绍了结果转换器的使用方法。本部分中的示例使用 XML 命名空间配置来说明几个特殊用例。首先,我们定义 ResultTransformer
,如下例所示:
We cover using result transformers in Using ResultTransformer
Implementations.
The examples in this section use XML namespace configuration to illustrates several special use cases.
First, we define the ResultTransformer
, as the following example shows:
<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
该 ResultTransformer
接受 StringResult
或 DOMResult
作为输入,并将该输入转换为 Document
。
This ResultTransformer
accepts either a StringResult
or a DOMResult
as input and converts the input into a Document
.
现在,我们可以声明转换器,如下所示:
Now we can declare the transformer, as follows:
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>
如果传入的消息有效负载为 Source
类型,那么第一步是使用 ResultFactory
确定 Result
。由于我们没有指定 ResultFactory
,因此使用了默认的 DomResultFactory
,这意味着转换产生了 DomResult
。
If the incoming message’s payload is of type Source
, then, as a first step, the Result
is determined by using the ResultFactory
.
As we did not specify a ResultFactory
, the default DomResultFactory
is used, meaning that the transformation yields a DomResult
.
但是,由于我们指定了 ResultTransformer
,因此它被使用,并且最终的 Message
有效负载为 Document
类型。
However, as we specified a ResultTransformer
, it is used and the resulting Message
payload is of type Document
.
指定了`ResultTransformer`时,String`或`Document`有效负载会将其忽略。如果传入消息的有效负载类型为`String
,则 XSLT 转换后的有效负载为`String`。同样,如果传入消息的有效负载类型为`Document`,则 XSLT 转换后的有效负载为`Document`。
The specified ResultTransformer
is ignored with String
or Document
payloads.
If the incoming message’s payload is of type String
, the payload after the XSLT transformation is a String
.
Similarly, if the incoming message’s payload is of type Document
, the payload after the XSLT transformation is a`Document`.
如果消息负载不是 Source
、 String`或 `Document
,作为备选方案,我们会尝试使用默认的 SourceFactory
来创建一个“Source”。由于我们没有使用 source-factory
属性显式指定 SourceFactory
,因此使用了默认的 DomSourceFactory
。如果成功,则 XSLT 转换的执行就像负载的类型为 Source
,如前几段所述。
If the message payload is not a Source
, a String
, or a Document
, as a fallback option, we try to create a`Source` by using the default SourceFactory
.
As we did not specify a SourceFactory
explicitly by using the source-factory
attribute, the default DomSourceFactory
is used.
If successful, the XSLT transformation is executed as if the payload was of type Source
, as described in the previous paragraphs.
|
The |
下一个转换器声明添加了 result-type
属性,它使用 StringResult
作为其值。result-type
在内部用 StringResultFactory
表示。因此,你还可以通过使用 result-factory
属性添加对 StringResultFactory
的引用,这是相同的。以下示例展示了转换器声明:
The next transformer declaration adds a result-type
attribute that uses StringResult
as its value.
The result-type
is internally represented by the StringResultFactory
.
Thus, you could have also added a reference to a StringResultFactory
, by using the result-factory
attribute, which would have been the same.
The following example shows that transformer declaration:
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
result-type="StringResult"/>
因为我们使用了 ResultFactory
,所以 XsltPayloadTransformer
类的 alwaysUseResultFactory
属性隐式设置为 true
。因此,使用了引用的 ResultToDocumentTransformer
。
Because we use a ResultFactory
, the alwaysUseResultFactory
property of the XsltPayloadTransformer
class is implicitly set to true
.
Consequently, the referenced ResultToDocumentTransformer
is used.
因此,如果您转换类型为 String
的负载,则结果负载的类型为 Document
。
Therefore, if you transform a payload of type String
, the resulting payload is of type Document
.
[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]]=== XsltPayloadTransformer`和 `<xsl:output method="text"/>
[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]]
=== XsltPayloadTransformer
and <xsl:output method="text"/>
<xsl:output method="text"/>
告诉 XSLT 模板仅从输入源生成文本内容。在这种特殊情况下,我们没有理由使用 DomResult
。因此,如果叫做 method
的 javax.xml.transform.Transformer
的 output property 返回 text
,则 XsltPayloadTransformer
默认为 StringResult
。此强制转换独立于入站负载类型执行。此行为只有在您为 <int-xml:xslt-transformer>
组件设置了 result-type
属性或 result-factory
属性时才可用。
<xsl:output method="text"/>
tells the XSLT template to produce only text content from the input source.
In this particular case, we have no reason to use a DomResult
.
Therefore, the XsltPayloadTransformer
defaults to StringResult
if the output property called method
of the underlying javax.xml.transform.Transformer
returns text
.
This coercion is performed independently from the inbound payload type.
This behavior is available only you set the if the result-type
attribute or the result-factory
attribute for the <int-xml:xslt-transformer>
component.