生産的で読みやすいXSLT:ヒントのコレクション

私の実践では、ほとんどの場合、XSLTはテンプレートエンジンとして使用されます。 これが起こる理由については説明しません。この技術の利点については十分に書かれています。 しかし、その欠点についてはさらに多くのことが書かれています。 XSLTは冗長で読みにくいと考えられており、最も生産的でもありません。 この記事では、読みやすさと表現力の観点からXSLTコードの品質を改善するためのヒントを集めてみます。 それらのいくつかは、XSLTが少し速く動作することも可能にします。



名前付きテンプレート


XSLTの「問題」の多くは、手続き型スタイルでXSLTに書き込もうとすることが多いという事実に関連しています。 私たちは絶えずSmartyを排除しようとしていますが、1つの単純な事実に遭遇します。XSLTは、どんなに珍しくても、宣言型言語です。

たとえば、名前付きテンプレートを使用して、特定の形式でデータを出力するプロシージャとして認識します。



< xsl:template name ="CreateItemLink" >

< xsl:param name ="item" />

< a href ="/item/?id={$item/id}" >

< xsl:value-of select ="$item/name" />

</ a >< br />

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






おそらく、多くのプログラマーが最初のテンプレートをこの方法で作成しました。 そして彼は自分の問題をうまく解決しています。 XSLT宣言は、少し異なるアプローチを提供します。



< xsl:template match ="item" >

< a href ="/item/?id={id}" >

< xsl:value-of select ="name" />

</ a >< br />

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






違いはまったく大きくありません。 好みとプログラミングのスタイルの問題。 テンプレートが将来どのように使用されるかを見てみましょう。





XSL:for-eachおよびxsl:apply-templates


次のように、テンプレートの「命令型」バージョンを使用します。



< xsl:template match ="/" >

< h1 > My market </ h1 >

< xsl:for-each select ="/root/market/item" >

< xsl:call-template name ="CreateItemLink" >

< xsl:with-param name ="item" select ="." />

</ xsl:call-template >

</ xsl:for-each >

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






「宣言的」-このように:



< xsl:template match ="/" >

< h1 > My market </ h1 >

< xsl:apply-templates select ="/root/market/item" />

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






今、違いははるかに顕著になっています:



XSL:選択してください


Xsl:chooseは、おそらくXSLTで最も冗長な構成要素の1つです。 多くの場合、次のように使用されます。



< xsl:template match ="product" >

...

< xsl:choose >

< xsl:when test ="currencyCode = 'eur'" >

< xsl:value-of select ="'Euros'" />

</ xsl:when >

< xsl:when test ="currencyCode = 'usd'" >

< xsl:value-of select ="'Dollars'" />

</ xsl:when >

< xsl:when test ="currencyCode = 'cad'" >

< xsl:value-of select ="'Canadian dollars'" />

</ xsl:when >

...

</ xsl:choose >

...

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






単に使用する必要がある場合があります。 ただし、この例では、外部ドキュメントと辞書を使用する方がはるかに正確です。



<? xml version ="1.0" ? >

< currencies >

< currency >

< code > eur </ code >

< name > Euros </ name >

</ currency >

< currency >

< code > usd </ code >

< name > Dollars </ name >

</ currency >

< currency >

< code > cad </ code >

< name > Canadian dollars </ name >

</ currency >

...

</ currencies >




* This source code was highlighted with Source Code Highlighter .






document()関数とXPathを使用して、テンプレートからアクセスできます。



< xsl:variable name ="currencies"

select ="document('cur.xml')/currencies" />



< xsl:template match ="product" >

...

< xsl:value-of select ="$currencies/currency[code=currencyCode]/name" />

...

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






そのようなコードは保守がはるかに簡単で、イデオロギー的にもより正確であるように思えます-データはデータのままであり、読みにくいコードに変換されるべきではありません。



組み込みの変換


多くの人は、XSLTがプログラマーの作業の一部を行ういくつかの「組み込み」変換を持っていることを知りません。 これらの変換は、XSLTプロセッサのレベルで実行されます。 一部の実装では、「手動」実装よりもはるかに生産的に動作できます。

たとえば、組み込みの変換により、テンプレートは現在のノードの子孫に再帰的に適用されます。 これはそのようなパターンと同等です:



< xsl:template match ="*|/" >

< xsl:apply-templates />

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






さらに、apply-templatesでモードが使用されている場合、子ノードもこのモードで変換されます。 別の例は、テキストノードと属性の自動出力です。



< xsl:template match ="text()|@*" >

< xsl:value-of select ="." />

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






これは、代わりに



< xsl:template match ="name" >

< name >< xsl:value-of select ="." /></ name >

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






使用できます



< xsl:template match ="name" >

< name >< xsl:apply-templates /></ name >

</ xsl:template >




* This source code was highlighted with Source Code Highlighter .






これは(おそらく)より速く動作し、テンプレートをより柔軟で拡張性のあるものにします。

標準のセクション



連結()関数


テンプレートを読むときに最も厄介なのは、次のコードです。



< xsl:value-of select ="$string1" />

< xsl:text > - </ xsl:text >

< xsl:value-of select ="$string2" />

< xsl:text > ... </ xsl:text >




* This source code was highlighted with Source Code Highlighter .






このような場合、1つの<xsl:value-of />を使用する方がはるかに便利であり、残りのフォーマットはconcat()を使用して行う必要があります。



< xsl:value-of select ="concat($string1, ' - ', $string2, '...')" />



* This source code was highlighted with Source Code Highlighter .






一般に、XPathにはコードを簡素化するために使用できる多くの組み込み関数があります。 例付きの優れたドキュメントはここにあります 。 特に部分文字列()、翻訳()などに注意する価値があります。 これらの関数は、PHPや他の外部言語で実装するべきではありません-XSLTプロセッサはそれをさらに改善します。



意図したとおりのxsl:要素の使用


Xsl:要素は、要素の名前が動的に決定される場合にのみ必要です。



< xsl:variable name ="s" > hello </ xsl:variable >

< xsl:element name ="{$s}" >

< xsl:attribute name ="site" > habr.ru </ xsl:attribute >

< xsl:value-of select ="{concat(' ', $username)}" />

</ xsl:element >




* This source code was highlighted with Source Code Highlighter .






その他の場合はすべて、タグ自体を作成できます。 そうしないと、コードが冗長になりすぎて目的がありません。



< hello site ="http://habr.ru/" >

< xsl:value-of select ="{concat(' ', $username)}" />

</ hello >




* This source code was highlighted with Source Code Highlighter .






私はまだ同様のヒントを集めています。 追加するものがある場合は、コメントの登録を解除してください。



All Articles