📈
段階的XSLT名前付きテンプレート導入
XSL Advent Calendar 2020 18日目の記事。
同人誌の方に収録予定の内容の一部。matchで順に変換できる元文書が無い場合を想定したnamedテンプレートだよ。でも<xsl:source-document>
とかにも応用可能ですね。
まず素の(X)HTMLを書く。named templateの中でもこの際構わない。
必要な要素のリストアップになる。
<main>
...
<article class="card">
<img class="img card-img img-fluid" decording="async"
src="hoge.jpg" alt="card image"/>
<div class="card-body">
<h1 class="card-title">TITLE</h1>
<p class="card-text"><strong>This</strong> card is ...</p>
</div>
</article>
...
</main>
繰り返し書くであろうattribute
を括り出していく。基本的に、1つの要素に対してxsl:use-attribute-sets
に書くattribute-set
名は1つが管理上望ましい。
<img>
の@src
や@alt
は個別の値にするのでここでは括り出さない。
<xsl:attribute-set name="atts.card">
<xsl:attribute name="class">card</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="atts.card.img">
<xsl:attribute name="class">img card-img img-fluid</xsl:attribute>
<xsl:attribute name="decording">async</xsl:attribute>
</xsl:attribute-set>
...
<xsl:template ...>
<main>
...
<article xsl:use-attribute-sets="atts.card">
<img xsl:use-attribute-sets="atts.card.img" src="hoge.jpg" alt="card image"/>
<div xsl:use-attribute-sets="atts.card.body">
<h1 xsl:use-attribute-sets="atts.card.body.title">TITLE</h1>
<p xsl:use-attribute-sets="atts.card.body.text"><strong>This</strong> card is ...</p>
</div>
</article>
...
</main>
</xsl:template>
<xsl:template>
で括り出し、大元の構造から外す。
<xsl:template name="card">
<article xsl:use-attribute-sets="atts.card">
<img xsl:use-attribute-sets="atts.card.img" src="hoge.jpg" alt="card image"/>
<div xsl:use-attribute-sets="atts.card.body">
<h1 xsl:use-attribute-sets="atts.card.body.title">TITLE</h1>
<p xsl:use-attribute-sets="atts.card.body.text"><strong>This</strong> card is ...</p>
</div>
</article>
</xsl:template>
<xsl:template ...>
...
<main>
...
<xsl:call-template name="card">
</xsl:call-template>
...
</main>
</xsl:template>
<xsl:template name="card">
で個別の内容を記述する箇所を抜き出してパラメータ化。ざっくりとっても構わない。で、大元の方にパラメータ化した内容を戻しておく。
<xsl:value-of>
がテキストとして抽出するのに対し、<xsl:copy-of>
は構造をそのまま持っていけるのでこういうこともできる。
<xsl:template name="card">
<xsl:param name="card.img" as="item()" required="yes"/>
<xsl:param name="card.body" as="item()" required="yes"/>
<article xsl:use-attribute-sets="atts.card">
<xsl:copy-of select="$card.img" />
<div xsl:use-attribute-sets="atts.card.body">
<xsl:copy-of select="$card.body"/>
</div>
</article>
</xsl:template>
<xsl:template ...>
<main>
...
<xsl:call-template name="card">
<xsl:with-param name="card.img" >
<img xsl:use-attribute-sets="atts.card.img" src="hoge.jpg" alt="card image"/>
</xsl:with-param>
<xsl:with-param name="card.body">
<h1 xsl:use-attribute-sets="atts.card.body.title">TITLE</h1>
<p xsl:use-attribute-sets="atts.card.body.text"><strong>This</strong> card is ...</p>
</xsl:with-param>
</xsl:call-template>
...
</main>
</xsl:template>
以下、同様にやっていく。
XML構造ライクな見た目になっていくので、将来的にShadow DOMとかに移行しやすいかもしれない。ホントか?
Discussion