第6章 テンプレート
- 「断片ごと」にソースメッセージへ適用することができます。これはメッセージ全体に適用される断片ベースのトランスフォーメーションプロセスとは対照的です。 SOAP メッセージにヘッダーを追加する時など、 特定時にメッセージへデータを挿入する必要がある場合に断片ごとの適用は便利です。 この場合、 他の断片を混乱させることなくプロセスを使用して希望の断片を「狙う」ことができます。
- メッセージデータをデコードし、 Bean コンテキストへバインドできる Java Bean カートリッジなど、 Smooks のその他の技術を利用することができます。 FreeMarker テンプレート内よりデコードされたデータへの参照を作成します (Smooks は FreeMarker がデータを利用できるようにします)。
- 比較的単純な処理モデルと小型のメモリフットプリントを維持しながら、 同時に「巨大」メッセージストリーム (数ギガバイト以上) を処理するために使用できます。
- 分割メッセージ断片の生成に使用できます。 分割メッセージ断片は、 エンタープライズサービスバスにある物理または論理エンドポイントへルーティングすることができます。
6.1. FreeMarker テンプレート
http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd より Smooks の FreeMarker テンプレートを設定します。 その後、使用を開始するため統合開発環境で XSD を設定します。
例6.1 例 - インラインテンプレート
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<ftl:freemarker applyOnElement="order">
<ftl:template><!--<orderId>${order.id}</orderId>--></ftl:template>
</ftl:freemarker>
</smooks-resource-list>
例6.2 例 - 外部テンプレートの参照
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<ftl:freemarker applyOnElement="order">
<ftl:template>/templates/shop/ordergen.ftl</ftl:template>
</ftl:freemarker>
</smooks-resource-list>
例6.3 例 - テンプレート結果の「インライン化」
<ftl:freemarker applyOnElement="order">
<ftl:template>/templates/shop/ordergen.ftl</ftl:template>
<ftl:use>
<ftl:inline directive="insertbefore" />
</ftl:use>
</ftl:freemarker>
Smooks.filterSource の結果へ「インライン化」できるようにします。 複数の「指示文」がサポートされます。
- addto: ターゲット要素にテンプレーティングの結果を追加します。
- replace (デフォルト): テンプレートの結果を使用してターゲット要素を置き換えます。 <use> 要素が設定されていない場合、 <ftl:freemarker> 設定のデフォルト動作になります。
- insertbefore: ターゲット要素の前にテンプレーティングの結果を追加します。
- insertafter: ターゲット要素の後にテンプレーティングの結果を追加します。
例6.4 例 - テンプレーティングの結果を Smooks Bean コンテキストへバインドする
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jms="http://www.milyn.org/xsd/smooks/jms-routing-1.2.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<jms:router routeOnElement="order-item" beanId="orderItem_xml" destination="queue.orderItems" />
<ftl:freemarker applyOnElement="order-item">
<ftl:template>/orderitem-split.ftl</ftl:template>
<ftl:use>
<!-- Bind the templating result into the bean context, from where
it can be accessed by the JMSRouter (configured above). -->
<ftl:bindTo id="orderItem_xml"/>
</ftl:use>
</ftl:freemarker>
</smooks-resource-list>
OutputStreamResource クラスに書き込みます。 これは、 巨大なメッセージを小型で「消費可能」なメッセージに分割する便利なメカニズムの 1 つです。
例6.5 例 - テンプレートの結果を OutputStreamSource に書き込む
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.3.xsd"
xmlns:file="http://www.milyn.org/xsd/smooks/file-routing-1.1.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<!-- Create/open a file output stream. This is written to by the freemarker template (below).. -->
<file:outputStream openOnElement="order-item" resourceName="orderItemSplitStream">
<file:fileNamePattern>order-${order.orderId}-${order.orderItem.itemId}.xml</file:fileNamePattern>
<file:destinationDirectoryPattern>target/orders</file:destinationDirectoryPattern>
<file:listFileNamePattern>order-${order.orderId}.lst</file:listFileNamePattern>
<file:highWaterMark mark="3"/>
</file:outputStream>
<!--
Every time we hit the end of an <order-item> element, apply this freemarker template,
outputting the result to the "orderItemSplitStream" OutputStream, which is the file
output stream configured above.
-->
<ftl:freemarker applyOnElement="order-item">
<ftl:template>target/classes/orderitem-split.ftl</ftl:template>
<ftl:use>
<!-- Output the templating result to the "orderItemSplitStream" file output stream... -->
<ftl:outputTo outputStreamResource="orderItemSplitStream"/>
</ftl:use>
</ftl:freemarker>
</smooks-resource-list>
注記
6.2. NodeModels を使用して FreeMarker 変換を実行する
- 「断片毎」に実行する機能。 DOM モデルの基盤としてメッセージ全体ではなく、 ターゲットの断片のみを使用します。
- ストリーミングフィルター処理で
NodeModelを使用する機能。 - 形式が XML 以外のメッセージで使用する機能。
NodeModels が「キャプチャ」 (SAX ストリーミングの場合は「作成」) されたことを宣言する追加のリソースを定義します。
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.3.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<!--
Create 2 NodeModels. One high level model for the "order"
(header etc) and then one per "order-item".
These models are used in the FreeMarker templating resources
defined below. You need to make sure you set the selector such
that the total memory footprint is as low as possible. In this
example, the "order" model will contain everything accept the
<order-item> data (the main bulk of data in the message). The
"order-item" model only contains the current <order-item> data
(i.e. there's max 1 order-item in memory at any one time).
-->
<resource-config selector="order,order-item">
<resource>org.milyn.delivery.DomModelCreator</resource>
</resource-config>
<!--
Apply the first part of the template when we reach the start
of the <order-items> element. Apply the second part when we
reach the end.
Note the <?TEMPLATE-SPLIT-PI?> Processing Instruction in the
template. This tells Smooks where to split the template,
resulting in the order-items being inserted at this point.
-->
<ftl:freemarker applyOnElement="order-items">
<ftl:template><!--<salesorder>
<details>
<orderid>${order.@id}</orderid>
<customer>
<id>${order.header.customer.@number}</id>
<name>${order.header.customer}</name>
</customer>
<details>
<itemList>
<?TEMPLATE-SPLIT-PI?>
</itemList>
</salesorder>--></ftl:template>
</ftl:freemarker>
<!--
Output the <order-items> elements. This will appear in the
output message where the <?TEMPLATE-SPLIT-PI?> token appears in the
order-items template.
-->
<ftl:freemarker applyOnElement="order-item">
<ftl:template><!-- <item>
<id>${.vars["order-item"].@id}</id>
<productId>${.vars["order-item"].product}</productId>
<quantity>${.vars["order-item"].quantity}</quantity>
<price>${.vars["order-item"].price}</price>
<item>--></ftl:template>
</ftl:freemarker>
</smooks-resource-list>
注記
6.2.1. FreeMarker と Java Bean カートリッジ
NodeModel は高性能で簡単に使用することができますが、 パフォーマンスに影響します。 W3C DOM の構築は「低負荷」ではありません。 また、 データをオブジェクトセットとして Java メッセージサービスのエンドポイントにルーティングする必要がある場合など、 必要なデータが既に抽出され Java オブジェクトモデルへ投入されていることもあります。
NodeModel の使用が実用的でない場合、 Java Bean カートリッジを使用して適切な Java オブジェクトや仮想モデルへ投入してください。 その後、 このモデルを FreeMarker テンプレート処理で使用することができます。
例6.6 例 (仮想モデルを使用)
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.3.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<!-- Extract and decode data from the message. Used in the freemarker template (below). -->
<jb:bean beanId="order" class="java.util.Hashtable" createOnElement="order">
<jb:value property="orderId" decoder="Integer" data="order/@id"/>
<jb:value property="customerNumber" decoder="Long" data="header/customer/@number"/>
<jb:value property="customerName" data="header/customer"/>
<jb:wiring property="orderItem" beanIdRef="orderItem"/>
</jb:bean>
<jb:bean beanId="orderItem" class="java.util.Hashtable" createOnElement="order-item">
<jb:value property="itemId" decoder="Integer" data="order-item/@id"/>
<jb:value property="productId" decoder="Long" data="order-item/product"/>
<jb:value property="quantity" decoder="Integer" data="order-item/quantity"/>
<jb:value property="price" decoder="Double" data="order-item/price"/>
</jb:bean>
<ftl:freemarker applyOnElement="order-item">
<ftl:template><!--<orderitem id="${order.orderItem.itemId}" order="${order.orderId}">
<customer>
<name>${order.customerName}</name>
<number>${order.customerNumber?c}</number>
</customer>
<details>
<productId>${order.orderItem.productId}</productId>
<quantity>${order.orderItem.quantity}</quantity>
<price>${order.orderItem.price}</price>
</details>
</orderitem>-->
</ftl:template>
</ftl:freemarker>
</smooks-resource-list>
注記
6.2.2. プログラムを用いた設定
FreeMarkerTemplateProcessor インスタンスを追加し、 設定します。次の例は、 Java バインディングの設定と FreeMarker テンプレートの設定を Smooks に追加します。
Smooks smooks = new Smooks();
smooks.addVisitor(new Bean(OrderItem.class, "orderItem", "order-item").bindTo("productId", "order-item/product/@id"));
smooks.addVisitor(new FreeMarkerTemplateProcessor(new TemplatingConfiguration("/templates/order-tem.ftl")), "order-item");
// And then just use Smooks as normal... filter a Source to a Result etc...
6.2.3. XSL テンプレート
重要
enableFilterBypass というパラメータを追加し、false に設定します。
<param name="enableFilterBypass">false</param>
FreeMarkerTemplateProcessor の設定とほぼ同じです。 即座に使用するには、 http://www.milyn.org/xsd/smooks/xsl-1.1.xsd を統合開発環境に設定します。
例6.7 例
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:xsl="http://www.milyn.org/xsd/smooks/xsl-1.1.xsd">
<xsl:xsl applyOnElement="#document">
<xsl:template><!--<xxxxxx/>--></xsl:template>
</xsl:xsl>
</smooks-resource-list>
6.2.3.1. XSL サポートに関する注意
- メッセージ全体の変換ではなく、 断片の変換を実行する必要がある場合。
- Smooks の他の機能を使用して、 メッセージ上で分割や永続化などの追加操作を実行する必要がある場合。
- XSL テンプレーティングは DOM フィルタからのみサポートされます。 SAX フィルタからはサポートされません。 XSL の SAX ベースのアプリケーションと比較すると、 パフォーマンスが劣化する場合があります (適用された XSL によります)。
- Smooks はメッセージ断片ごとに XSL テンプレートを適用します。 これは、 XSL の断片化には大変便利ですが、 スタンドアロンコンテキスト向けに書かれたテンプレートが変更なしに Smooks で自動的に動作することを想定しません。 そのため、 Smooks はドキュメントルートノードへターゲットされた XSL には異なった処理を行い、 テンプレートをルート DOM 要素ではなく DOM ドキュメントノードへ適用します。
- ほとんどの XSL には root 要素と一致するテンプレートが含まれています。 これは、 Smooks は断片毎に XSL を適用しますが、 これが有効ではないためです。 スタイルシートにコンテキストノードに対して一致するテンプレートが含まれるようにしてください (ターゲットされた断片)。
6.2.3.2. 潜在的な問題: XSLT は外部で動作するが、 Smooks 内では動作しない
- ドキュメントルートノードへの絶対パス参照を使用するテンプレートがスタイルシートに含まれている場合、 この問題が Smooks の断片ベース処理モデルで発生します。 これは、 正しくない要素が Smooks によってターゲットされるためです。 この問題を修正するには、 Smooks によってターゲットされるコンテキストノードに一致するテンプレートが XSLT に含まれるようにしてください。
- SAX とDOM の処理: 現在、 Smooks は XSL の 処理に対して DOM ベース処理モデルのみをサポートしています。 正確な比較を行うには、 Smooks の外部で XSL テンプレートを実行する時に名前空間を認識する DOMSource を使用します (SAX または DOM を使用して XSL テンプレートを適用しようとする場合、 指定の XSL プロセッサが常に同じ出力を生成するとは限りません)。

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.