任意の変換操作を実行できるジェネリック for テンプレートを作成する戦略があれば、それは素晴らしいことです。再帰イテレータを使用せずに済む場合、この目的のための関数の宝石が XSLT 1.0 に隠されている場合、それは同様に素晴らしいことです。
とにかく、どうすればこれを達成できますか?WET アプローチに頼る必要がありますか、それとももっと良い方法がありますか?
必要な DRY ネスは、FXSLのテンプレート/関数の簡単なアプリケーションiter
です。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/" xmlns:myRepeat="f:myRepeat"
exclude-result-prefixes="xsl f myRepeat">
<xsl:import href="iter.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<myRepeat:myRepeat/>
<xsl:variable name="vFunRepeat" select="document('')/*/myRepeat:*[1]"/>
<xsl:variable name="vAdditive" select="/*/*[1]"/>
<xsl:template match="/*">
<xsl:call-template name="iter">
<xsl:with-param name="pTimes" select="@count"/>
<xsl:with-param name="pFun" select="$vFunRepeat"/>
<xsl:with-param name="pX" select="/.."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="myRepeat:*" mode="f:FXSL">
<xsl:param name="arg1"/>
<xsl:copy-of select="$arg1 | $vAdditive"/>
</xsl:template>
</xsl:stylesheet>
この変換が提供された XML ドキュメントに適用されると、次のようになります。
<items count="3">
<item>
<name>Name</name>
<description>Description</description>
</item>
</items>
必要な正しい結果が生成されます。
<item>
<name>Name</name>
<description>Description</description>
</item>
<item>
<name>Name</name>
<description>Description</description>
</item>
<item>
<name>Name</name>
<description>Description</description>
</item>
注意してください:
再帰的なテンプレートを書く必要はまったくありません。
テンプレートは、他のほとんどの FXSLのiter
テンプレートと同様に、非常に一般的で強力であり、プログラマーが何度も再帰を記述してデバッグする必要がなくなります。
FXSL は、必要な DRY 性を提供し、より抽象的な思考を刺激します。つまり、より強力な構成要素 (関数、折り畳み、反復など) です。
この問題は、XSLT 2.0 で自明な解決策を持っている ( <xsl:for-each select="1 to @count">
) ためですが、他にも多くの問題があり、XSLT 2.0 での解決策はそれほど単純ではありません。FXSL は、折り畳み、マップ、スキャン、zip など、最も一般的で強力な高次関数の汎用的で強力な実装を使用して、このような「難しい」問題を解決するのに役立ちます。
Ⅱ.Piez 法を使用する( の値に既知の上限がある場合@count
)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vStyle" select="document('')"/>
<xsl:variable name="vNodes" select=
"$vStyle//node()|$vStyle//@* | $vStyle//namespace::*"/>
<xsl:variable name="vAdditive" select="/*/*[1]"/>
<xsl:template match="/*">
<xsl:for-each select="$vNodes[not(position() > current()/@count)]">
<xsl:copy-of select="$vAdditive"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
この変換を同じ XML ドキュメント (上記) に適用すると、同じ正しい結果が生成されます。
<item>
<name>Name</name>
<description>Description</description>
</item>
<item>
<name>Name</name>
<description>Description</description>
</item>
<item>
<name>Name</name>
<description>Description</description>
</item>
注意してください:
Piez 法を使用できる場合、再帰は完全に回避されます。
免責事項:
私は 11 ~ 12 年前に FXSL を開発できてうれしかったです。それ以来、免責事項を提供する必要があることを知らずに、2 つの会議論文を含め、何千回も言及してきました:)