📃

[XSLT 3.0]method="text"の出力にHTMLタグを出力する

2024/09/08に公開

「全体としての出力はテキストにしたいが、その中に配置するHTMLはタグをそのまま出したい」という要望があるとき、fn:serialize()が有用です。どんなときにそんなことをする羽目になるのかというと、「XSLTでHTMLを作ってそれを.astroファイルにしたい」というときです。XSLTで静的HTML作れるのに……と思わなくもないですが、ヘッダやフッタを後処理に回せるので非XSLT技術者でも触れるようになる、という利点があります。

MDXについてはこれから勉強するので適当。

astroの構成例
---
layout: hoge
---
<!DOCTYPE html>
<html >
<Head/>
<body>
<Header/>
<main>...<!--変換したコンテンツ本体--></main>
<Footer/>
</body>
</html>

シチュエーションとしては、別のmodeでHTML化した結果のdocument-node()を通す。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all">
    <xsl:output method="text" encoding="UTF-8"/>
...
    <xsl:template name="astronize">
       <xsl:param name="doc" as="document-node()"/>
        <xsl:text>
---
layout: hoge
---</xsl:text>
        <xsl:copy-of select="
                fn:serialize($doc, map{
                    'html-version': 5,
                    'method': 'html'
                })"/>
    </xsl:template>
    <xsl:template match="*" mode="html2astro">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="." mode="#current"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

serialize()は第一引数に対象を指定し、オプションの第二引数に<xsl:output>と同じパラメータを受け付けます。XSLT 3.0ではhtml-versionを指定することで。HTML5(Living Standardかは保証しない)出力にできるので、<!DOCTYPE html>を出せます。

参考資料

https://stackoverflow.com/questions/60620218/xslt-copy-element-with-method-text

https://www.w3.org/TR/xpath-functions-31/#func-serialize

組版・ドキュメンテーション勉強会

Discussion