🦔

Speedata Publisherのマークアップ

2021/12/24に公開

この記事はTeX & LaTeX Advent Calendar 2021 19日目の記事です。
18日はSpark Hiroさんで
l3keys の紹介でした。

Speedata Publisher is 何

https://github.com/speedata/publisher

The speedata Publisher is a full featured and mature database publishing software. It generates PDF files from XML data and XML layout instructions. It is used to make product catalogs and other documents with high demands on the layout.
Its built-in layout description language allows you to create almost arbitrary layouts, while keeping the job as simple as possible.
Think of it as »XSL-FO on steroids« or »server side InDesign«.

(ギュメの開きと閉じは、ドイツ語ではこれで正しい。)

見る限りTeX要素がありませんね……? :thinking_face:

ご安心ください、src/texディレクトリに.texファイルが!

% publisher.tex
\catcode`\{=1
\catcode`\}=2

\def\pdfoutline{\pdfextension outline }
\directlua{require("publisher.spinit")}

\end

ということで(?)、LuaTeXを処理エンジンとして活用します。組版用のメインはLua言語、サーバやGUI用HTMLなどをGoで補助します。

処理の詳細を追うならTeXアドベントカレンダーっぽいのですが、今回の主題はこのソフトウェアが処理するXMLアプリケーションについてです。

ちなみに、LuaTeX-jaがLuaマクロとして実装されていることからも分かるように、LuaTeXがエンジンレベルで日本語をサポートしているワケでなし。後で見るように、マークアップの方向性を見ても日本語は多分向かないんじゃないかなぁ……。一応examples/languageにsimplified Chineseのサンプルはあるのですが、サポート言語にあるのは次のもの。他は「「Other」で大体大丈夫だよ!」とあるけれども、本当か?

https://doc.speedata.de/publisher/en/commandreference/options/index.html#ref_info_7

TUG Boat 2020年のVol.41 No2に本記事の内容よりもまとまったものがあります。
https://tug.org/TUGboat/tb41-2/tb128gundlach-speedata.pdf

基本

別リポジトリにexamplesがあります。

https://github.com/speedata/examples

次の2ファイルがどの例でも登場しています。

  • layout.xml
  • data.xml

ところで紹介文にこんな1文がありました。

Think of it as »XSL-FO on steroids« or »server side InDesign«.

XSL-FOは「XSLの語彙の方」です。「サーバサイドInDesign」の意味するところって人によって違うんじゃないかとは思いますが、見ていきましょう。

マニュアルは次のところにあります。

https://doc.speedata.de/publisher/en/index.html

examples/introduction/helloworld

https://github.com/speedata/examples/tree/master/introduction/helloworld

マニュアルもhelloworldから始めているんですが、examplesのものと構成が異なります。
layout.xml。

<Layout xmlns="urn:speedata.de:2009/publisher/en">

  <Options crop="3mm" />
  <Trace grid="no" gridallocation="no" objects="no"/>


  <Record element="root">
    <ProcessNode select="elt"/>
  </Record>

  <Record element="elt">
    <PlaceObject>
      <Textblock>
        <Paragraph>
          <Value select="@greeting" />
        </Paragraph>
      </Textblock>
    </PlaceObject>
  </Record>
</Layout>

名前空間はurn:speedata.de:2009/publisher/en、Option@cropはまあ雰囲気で分かりますね。
Trace要素のオプションに気になるattributeがありますね。まあハロワでは使わないので全部noと書いてあります。一度ここでdata.xmlを見てみましょう。

data.xmlは次の通り。

<root>
  <elt greeting="Hello world" />
</root>

Recordはどうやらdata.xmlの要素を処理する単位のようです。root要素を見つけたらその文脈でelt要素を処理して最終的にgreeting attributeを取得して、PlaceObjectによって紙面に置かれるオブジェクトを用意、種類はTextblockのParagraphで……ということが何となく掴めるかと思います。
大体XSLTでFOに変換するのと同じですね。

このままだと「on steroids」がどういうことなのか分かりません。TUGBoatの記事を軽く流して見ましょう。

Grid

Speedata Publisherのウリの1つがGrid typesettingです。

<SetGrid height="12pt" nx="10"/>
<Trace grid="yes"/>
<Pageformat width="8cm" height="4cm"/>
<Record element="data">
  <PlaceObject column="3" row="2">
    <Textblock>
      <Paragraph>
        <Value>Hello world!</Value>
      </Paragraph>
    </Textblock>
  </PlaceObject>
</Record>

SetGridで基本的なグリッドの単位を設定しています。heightが行進行方向の単位、nxがページの本文領域をいくつに等分するか、となるようです。

この Hello World! は2行目3列目に配置されることになります。ページはこのGridによるrowの連続によって構成されるため、前のコンテンツが配置が完了されたrowの次の行を始点とすることになる、はず。Grid指定によって配置されたコンテンツは基本的には他のコンテンツと被らないように配置されるようです。

ほか制御構造

Valueが先のサンプルでは出てきましたが、他にもSwitchによる分岐などをサポートします。
どっちかというとXSL-FOとXSLTを再統合したような存在がLayout.xmlっぽいんですよね。XSL誕生に際してのSGMLにおけるDSSSLの反省の1つが記法、構造がSGMLでないことだったので、その辺りが丁度良い塩梅の人もいるよね、という感じ。

Data

Layoutについて見てきましたが、完全に無視もできないのがData。Layout.xmlでelementと@attributeのようにしてアクセスできるのであまり構造を選ばないといえばそうなのですが、変換とフォーマットがXSLTとXSL-FOほど分離させていない分、Dataの方も書き方に影響が出ます。基本的なSchemaはSpeedata Publisherが用意したものが使えますが、自力でバリデーションするなどであればこの辺りは無視できそう。

https://github.com/speedata/examples/blob/master/magazine/data.xml

 <text>
        <par initial="T">he city stretches along the northern bank of the river Tejo as it flows
            into the Atlantic Ocean. As the terrain rises north away from the water, steep streets
            and stairways form the old tangled districts or give way to green parks in the western
		suburbs.</par>
...</text>

XML構造は最終的には書き手と読み手で了解が取れれば良いのですが、このサンプルでは「T」と「he city ...」が分離しています。1単語がattributeとテキストに分かれちゃうのは何だかなと思うところ。

<par title="Tram 28">Instead of paying for a ride ...</par>

headingのtitleがattributeになっているのはScriptがメジャーな言語の傲りという怨嗟があります、個人的に。XMLはelement、attribute、そしてテキストで構成される訳ですが、基本的にattributeに対するattributeというのは設計としてあまり良い感じがしません(個人の感想です)。つまり、「このタイトルに対しルビが振りたい」のような構造はtitleがattributeだとちょっと難しいということです。

Image shape

https://github.com/speedata/examples/tree/master/imageshape

Speedata Publisherのサンプルで一際目をひくのがImage Shapeのサンプル。花瓶の形状にテキストがwrapされています。

どうやって実現しているのかとvase.xmlをみると、愚直に花瓶の形状をなぞるxとyの位置情報が連続しています。

ただし、この形状を示すXMLはSpeedataが提供しているアプリで自動生成できます。

https://github.com/speedata/imageshaper

次の日

完全に途中で力尽きていました……。

20日はhilsshさんです。
LaTeXで宛名ラベルシールの差し込み印刷をする

Discussion