この部分を 敢えてBPEL だけで書いたらこんな風になるけど...
...実際にはそんなフローを書く人は少ない。BPEL やワークフローを体系的に勉強していなくても、こんな粒度の細々したステップを書くのはまずかろうと、いくらなんでも普通は気づく(IDE は JDeveloper)。
で XSLT で書いたりするが、惜しいかな、いかにも手続き型っぽいこんな感じのコードが多い。
<xsl:template match="/">JDeveloper の XSLマップ デザイナ前提だと手続き型になるしかないけど、上記コードは実はこの時点でデザイナが使えなくなってる。<for-each> の使い方が違うとか、<choose> 内には<when> 要素が必要だとか意味不明なことを言ってくるが、見ての通りそんな問題は存在しない。
<client:processResponse>
<client:result>
<xsl:for-each select="/client:process/client:input">
<xsl:choose>
<xsl:when test="position() > 1">
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</client:result>
</client:processResponse>
</xsl:template>
というわけで、これ以上糞ツールに気を使っても面白くないので、XSLT らしく関数型で書いてみる。
<xsl:template match="/">繰り返し文や条件文を全否定する気はサラサラないけど、関数型の書法の方が応用が利くので、こっちの方がお勧め。
<client:processResponse>
<client:result>
<xsl:apply-templates select="client:process/client:input[1]"/>
</client:result>
</client:processResponse>
</xsl:template>
<xsl:template match="client:input[following-sibling::client:input]">
<xsl:value-of select="."/>
<xsl:text>-</xsl:text>
<xsl:apply-templates select="following-sibling::client:input[1]"/>
</xsl:template>
<xsl:template match="client:input[not(following-sibling::client:input)]">
<xsl:value-of select="."/>
</xsl:template>
もう一個の改善点は、XSLT 変換の範囲。
上記コードは、もともと Transform アクティビティ生成の結果作られたものを書き直したものなので、BPEL側の<assign>ではメッセージタイプからメッセージタイプへの変換になっている。従って、client:processResponse がもっと複雑な構造だと、<xsl:template match="/"> の中に 要素の複製や空要素の生成など無駄なコードが大量発生がちなので、次はこれを改善。
<xsl:template match="/">
<xsl:apply-templates select="client:process/client:input[1]"/>
</xsl:template>
<xsl:template match="client:input[following-sibling::client:input]">
以下同文
上記コードの出力は連結したテキストのみとなるので、このXSLTの出力を受ける BPEL 内の<to>要素に query 属性で processResponse/client:result を指定しておけば、最小限の要素をピンポイントで指定したコードになる。(XSLT内に<xsl:output method="text"/>も含めておく)
実は、更にもう一段階ある。
どうも JDeveloperでは、標準的な XSLT 関数なのに IDE的にサポートされていないものがあるらしい。例えば document()関数なども、ドロップダウンリストに表示されなかったりする。
ここまで例として取り上げてきた文字列の連結では、string-join 関数が使える。せっかく再帰で書いた上の XSLTコードがもったいないけど、実は 3行で書けちゃったりする。
<xsl:template match="/client:process">
<xsl:value-of select="string-join(client:input, ',')"/>
</xsl:template>
うーん、なんだか今日はずいぶん無駄なコードを書いたかも・・・
0 件のコメント:
コメントを投稿