はじめに
イスラーム圏の歴史テキストを扱う OpenITI(Open Islamicate Texts Initiative) プロジェクトでは、TEI/XMLの代わりに mARkdown という軽量記法でテキストをタグ付けできます。
TEI/XMLは構造化の国際規格として強力ですが、特にアラビア語のような右から左に書く言語(RTL)では、XMLタグとの混在でエディタ上の表示が乱れるという問題があります。mARkdownはこの課題を解決する記法です。
本記事では、mARkdownで書かれたテキストを TEI XMLに自動変換 するPythonツール oitei を実際に動かしてみます。
oiteiとは
- OpenITI mARkdown → TEI XML の変換ライブラリ(Python)
- OpenITI TEI Schema に準拠したXMLを出力
- PyPIで公開されており
pip installで導入可能 - 依存ライブラリ:
oimdp(mARkdownパーサー)、lxml
https://github.com/OpenITI/oitei
インストール
pip install oitei
Python 3.8以上が必要です。oimdp(OpenITI mARkdown Parser)と lxml が依存関係として自動インストールされます。
OpenITI mARkdownの記法
mARkdownファイルは以下の3部構成です。
- マジックバリュー (1行目):
######OpenITI# - メタデータ :
#META#で始まる行 - 本文 :
#META#Header#End#の後に記述
主なタグ
| 記法 | 意味 |
|---|---|
| `### | ` |
| `### | |
### $ | 伝記エントリ |
# | 段落の開始 |
@P02 名前 | 人物名(後続2語を含む) |
@T11 地名 | 地名(後続1語を含む) |
@YB732 | 誕生年(ヒジュラ暦732年) |
@YD808 | 没年(ヒジュラ暦808年) |
%~% | 詩行(hemistich)の区切り |
固有表現タグ(@P, @T 等)の後ろの 2桁の数字 は、1桁目がエンティティ番号、2桁目が「後続する何単語を名前に含むか」を指定します。例えば @P02 Ibn Khaldun は「後続2語(Ibn Khaldun)を人名として含む」という意味です。
サンプルファイルの作成
以下の内容で sample_markdown.md を作成します。
######OpenITI#
#META# Title: Sample Text for OpenITI mARkdown Demo
#META# Author: Demo Author
#META# Language: Arabic
#META#Header#End#
### | Chapter One: Introduction
# This is the first paragraph of the sample text. It demonstrates how OpenITI mARkdown works for tagging biographical and geographical information.
### $ Ibn Khaldun
# @P02 Ibn Khaldun was born in @T11 Tunis in @YB732 and died in @YD808 in @T11 Cairo . He wrote the Muqaddimah.
### || Section on Geography
# The city of @T11 Damascus was an important center of learning. Many scholars traveled from @T11 Baghdad to @T11 Damascus .
### $ Abu Bakr al-Razi
# @P03 Abu Bakr al-Razi was a renowned physician. He was born in @T11 Rayy and later moved to @T11 Baghdad . He died in @YD313 .
### | Chapter Two: Poetry
# The following is a sample verse:
# %~% The morning light shines on the desert sand %~% And caravan bells echo through the land
# This concludes our sample text.
変換の実行
import oitei
md = open("sample_markdown.md", "r").read()
tei_string = oitei.convert(md).tostring()
with open("sample_tei.xml", "w") as writer:
writer.write(tei_string)
たった4行で変換が完了します。
変換結果
生成された TEI XML は以下の通りです。
<?xml version='1.0' encoding='UTF-8'?>
<TEI xmlns="http://www.tei-c.org/ns/1.0"
xmlns:xi="http://www.w3.org/2001/XInclude">
<teiHeader>
<fileDesc>
<titleStmt>
<title/>
<author/>
</titleStmt>
<publicationStmt>
<publisher>Open Islamicate Texts Initiative (OpenITI)</publisher>
<availability>
<p>Creative Commons Attribution Non Commercial Share Alike
4.0 International</p>
</availability>
</publicationStmt>
<sourceDesc>
<bibl/>
</sourceDesc>
</fileDesc>
<profileDesc>
<calendarDesc>
<calendar xml:id="ah">
<p>Anno Hegirae</p>
</calendar>
</calendarDesc>
</profileDesc>
<xenoData xml:space="preserve">
Title: Sample Text for OpenITI mARkdown Demo
Author: Demo Author
Language: Arabic
</xenoData>
</teiHeader>
<text>
<body>
<div>
<head>Chapter One: Introduction</head>
<p>
<lb/>This is the first paragraph of the sample text. ...
</p>
<div type="biography" subtype="man">
<head>Ibn Khaldun</head>
<p>
<lb/>
<persName>Ibn Khaldun </persName> was born in
T<placeName>unis </placeName> in
<date type="birth" calendar="#ah" when-custom="732"/>
and died in
<date type="death" calendar="#ah" when-custom="808"/>
in C<placeName>airo </placeName> .
He wrote the Muqaddimah.
</p>
</div>
<!-- ... 以下略 ... -->
</div>
</body>
</text>
</TEI>
変換のポイント
mARkdownの各タグが適切なTEI要素に変換されています。
| mARkdown | TEI XML |
|---|---|
| `### | ` 章見出し |
### $ 伝記 | <div type="biography" subtype="man"> |
@P02 Ibn Khaldun | <persName>Ibn Khaldun</persName> |
@T11 Tunis | <placeName>unis</placeName> |
@YB732 | <date type="birth" calendar="#ah" when-custom="732"/> |
@YD808 | <date type="death" calendar="#ah" when-custom="808"/> |
%~% 詩行区切り | <caesura/> |
#META# メタデータ | <xenoData> |
ヒジュラ暦の年号には自動的に calendar="#ah" が付与され、暦体系が明示されます。
日本語テキストへの適用
oiteiはイスラーム圏のテキスト向けに設計されていますが、日本語テキストにも適用できるか試してみます。
注意点:スペース区切りの問題
mARkdownの固有表現タグ(@P, @T 等)は、スペース区切りで「後続N語」 を名前として取り込む仕組みです。日本語はスペースで単語が区切られないため、工夫が必要です。
@P02 Ibn Khaldun→ 後続2語 = “Ibn Khaldun” ✅(英語・アラビア語)@P02 源 頼朝→ 後続2語 = “源” “頼朝” … だが<persName>源 頼朝</persName>にはなるものの不自然
対処法 : 日本語の名前はスペースなしで1語にまとめ、@P01(後続1語)を使います。
@P01 源頼朝 → <persName>源頼朝</persName> ✅
@T01 鎌倉 → <placeName>鎌倉</placeName> ✅
日本語サンプル
架空の人物・地名を使った単純な例で試します。
######OpenITI#
#META# Title: 日本語テキストサンプル
#META# Author: デモ著者
#META# Language: Japanese
#META#Header#End#
### | 第一章 人物紹介
# @P01 太郎 は @T01 東京 に住んでいる。
# @P01 花子 は @T01 京都 で生まれ、現在は @T01 大阪 に住んでいる。
### | 第二章 詩
# 以下はサンプルの詩である。
# %~% 春の風が街を吹き抜け %~% 桜の花びらが舞い散る
# これでサンプルテキストは終わりである。
日本語の変換結果
<div>
<head>第一章 人物紹介</head>
<p>
<lb/>
<persName>太郎 </persName> は <placeName>東京 </placeName> に住んでいる。
</p>
<p>
<lb/>
<persName>花子 </persName> は <placeName>京都 </placeName> で生まれ、
現在は <placeName>大阪 </placeName> に住んでいる。
</p>
</div>
<div>
<head>第二章 詩</head>
<p>
<lb/>以下はサンプルの詩である。
</p>
<lg>
<l>
<caesura/> 春の風が街を吹き抜け
<caesura/> 桜の花びらが舞い散る
</l>
</lg>
</div>
人物名・地名・詩行がTEI要素に変換されており、このXMLも tei_all.rng でバリデーションに通ることを確認しました。
!
oiteiはイスラーム圏テキスト向けのツールであるため、以下の点に注意が必要です。
teiHeaderにcalendar="#ah"(ヒジュラ暦)が固定で出力されるpublisherが “Open Islamicate Texts Initiative” 固定- 日本語で使う場合、固有表現タグの前後にスペースが必要
本格的に日本語テキストのTEI化を行う場合は、oiteiの出力をベースにヘッダ等を修正するか、別のツールの利用を検討してください。
TEIスキーマによるバリデーション
生成されたXMLがTEI規格に適合しているか検証します。
# TEI Allスキーマをダウンロード
curl -sL -o tei_all.rng \
https://tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng
# xmllintでバリデーション
xmllint --relaxng tei_all.rng sample_tei.xml
sample_tei.xml validates
TEI公式のRelaxNGスキーマ(tei_all.rng)で バリデーションに通る ことを確認しました。
!
OpenITI独自のカスタムスキーマ(tei_openiti.rng)でも検証を試みましたが、434KBと大きいスキーマのコンパイルに非常に時間がかかり、ローカル環境では完了しませんでした。tei_all は tei_openiti のスーパーセットであるため、tei_all で通れば基本的な適合性は確認できます。
まとめ
- oitei を使えば、OpenITI mARkdown → TEI XML の変換がPython数行で可能
- XMLタグの手書きが不要で、特にRTL言語を扱う際のエディタ上の混乱を回避できる
- 生成されるXMLはTEI標準スキーマのバリデーションに通る
<persName>,<placeName>,<date>等の固有表現タグが自動付与される
軽量な記法で書いて、必要な時にTEI XMLに変換する。このワークフローは、特にイスラーム圏の歴史テキストを扱う研究者にとって有用なアプローチです。