💭

VSCodeとXSLTを用いたTEI/XMLのリアルタイムプレビュー

2025/01/15に公開

概要

VSCodeとXSLTを用いたTEI/XMLのリアルタイムプレビュー環境を試作したので、備忘録です。

挙動

動作例は以下です。TEI/XMLファイルを編集し、保存すると、ブラウザの表示内容が更新されます。

https://youtu.be/ZParCRUc5AY?si=-aHHi3bIZGWoJYnP

準備

以下の拡張機能をインストールします。

TEI/XMLを保存した際に、Trigger Task on SaveによってXSLTを実行し、変換されたHTMLファイルをLive Serverで閲覧します。

リポジトリ

サンプルコードを以下に格納しています。

https://github.com/nakamura196/tei-xml-xslt-vscode

XSLTを行うにあたり、xslt3をインストールします。

git clone https://github.com/nakamura196/tei-xml-xslt-vscode
cd tei-xml-xslt-vscode
npm install

settings.jsonとtasks.json

.vscodeフォルダに、settings.jsontasks.jsonを格納しています。

tasks.jsonは以下です。xsl/make-CETEIcean.xslを用いて、XSLTを行うタスクを設定しています。

.vscode/tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Transform XML with XSLT",
      "type": "shell",
      "command": "npx",
      "args": [
        "xslt3",
        "-xsl:xsl/make-CETEIcean.xsl",
        "-s:${file}",
        "-o:${fileDirname}/${fileBasenameNoExtension}.html"
      ],
      "presentation": {
        "reveal": "never",
        "close": true
      },
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "problemMatcher": []
    }
  ]
}

xsl/make-CETEIcean.xslは、CETEIceanで公開されているXSLファイルです。

https://github.com/TEIC/CETEIcean/blob/master/xslt/make-CETEIcean.xsl

次に、settings.jsonです。teiフォルダ以下のxmlファイルに対して、保存時に上記のタスクを実行します。

.vscode/settings.json
{
  "triggerTaskOnSave.tasks": {
    "Transform XML with XSLT": ["tei/*.xml"]
  }
}

これらの設定により、TEI/XMLファイルを保存時に、同フォルダにHTMLファイルが作成されます。

サンプルファイル

TEI/XMLファイルの例は以下です。xsl/make-CETEIcean.xslにより、rendition要素で設定したスタイルが適用されます。

tei/example1.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
    <teiHeader>
        <fileDesc>
            <titleStmt>
                <title>CETEICean Demo</title>
                <author>Satoru Nakamura</author>
            </titleStmt>
            <publicationStmt>
                <p></p>
            </publicationStmt>
            <sourceDesc>
                <p></p>
            </sourceDesc>
        </fileDesc>
        <encodingDesc>
            <tagsDecl>
                <rendition scheme="css" xml:id="italic">font-style: italic;</rendition>
                <rendition scheme="css" selector="title">text-decoration: underline;</rendition>
                <rendition scheme="css" selector="persName">color: green;</rendition>
            </tagsDecl>
        </encodingDesc>
    </teiHeader>
    <text>
        <body>
            <div>
                <p>
                    <!--
                    <title xml:id="foo" xml:lang="de">Die Leiden des jungen Werther</title>
                    -->
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                    <lb/>
                </p>
            </div>
            <div>
                <p>
                    CETEIceanは<ref target="https://github.com/TEIC/CETEIcean">こちら</ref>を参考にしてください。
                </p>
                <p>
                    こちらは
                    <persName>人名</persName>のマークアップの例です。
                    はじめてのテキストです。
                </p>
                <p>
                    第二段落のテキストです。
                </p>
                <p>
                    第三段落のテキストです。
                </p>
                <p>
                    第四段落のテキストです。
                </p>
            </div>
            <div>
                <ab>任意のブロックです。</ab>
            </div>
            <div>
                <ab>
                    <table rows="4" cols="4">
                        <head>はじめての表です。</head>
                        <row role="label">
                            <cell role="data"/>
                            <cell role="data"></cell>
                            <cell role="data"></cell>
                            <cell role="data"></cell>
                        </row>
                        <row role="data">
                            <cell role="label"></cell>
                            <cell role="data"></cell>
                            <cell role="data"></cell>
                            <cell role="data"></cell>
                        </row>
                    </table>
                </ab>
            </div>

        </body>
    </text>
</TEI>

変換結果のHTMLファイルは以下です。TEI/XMLのlb要素などが、HTMLのtei-lb要素に変換され、これに対して、cssファイルやjsファイルが適用されます。

tei/example1.html
<!DOCTYPE html><!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" href="https://teic.github.io/CETEIcean/css/CETEIcean.css"><script type="text/javascript" src="https://github.com/TEIC/CETEIcean/releases/download/v0.4.0/CETEI.js"></script><style>
.            italic
 {
            font-style: italic;
       
}
        tei-title {
            text-decoration: underline;
       
}
        tei-persName {
            color: green;
       
}
        </style></head><body>
                <?xml-model href="https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"><tei-tei data-xmlns="http://www.tei-c.org/ns/1.0" data-origname="TEI">
    <tei-teiheader data-origname="teiHeader">
        <tei-filedesc data-origname="fileDesc">
            <tei-titlestmt data-origname="titleStmt">
                <tei-title data-origname="title">CETEICean Demo</tei-title>
                <tei-author data-origname="author">Satoru Nakamura</tei-author>
            </tei-titlestmt>
            <tei-publicationstmt data-origname="publicationStmt">
                <tei-p data-origname="p"></tei-p>
            </tei-publicationstmt>
            <tei-sourcedesc data-origname="sourceDesc">
                <tei-p data-origname="p"></tei-p>
            </tei-sourcedesc>
        </tei-filedesc>
        <tei-encodingdesc data-origname="encodingDesc">
            <tei-tagsdecl data-origname="tagsDecl">
                <tei-rendition id="italic" data-origname="rendition" data-origatts="schemeid" scheme="css" xml:id="italic">font-style: italic;</tei-rendition>
                <tei-rendition data-origname="rendition" data-origatts="schemeselector" scheme="css" selector="title">text-decoration: underline;</tei-rendition>
                <tei-rendition data-origname="rendition" data-origatts="schemeselector" scheme="css" selector="persName">color: green;</tei-rendition>
            </tei-tagsdecl>
        </tei-encodingdesc>
    </tei-teiheader>
    <tei-text data-origname="text">
        <tei-body data-origname="body">
            <tei-div data-origname="div">
                <tei-p data-origname="p">
                    <!--
                    <title xml:id="foo" xml:lang="de">Die Leiden des jungen Werther</title>
                    -->
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                    <tei-lb data-origname="lb"></tei-lb>
                </tei-p>
            </tei-div>
            <tei-div data-origname="div">
                <tei-p data-origname="p">
                    CETEIceanは<tei-ref data-origname="ref" data-origatts="target" target="https://github.com/TEIC/CETEIcean">こちら</tei-ref>を参考にしてください。
                </tei-p>
                <tei-p data-origname="p">
                    こちらは
                    <tei-persname data-origname="persName">人名</tei-persname>のマークアップの例です。
                    はじめてのテキストです。
                </tei-p>
                <tei-p data-origname="p">
                    第二段落のテキストです。
                </tei-p>
                <tei-p data-origname="p">
                    第三段落のテキストです。
                </tei-p>
                <tei-p data-origname="p">
                    第四段落のテキストです。
                </tei-p>
            </tei-div>
            <tei-div data-origname="div">
                <tei-ab data-origname="ab">任意のブロックです。</tei-ab>
            </tei-div>
            <tei-div data-origname="div">
                <tei-ab data-origname="ab">
                    <tei-table data-origname="table" data-origatts="rowscols" rows="4" cols="4">
                        <tei-head data-origname="head">はじめての表です。</tei-head>
                        <tei-row data-origname="row" data-origatts="role" role="label">
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                        </tei-row>
                        <tei-row data-origname="row" data-origatts="role" role="data">
                            <tei-cell data-origname="cell" data-origatts="role" role="label"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                            <tei-cell data-origname="cell" data-origatts="role" role="data"></tei-cell>
                        </tei-row>
                    </tei-table>
                </tei-ab>
            </tei-div>

        </tei-body>
    </tei-text>
</tei-tei>
                <script type="text/javascript">
          var c = new CETEI();
          c.els = ["tei:TEI
"            ,"tei:teiHeader
"            ,"tei:fileDesc
"            ,"tei:titleStmt
"            ,"tei:title
"            ,"tei:author
"            ,"tei:publicationStmt
"            ,"tei:p
"            ,"tei:sourceDesc
"            ,"tei:encodingDesc
"            ,"tei:tagsDecl
"            ,"tei:rendition
"            ,"tei:text
"            ,"tei:body
"            ,"tei:div
"            ,"tei:lb
"            ,"tei:ref
"            ,"tei:persName
"            ,"tei:ab
"            ,"tei:table
"            ,"tei:head
"            ,"tei:row
"            ,"tei:cell
"            ,
];
          c.els.push("egXML");
          c.applyBehaviors();
                </script></body></html>

結果、以下のように表示されます。

まとめ

XSLファイルを変更することで、プレビューの表示内容が変更されます。

大きなファイルでは、XSLTに時間がかかってしまうかもしれませんが、TEI/XMLの編集環境の構築にあたり、参考になりましたら幸いです。

Discussion