轉換 XML 酬載

本節涵蓋如何轉換 XML 酬載

將轉換器設定為 Bean

本節將說明以下轉換器的工作原理以及如何將它們設定為 Bean

所有 XML 轉換器都擴充 AbstractTransformerAbstractPayloadTransformer,因此實作 Transformer。在 Spring Integration 中將 XML 轉換器設定為 Bean 時,您通常會將 TransformerMessageTransformingHandler 結合設定。這讓轉換器可以用作端點。最後,我們討論命名空間支援,它允許將轉換器設定為 XML 中的元素。

UnmarshallingTransformer

UnmarshallingTransformer 讓 XML Source 可以使用 Spring OXM Unmarshaller 的實作進行解組。Spring 的物件/XML 對應支援提供了多種實作,支援使用 JAXBCastorJiBX 等進行組譯和解組。解組器需要 Source 的實例。如果訊息酬載不是 Source 的實例,仍然會嘗試轉換。目前,支援 StringFilebyte[]org.w3c.dom.Document 酬載。若要建立自訂轉換為 Source,您可以注入 SourceFactory 的實作。

如果您未明確設定 SourceFactory,則 UnmarshallingTransformer 上的屬性預設會設定為 DomSourceFactory

從 5.0 版開始,UnmarshallingTransformer 也支援 org.springframework.ws.mime.MimeMessage 作為傳入酬載。當我們透過 SOAP 接收具有 MTOM 附件的原始 WebServiceMessage 時,這會很有用。如需詳細資訊,請參閱 MTOM 支援

以下範例示範如何定義解組轉換器

<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 Marshaller 轉換為 XML。預設情況下,MarshallingTransformer 會傳回 DomResult。但是,您可以透過設定替代的 ResultFactory(例如 StringResultFactory)來控制結果類型。在許多情況下,將酬載轉換為替代的 XML 格式會更方便。若要執行此操作,請設定 ResultTransformer。Spring Integration 提供了兩個實作,一個轉換為 String,另一個轉換為 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 實作時,酬載是組譯的適當來源物件。

XsltPayloadTransformer

XsltPayloadTransformer 使用 可延伸樣式表語言轉換 (XSLT) 轉換 XML 酬載。轉換器的建構函式需要傳入 ResourceTemplates 的實例。傳入 Templates 實例可以更廣泛地設定用於建立範本實例的 TransformerFactory

UnmarshallingTransformer 一樣,XsltPayloadTransformer 會針對 Source 實例執行實際的 XSLT 轉換。因此,如果訊息酬載不是 Source 的實例,仍然會嘗試轉換。直接支援 StringDocument 酬載。

若要建立自訂轉換為 Source,您可以注入 SourceFactory 的實作。

如果未明確設定 SourceFactory,則 XsltPayloadTransformer 上的屬性預設會設定為 DomSourceFactory

預設情況下,XsltPayloadTransformer 會建立具有 Result 酬載的訊息,類似於 XmlPayloadMarshallingTransformer。您可以透過提供 ResultFactoryResultTransformer 來自訂此設定。

以下範例設定一個作為 XSLT 酬載轉換器運作的 Bean

<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 屬性來執行此操作。

使用 ResultTransformer 實作

MarshallingTransformerXsltPayloadTransformer 都允許您指定 ResultTransformer。因此,如果組譯或 XSLT 轉換傳回 Result,您可以選擇使用 ResultTransformerResult 轉換為另一種格式。Spring Integration 提供了兩個具體的 ResultTransformer 實作

預設情況下,MarshallingTransformer 始終傳回 Result。透過指定 ResultTransformer,您可以自訂傳回的酬載類型。

對於 XsltPayloadTransformer,行為稍微複雜一些。預設情況下,如果輸入酬載是 StringDocument 的實例,則會忽略 resultTransformer 屬性。

但是,如果輸入酬載是 Source 或任何其他類型,則會套用 resultTransformer 屬性。此外,您可以將 alwaysUseResultFactory 屬性設定為 true,這也會導致使用指定的 resultTransformer

如需更多資訊和範例,請參閱 命名空間設定和結果轉換器

XML 轉換器的命名空間支援

Spring Integration XML 命名空間中提供了所有 XML 轉換器的命名空間支援,其範本如 先前所示。轉換器的命名空間支援會根據提供的輸入通道類型建立 EventDrivenConsumerPollingConsumer 的實例。命名空間支援旨在透過允許建立使用一個元素的端點和轉換器來減少 XML 設定量。

使用 UnmarshallingTransformer

以下顯示 UnmarshallingTransformer 的命名空間支援。由於命名空間建立端點實例而不是轉換器,因此您可以將 poller 巢狀於元素內,以控制輸入通道的輪詢。以下範例示範如何執行此操作

<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(預設值)。以下範例設定一個組譯轉換器

<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 屬性是互斥的。

在內部,StringResultDomResult 結果類型由 ResultFactory 實作表示:StringResultFactoryDomResultFactory

使用 XsltPayloadTransformer

XsltPayloadTransformer 的命名空間支援讓您可以傳入 Resource(為了建立 Templates 實例),或傳入預先建立的 Templates 實例作為參考。與組譯轉換器一樣,您可以透過指定 result-factoryresult-type 屬性來控制結果輸出的類型。當您需要在傳送之前轉換結果時,可以使用 result-transformer 屬性來參考 ResultTransformer 的實作。

如果您指定 result-factoryresult-type 屬性,則 XsltPayloadTransformer 上的 alwaysUseResultFactory 屬性會由 XsltPayloadTransformerParser 設定為 true

以下範例設定兩個 XSLT 轉換器

<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 提供了兩種方便的方法來完成此操作,如以下範例所示

<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

您也可以使用 <xslt-param/> 元素設定個別的 XSLT 參數。在該元素上,您可以設定 expression 屬性或 value 屬性。expression 屬性應該是任何有效的 SpEL 運算式,其中 Message 是運算式評估內容的根物件。value 屬性(與 Spring Bean 中的任何 value 一樣)讓您可以指定簡單的純量值。您也可以使用屬性預留位置(例如 ${some.value})。因此,透過 expressionvalue 屬性,您可以將 XSLT 參數對應到 Message 的任何可存取部分以及任何常值。

從 Spring Integration 3.0 開始,您現在可以透過設定 transformer-factory-class 屬性來指定轉換器工廠類別名稱。

命名空間設定和結果轉換器

我們在 使用 ResultTransformer 實作 中涵蓋了使用結果轉換器。本節中的範例使用 XML 命名空間設定來說明幾個特殊的使用案例。首先,我們定義 ResultTransformer,如以下範例所示

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

ResultTransformer 接受 StringResultDOMResult 作為輸入,並將輸入轉換為 Document

現在我們可以宣告轉換器,如下所示

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

如果傳入訊息的酬載類型為 Source,則第一步是使用 ResultFactory 判斷 Result。由於我們未指定 ResultFactory,因此使用預設的 DomResultFactory,這表示轉換會產生 DomResult

但是,由於我們指定了 ResultTransformer,因此會使用它,且產生的 Message 酬載類型為 Document

對於 StringDocument 酬載,會忽略指定的 ResultTransformer。如果傳入訊息的酬載類型為 String,則 XSLT 轉換後的酬載為 String。同樣地,如果傳入訊息的酬載類型為 Document,則 XSLT 轉換後的酬載為 Document

如果訊息酬載不是 SourceStringDocument,作為後備選項,我們會嘗試使用預設的 SourceFactory 建立 Source。由於我們未使用 source-factory 屬性明確指定 SourceFactory,因此會使用預設的 DomSourceFactory。如果成功,則會執行 XSLT 轉換,如同酬載類型為 Source 一樣,如前幾段所述。

DomSourceFactory 支援從 DocumentFileString 酬載建立 DOMSource

下一個轉換器宣告新增了一個 result-type 屬性,該屬性使用 StringResult 作為其值。result-type 在內部由 StringResultFactory 表示。因此,您也可以新增對 StringResultFactory 的參考,方法是使用 result-factory 屬性,這會是相同的。以下範例顯示該轉換器宣告

<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

因此,如果您轉換類型為 String 的酬載,則產生的酬載類型為 Document

[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]] === XsltPayloadTransformer<xsl:output method="text"/>

<xsl:output method="text"/> 告知 XSLT 範本僅從輸入來源產生文字內容。在這種特殊情況下,我們沒有理由使用 DomResult。因此,如果基礎 javax.xml.transform.Transformer輸出屬性 稱為 method,則 XsltPayloadTransformer 預設為 StringResult。此強制轉換獨立於輸入酬載類型執行。只有在您為 <int-xml:xslt-transformer> 元件設定 result-type 屬性或 result-factory 屬性時,此行為才可用。