📈

段階的XSLT名前付きテンプレート導入

2021/01/17に公開

XSL Advent Calendar 2020 18日目の記事。

https://adventar.org/calendars/5027

同人誌の方に収録予定の内容の一部。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