0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JATS XML文書をHTMLに変換してVivliostyleでページ組版する

Last updated at Posted at 2025-07-08

この記事の「サンプル」で扱ったJATS XML文書サンプルを、HTMLに変換してVivliostyleでページ組版してみます。(長い記事です…)

JATS XMLやDITA1をページ組版というと、XSLT2で変換してXSL-FO3やTeXやCSSで組んで…という解説を見かけますが、ここはJavaScriptでDOMを変換してCSSで組みます。つまりフロントエンドの技術でページ組版しようというわけです。

変換はごく単純で、元のJATS XMLの構造を大胆には変えないようにします。やってみると分かることがあって、この気付きが目的です。というわけで、泥臭く進めていきます。

「JATSが分かる…」の薄い本を作ってみましょう!(薄くないw)

手順

前記の記事で、サンプルをダウンロードして展開したところから始めます。Visual Studio Codeやvscode-xmlは、まだ手を付けてなくて大丈夫、後の個々の画像にサイズを設定してみようで使います。

JATS XML文書をHTMLに変換

次のURLのページでJATS XML文書を読み込んでHTMLに変換して、拡張子だけ.htmlに変えたファイルを作り、元のJATS XML文書と同じところに置きます。

この2025_112.xmlを変換して2025_112.htmlを作り…

JATSBOOK_XML
├── 2025_112
│   ├── 2025_112.txt
│   ├── 2025_112.xml
│   └── Graphics
│ …

同じフォルダーに置きます:

JATSBOOK_XML
├── 2025_112
│   ├── 2025_112.html # 変換して追加
│   ├── 2025_112.txt
│   ├── 2025_112.xml
│   └── Graphics
│ …

これをすべてのJATS XMLで繰り返します。

(何度もやるようになったら面倒ですよね)

そうなったら一括変換の仕組みを用意するでしょう(この項、修正しました 2025-07-09)。

例えば、次をダウンロードして:

package.jsonを用意して:

package.json
{
  "type": "module",
  "dependencies": {
    "xmldom": "^0.6.0"
  }
}

後のVivliostyleを実行するのとは別のJATSBOOK_XMLフォルダー/ディレクトリを用意して、こんな構造にして:

JATSBOOK_XML
├── 2025_112
├── 2025_122
├── 2025_14
├── …
├── index.js
├── j2hN.js
├── lib
│   ├── convert.js
│   └── sed.js
└── package.json

Macなら、次を実行すると楽……なはずです。ご笑覧ください

find ./2025*  -type f -name "*.xml" | while read -r f; do
  node index.js "$f" > "${f%.xml}.html"
done

変換後にVivliostyleで組版する用のフォルダー/ディレクトリにコピーします。

ちなみに、この変換処理はみなさんのブラウザーで、みなさんのパソコンなどで実行されます。変換プログラムを置いてあるサーバーでではなく、「変換処理がサーバーに集中して重い」みたいな事態にはなりにくいと思います。

1つのHTMLファイルを複製

HTMLファイルを1つ複製します。奥付用です。

後の構成ファイルに合わせて2025_i.htmlを複製することにします…

JATSBOOK_XML
├── …
└── 2025_i
    ├── 2025_i.html # これを複製
    ├── 2025_i.txt
    ├── 2025_i.xml
    └── Graphics

こうなります。構成ファイルに合わせて2025_i copy.htmlという名前にしてください。

JATSBOOK_XML
├── …
└── 2025_i
    ├── 2025_i copy.html # 複製
    ├── 2025_i.html
    ├── 2025_i.txt
    ├── 2025_i.xml
    └── Graphics

Vivliostyleをインストール

まだインストールしてなければ、次のページの手順でVivliostyleをインストールします:

構成ファイルvivliostyle.config.jsを用意

Vivliostyleの構成ファイルvivliostyle.config.jsを用意します。これはVivliostyleに、どのファイルをどのように処理するか指示するものです。

vivliostyle.config.jsという名前のファイルを用意して、中身を次のコードとして、JATSBOOK_XMLフォルダー直下に置きます。Qiitaではカーソルをコード領域に持ってくると右上に現れるコピーボタンを押してコピーできます。

vivliostyle.config.js
module.exports = {
  title: 'JATSがわかる 学術情報XML作成の実際',
  language: 'ja',
  theme: ['https://yamahige.github.io/study/jats2html/vivliostyle/body.css'],
  copyAsset: {
    includes: [
    ]
  },
  author: '学術情報XML推進協議会',
  entry: [
    // {
    //   /* 目次 */
    //   path: "./cover.html",
    //   theme: ['./body.css', './cover.css'],
    // },
    {
      path: "./2025_i/2025_i.html",
      theme: ['https://yamahige.github.io/study/jats2html/vivliostyle/jats_i.css'],
    },
    {
      // path: 'toc-template.html',
      theme: ['https://yamahige.github.io/study/jats2html/vivliostyle/toc.css'], // ページ番号を付けるなど
      output: 'toc.html',
      rel: 'contents',
      pageCounterReset: 1,
    },
    {
      path: "./2025_2/2025_2.html",
      theme: [
        'https://yamahige.github.io/study/jats2html/vivliostyle//body.css',
        'https://yamahige.github.io/study/jats2html/vivliostyle/page-reset.css' // ページ番号をリセット
      ],
    },
    "./2025_14/2025_14.html",
    "./2025_38/2025_38.html",
    "./2025_52/2025_52.html",
    "./2025_65/2025_65.html",
    "./2025_78/2025_78.html",
    "./2025_98/2025_98.html",
    "./2025_112/2025_112.html",
    "./2025_122/2025_122.html",
    {
      path: "./2025_i/2025_i copy.html",
      theme: ['https://yamahige.github.io/study/jats2html/vivliostyle/okuduke.css'],
    },
  ],
  output: [
    'jatsbook.pdf',
  ],
  toc: {
    title: '目次',
    htmlPath: 'toc.html',
    sectionDepth: 2,
  },
  workspaceDir: './.vivliostyle',
};

ファイルの構成はこうなります:

JATSBOOK_XML
├── 2025_112
├── 2025_122
├── 2025_14
├── 2025_2
│── 2025_38
├── 2025_52
├── 2025_65
├── 2025_78
├── 2025_98
├── 2025_i
└── vivliostyle.config.js # 追加した構成ファイル

プレビュー

JATSBOOK_XMLフォルダーで、次のコマンドを実行してプレビューします:

$ vivliostyle preview
(こんなふうに表示されれば成功です)

success.png

© XML Scholarly Publishing Association, 2025

(画面左上のボタンから目次が展開されるはずです)

vivliostyle.png

© XML Scholarly Publishing Association, 2025

次のコマンドでjatsbook.pdfという名前のPDFファイルが出力されます:

$ vivliostyle build
(こんなふうになってれば成功です)

jatsbook.png

© XML Scholarly Publishing Association, 2025

考察

変換といっても、ほとんどの要素はそのままスルーしてます。変換結果を左右見比べると分かるでしょう。article-metaといった要素もそのままVivliostyleに入力してます。

以降で、変換について主なポイントを説明します。

  といった文字実体参照と外部実体

JavaScriptのパーサーには、JATS XML文書をHTML文書text/htmlとして読み込ませてます。なぜかというと…

  といった文字実体参照は、HTMLでは宣言せずに使えます。一方、XMLでは宣言が必要です(実体参照といいます)。で、それはJATSのDTDをたどるとisopub.entというファイルで、こんなふうに宣言されてます。

isopub.ent
<!ENTITY emsp             "&#x02003;" ><!--=em space -->

問題は、JavaScriptのパーサーが、DTDをたどって外部実体を読みに行ってくれないことです。ブラウザーでも、サンプルのJATS XML文書を表示しようとすると次のエラーになります:

This page contains the following errors:
error on line 63 at column 26: Entity 'emsp' not defined
error on line 74 at column 180: Entity 'ldquo' not defined
error on line 79 at column 51: Entity 'nbsp' not defined
error on line 92 at column 57: Entity 'nbsp' not defined
error on line 104 at column 26: Entity 'emsp' not defined

いやいや、「not defined」って、DTD指定してるのに……困りました。

HTML文書として読み込ませれば、この問題は起きません。このために変換後のファイルの拡張子を.htmlにしてます。これで大丈夫なのか……

JATS XMLの名前空間

「後方互換のために、JATS自身には名前空間の記法を使わなくてよい」ことになってるようです。J-STAGEとはJATSのバージョンが異なりますが、次のURLに説明があります。

実際、サンプルのJATS XML文書では、XLinkのxlink:hrefといった導入要素を除いて、JATS XML自身は名前空間を宣言してません。

一方、HTMLも名前空間を使わなくてよいことになってます。そこで、JATS XML文書をHTML文書として読めてしまう……ようです。

HTMLのtitlebodyと事前の文字列変換

JATSにもbodytitleという要素がありますが、HTMLのとは役割が異なります。ブラウザーのDOMParserや、JSDOMが読み込む時点で特別扱いされてしまうので、パーサーで読み込む前に文字列変換で名前を変えます。

前記の変換プログラムでは次のように文字列変換してます:

  • title -> jats-title
  • body -> jats-body

title

JATSのtitleはHTMLのh1h6相当、あるいは図表のcaptionの中でも使われてます。

こんな感じ

<sec>
    <label>(1)</label>
    <title>J-STAGE…</title>
    <p></p>
    <!-- … -->
</sec>

あるいはこう

<fig>
    <label>図7.2</label>
    <caption>
        <title>画面構成</title>
    </caption>
    <graphic xlink:href="gui.jpg"/>
</fig>

一方、HTMLのtitleは文書中に唯一で特別です。例えば、テキストのみ含めることができて、supなどを含められません。

また、HTMLのtitleは空要素ではありませんが、JATS XML文書には空の<title/>があります。これも事前に文字列変換します。

body

HTMLのbody要素は特別で、パーサーで読み込むとhtml > bodyの配下にhead以外の要素がぶら下がるように構造変換されてしまいます。

JATSのlabel

HTML + CSSなら疑似要素で自動生成するようなテキストが、JATSではlabel要素になっています。前記の例もそうなってます。

箇条書きもこんなふうで、「●」が生成済です:

<list>
    <list-item>
        <label></label>
        <p>title要素とbody要素は特別です。</p>
    </list-item>
    <!-- …… -->
</list>

JATSの画像graphic

JATSの画像はgraphic要素ですが、このままブラウザーなどに渡しても画像は表示されません。変換プログラムでは、パーサーで読み込んだ後、img要素に置き換えてます。

こんなふうに記述されてます:

<graphic xlink:href="photo.jpg"/>

そこで、次のようなCSSが有効ならよいのですが、url()関数内にattr()関数を書けないようで、ダメです。

graphic {
    content: url(attr(xlink\:href));
}
/* または */
graphic::after {
    content: url(attr(xlink\:href));
}

なお、xml:lang属性など名前空間プレフィックス付きの属性をCSSの属性セレクターに使うときは、abstract[xml\:lang="ja"]などと:\でエスケープするそうです。

インラインボックスのまとまり

JATSでは、ブロックボックスにまとめたくなるようなインラインボックスが、特にまとまりなく並んでいます。

セクション見出し

セクション番号と見出しが次のような構造になってます:

<sec>
    <label>第1章</label>
    <title>JATSの歴史</title>
    <p>昔々…</p>
    <!-- … -->
</sec>

次のように表示したいのですが、labeltitle(jats-titleに変換されます)がpと同じレベルで並んでいて、まとまってません。

第1章 JATSの歴史
昔々…

このままだと、次の記事の「見出しをrun-inにする」手法を使うことになりますが、扱いにくいので、パーサーで読み込んだ後、jats-title-wrap要素でくくってます。

<sec>
    <jats-title-wrap>
        <label>第1章</label>
        <jats-title>JATSの歴史</jats-title>
    </jats-title-wrap>
    <p>昔々…</p>
    <!-- … -->
</sec>

図表のキャプションも同様です。「図のキャプションは図の下、表は上」にしたくても、labeltitlegraphicなどと3つに分かれてると、display: flex; flex-direction: column-reverse;などで制御しようとすると困っちゃいますよね。

<fig>
    <label>図7.2</label>
    <caption>
        <title>画面構成</title>
    </caption>
    <graphic xlink:href="gui.jpg"/>
</fig>

目次生成

Vivliostyleに目次を自動生成してもらうために、title要素(というかjats-title-wrap要素)のままでは目次ができません。h1h2h3などの要素を想定しているからです。そこで、トップレベルだけjats-title-wraph2に置き換えてます。

奥付

奥付を生成するために、どれかのHTMLファイルを複製します。前記の手順では2025_i copy.htmlとしました。中身は全く同じでファイル名が異なるようにします4。どのファイルでもよいです……つまり、どのファイルにも(章だけでなく)書籍の情報が入ってます。論文でいえば掲載誌の情報です。今回は表紙を作ってませんが、表紙も同じ方法で作れます。

もちろん、DOMを変換して奥付用ファイルを作るワークフローもありでしょう。

画像graphicのサイズ

さて、入手できるJATS XML文書では、画像にサイズがありません。

そこで、Vivliostyleに渡すCSSでは、graphicから変換したimgについて一律に、次のように設定してます:

img {
    max-inline-size: 90%;
    max-block-size: 60vh;
    margin-inline: auto;
}

個々の画像にサイズを設定してみよう

これはページ組版なので、サイズや配置を調整したいですよね。

やってみましょう!

まず、できれば次の記事のように、Visual Studio Code (以下、VSCode)とXML拡張機能(vscode-xml)を用意して、DTDを読み込んでバリデーションできるようにしておきます。できなくてもよいです、テキストエディターでもOKです。

JATS XML文書、例えば./2025_2/2025_2.xml(2025_2.htmlではなく)をVSCodeで開いて、graphic要素を、style属性付きのstyled-content要素で囲みます。

<graphic xlink:href="2025_2_f1.jpg"/>

を、このように編集します。

<styled-content style="inline-size: 50%; float: outside;">
    <graphic xlink:href="2025_2_f1.jpg"/>
</styled-content>

画像の幅をページ幅の50%にして外側寄せにするという設定です。

float: outside;はVivliostyleの新しい機能です

https://qiita.com/u1f992/items/8aa60c0cce645a5929ae

編集前は横幅いっぱいだった画像が、半分の幅で外側寄せになってれば成功です。

(編集前はこうだったものが)

graphic-before.png

© XML Scholarly Publishing Association, 2025

(編集後に、こうなっていれば成功です)

graphic-after.png

© XML Scholarly Publishing Association, 2025

このようにして、ソースのXML文書で、画像のサイズや配置を調整できます。

styled-content要素とstyle属性

ここで、編集後でも妥当なXML文書であることに注目してください。VSCodeとvscode-xmlを使って編集すると分かります。バリデーションが成功します。

試しに、graphic要素にstyle属性を設定するとエラーになり、ちゃんとバリデートされてることが分かります。styleのところに赤い波線が表示されるのを確認できます。

<graphic xlink:href="2025_2_f1.jpg" style="inline-size: 50%; float: outside;"/>

style-error.png

styled-content要素にstyle属性(XMLでは@styleと表現したりします)を使うのは、JATSが用意している方法です。

ただし、J-STAGEの「XMLフォーマットガイドライン」などにはstyled-contentの記述が見当たらず、使ってよいものかどうか分かりません……

この他に、named-content要素があって、こちらはHTMLのclass属性の用法に似ています。ただし@classはなくて、@content-type@specific-useで識別します。

JATSの画像のサイズ設定

JATSで画像にサイズが設定されていなくてもよい事情は、実際に公開されている論文をJ-STAGEで見ると想像できます。どの画像も固定幅の100%で表示するように設定されていて、クリックすると拡大表示されるようになってます。

次のようにして実物を確認できます:

J-STAGEトップページで、「検索条件の詳細設定」から、まず「指定検索」に何か入力します(ここに何か入れないと検索してくれません)。そして「記事属性」で「本文(HTML形式)」をチェックします。見たところ、HTML形式が公開されてるのは医薬系に多いです。例えば「論文タイトル」に「COVID-19」などと入力します。検索結果一覧の画面で、「認証」の「フリー」や「オープンアクセス」をチェックすると無料・会員登録不要で読める論文に絞り込めます5

j-stage-search.png

あるいは「情報管理」という雑誌です。休刊してるのですが、この論文は、すべてフリー& HTML形式で見られるんじゃないでしょうか

https://www.jstage.jst.go.jp/browse/johokanri/-char/ja

いずれも論文一覧の画面で、各論文の「HTML形式で全画面表示」をクリックするか、タイトルをクリックして開いたページの右上の「本文(HTML形式)」をクリックすると、JATS XMLから変換して作ったHTML形式で論文を閲覧できます。

細かいところはやってません

  • 著者は奥付に一覧したい。そういった奥付生成はDOMで可能でしょう
  • 図のキャプションは下、表キャプションは上にしたい
  • 目次の最後の項目の見出しが「序文…」なのはおかしい。そもそも奥付は目次に載せないでしょう
  • いまさらですが、XML文書の空白文字や改行は要注意で、整形(prettify)は危険です。何がどのように変換されるのか、整形した方が対比しやすいので、変換プログラムは整形して見せています。実際のワークフローでは整形しないデータを使うべきです。(2025-07-27 追記)

以上です、お疲れ様でした。
CSSの中身は、後でゆっくりご笑覧ください。ここで紹介した手法を使ってます

  1. Darwin Information Typing Architecture https://ja.wikipedia.org/wiki/Darwin_Information_Typing_Architecture

  2. https://ja.wikipedia.org/wiki/XSL_Transformations

  3. https://ja.wikipedia.org/wiki/XSL_Formatting_Objects

  4. 同じファイルが複数個entryしてるとVivliostyleでエラーになります。

  5. 「COVID-19」の結果はフリーやオープンアクセスのものだけですね……という点が、JATS XMLについては重要だったりします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?