ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English

TEI XMLのスタンドオフ注釈をインライン化する際の落とし穴とDOM操作による解決

デジタル延喜式は、延長5年(927年)に完成した律令の施行細則集『延喜式』を TEI (Text Encoding Initiative) XML で符号化し、Web上で閲覧・検索できるようにするプロジェクトです。国立歴史民俗博物館を中心に、校訂文・現代語訳・英訳を TEI でマークアップし、Nuxt.js(Vue.js)ベースのビューアで公開しています。 この開発の中で、TEI XML のスタンドオフ(standoff)注釈をインライン注釈に変換する処理において、XML の文書構造が崩壊するバグに遭遇しました。本記事では、その原因と DOM 操作ベースの解決策を記録します。 スタンドオフ注釈とは TEI XML では、テキスト中の校異(variant readings)を記録する方法として、スタンドオフ方式がよく使われます。デジタル延喜式では、複数の写本間のテキストの異同を <app> 要素で記録しており、テキスト中に <anchor> 要素で範囲を示し、対応する <app> 要素を別の場所に置く構造になっています。 <p> 前テキスト <anchor xml:id="app001"/> 校異対象のテキスト <anchor xml:id="app001e"/> 後テキスト </p> <!-- 別の場所に校異情報 --> <app from="#app001" to="#app001e"> <lem>校異対象のテキスト</lem> <rdg wit="#写本A">異なるテキスト</rdg> </app> この方式は、XML のネスト制約を回避できる利点があります。校異の範囲が要素境界をまたぐ場合(overlapping hierarchy)でも、anchor はどこにでも置けるためです。 インライン化の理由 XML ツリーと UI コンポーネントツリーの対応 デジタル延喜式のビューアは Vue.js で構築しています。Vue.js や React のようなコンポーネントベースのフレームワークでは、UI はツリー構造で記述されます。TEI XML もツリー構造なので、XML の各要素を UI コンポーネントに 1:1 でマッピングする再帰レンダリングが自然なアプローチになります。 <!-- TEI.vue: XML要素を再帰的にコンポーネントにマッピング --> <template> <component v-for="child in element.children" :is="getComponent(child.tagName)" :element="child" /> </template> この設計では、<app> 要素がテキスト中にインラインで存在すれば、ツリーの走査だけでレンダリングできます。 ...

TEI Publisher:TEI XMLデジタルエディション出版プラットフォーム

TEI Publisher:TEI XMLデジタルエディション出版プラットフォーム

はじめに TEI(Text Encoding Initiative)は、人文学のテキストをデジタル化する際の国際標準として広く採用されている XML マークアップ言語です。古典籍、書簡、碑文、辞書など、さまざまなテキスト資料を構造化された形式で記述できます。 しかし、TEI XML で符号化されたテキストを、読みやすい形で Web 上に公開するには、相応の技術的知識が必要です。本記事では、TEI XML のデジタルエディションを簡単に出版できるプラットフォーム TEI Publisher を紹介します。 TEI Publisher とは TEI Publisher は、eXist-db XML データベース上で動作するデジタルエディション出版プラットフォームです。TEI XML で符号化されたテキストを、カスタマイズ可能な美しい Web ページとして公開できます。 e-editiones コミュニティによって開発・メンテナンスされており、オープンソースとして公開されています。学術的なテキスト出版のためのワンストップソリューションを目指しています。 主な機能 カスタマイズ可能な表示 ODD(One Document Does it all)仕様に基づく処理モデルにより、TEI XML の各要素をどのように表示するかを柔軟に定義できます。XSLT を直接書く必要はなく、GUI ベースのエディタで表示ルールを設定できます。 ファクシミリ表示 原本のデジタル画像(ファクシミリ)とテキストの翻刻を並べて表示できます。IIIF Image API にも対応しており、高解像度画像のズーム表示が可能です。テキストの特定箇所と画像の対応する領域をリンクさせることもできます。 全文検索 eXist-db の全文検索エンジンにより、テキスト全体を高速に検索できます。Lucene ベースのインデックスにより、大量のテキストでも即座に結果を返します。ファセット検索やハイライト表示にも対応しています。 REST API テキストデータやメタデータにプログラムからアクセスするための REST API が提供されています。外部のアプリケーションやツールとの連携が容易で、データの再利用を促進します。 レスポンシブデザイン 生成される Web ページはレスポンシブデザインに対応しており、PC、タブレット、スマートフォンなど、さまざまなデバイスで適切に表示されます。 多言語・多文字体系対応 ラテン文字はもちろん、アラビア文字、漢字、デーヴァナーガリーなど、多様な文字体系に対応しています。右から左に書く言語(RTL)もサポートしています。 導入方法 TEI Publisher は eXist-db 上で動作します。Docker を使った導入が推奨されています。 docker run -p 8080:8080 existdb/teipublisher:latest 起動後、ブラウザで http://localhost:8080/exist/apps/tei-publisher/ にアクセスすると、TEI Publisher のインターフェースが表示されます。サンプルのテキストが含まれているため、すぐに機能を試すことができます。 ...

DOCX → TEI/XML 変換ツールに CETEIcean を使ったプレビュー機能を追加した

DOCX → TEI/XML 変換ツールに CETEIcean を使ったプレビュー機能を追加した

はじめに 以前の記事で、DOCX → TEI/XML 変換ツールを紹介しました。TEI Garage API を使ってブラウザだけで Word 文書を TEI/XML に変換できるツールです。 公開後、利用者の方から「変換されたタグが想定どおりに機能するかを視覚的に確認したい」というフィードバックをいただきました。XML のシンタックスハイライト表示だけでは、見出し・注釈・リスト・テーブルなどが実際にどのようにレンダリングされるか確認が難しいためです。 そこで、CETEIcean を使った TEI プレビュー機能を追加しました。 デモサイト: https://tei-converter.pages.dev/ CETEIcean とは CETEIcean は、TEI Consortium が開発している JavaScript ライブラリです。TEI/XML を HTML5 カスタム要素(Custom Elements) に変換し、ブラウザ上でそのまま表示できます。 通常、TEI/XML をブラウザで表示するには XSLT で HTML に変換する必要がありますが、CETEIcean は Web Components の仕組みを利用して、TEI の要素名をそのままカスタム要素として登録します。例えば <p> は <tei-p> に、<head> は <tei-head> に変換されます。 これにより、CSS だけで TEI 要素のスタイルを定義でき、サーバサイドの変換処理が不要になります。 追加した機能 XML / プレビュー タブ切り替え 変換結果の表示エリアに 「XML」と「プレビュー」の2つのタブを追加しました。 XML タブ: 従来どおりのシンタックスハイライト付き XML 表示 プレビュータブ: CETEIcean によるレンダリング結果 タブをクリックするだけで切り替えられます。 ...

TEI Garage APIを使って、DOCX → TEI/XML 変換ツールをブラウザだけで作った

TEI Garage APIを使って、DOCX → TEI/XML 変換ツールをブラウザだけで作った

はじめに TEI (Text Encoding Initiative) は、人文学分野のテキストをデジタルで構造化するための国際標準です。図書館・博物館・学術研究などで利用されていますが、TEI/XML を直接書くにはマークアップの知識が必要で、導入のハードルが高いのが実情です。 そこで活用されるのが、Microsoft Word (.docx) から TEI/XML への変換ツールです。代表的なものに TEI Garage(旧 OxGarage)がありますが、多機能ゆえに UI がやや複雑です。今回、DOCX → TEI/XML の変換に特化した、シンプルなブラウザベースのツールを作成しました。 https://github.com/nakamura196/tei-converter デモサイト: https://tei-converter.pages.dev/ 仕組み TEI Garage は REST API を公開しており、以下のエンドポイントに DOCX ファイルを POST するだけで TEI/XML が返ってきます。 POST https://teigarage.tei-c.org/ege-webservice/Conversions/ docx:application:vnd.openxmlformats-officedocument.wordprocessingml.document/ TEI:text:xml/ 本ツールはこの API を呼び出すフロントエンドです。変換処理自体は TEI Consortium が運営するサーバ上で行われます。 主な機能 ドラッグ & ドロップ .docx ファイルをブラウザにドラッグ & ドロップするだけでアップロードできます。クリックしてファイルを選択することも可能です。 整形済み XML プレビュー 変換結果はインデント付きで整形され、シンタックスハイライト付きで表示されます。タグ名、属性名、属性値がそれぞれ色分けされるため、構造を把握しやすくなっています。 コピー & ダウンロード 結果をワンクリックでクリップボードにコピーしたり、.xml ファイルとしてダウンロードしたりできます。 サンプル DOCX 内蔵 「サンプル .docx で試す」をクリックするだけで、内蔵のサンプルファイルで動作を確認できます。サンプルのダウンロードも可能です。 ...

Hypothes.is APIでWebアノテーションをエクスポートしてTEI/XMLに変換する

Hypothes.is APIでWebアノテーションをエクスポートしてTEI/XMLに変換する

はじめに Hypothes.isは、Webページ上にハイライトやコメントを付けられるオープンソースのアノテーションツールです。ブラウザ拡張やJavaScriptの埋め込みで手軽に使えますが、蓄積したアノテーションをバックアップしたい、あるいはTEI/XMLなど別の形式で活用したいケースもあります。 本記事では、Hypothes.is APIを使ってアノテーションをエクスポートし、TEI/XMLに変換する方法を紹介します。 APIキーの取得 Hypothes.isにログイン Developer settings にアクセス 「Generate your API token」でAPIキーを生成 取得したキーを.envファイルに保存します。 cp .env.example .env # .env を編集してAPIキーを設定 HYPOTHESIS_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx アノテーションのエクスポート APIの基本 Hypothes.is APIのベースURLは https://api.hypothes.is/api です。認証はAuthorization: Bearer <API_KEY>ヘッダーで行います。 主要なエンドポイント: エンドポイント 用途 GET /api/profile 認証ユーザーのプロフィール取得 GET /api/search アノテーション検索 GET /api/annotations/{id} 個別アノテーション取得 スクリプト エクスポートからTEI/XML変換までを1つのスクリプト hypothes_export.py にまとめています。 https://github.com/nakamura196/hypothes-export/blob/main/hypothes_export.py 以下、主要な処理を抜粋して説明します。 .envの読み込みとAPI呼び出し def load_env(): env_path = Path(__file__).parent / ".env" with open(env_path) as f: for line in f: line = line.strip() if line and not line.startswith("#") and "=" in line: k, v = line.split("=", 1) os.environ[k.strip()] = v.strip() def api_get(endpoint, params=None): api_key = os.environ["HYPOTHESIS_API_KEY"] url = f"https://api.hypothes.is/api/{endpoint}" if params: url += "?" + urllib.parse.urlencode(params) req = urllib.request.Request(url) req.add_header("Authorization", f"Bearer {api_key}") with urllib.request.urlopen(req) as resp: return json.loads(resp.read().decode()) 全アノテーションの取得(ページネーション対応) Search APIは1リクエストあたり最大200件なので、offsetをずらして全件取得します。 ...

OpenITI mARkdownからTEI XMLへの自動変換ツール「oitei」を試す

OpenITI mARkdownからTEI XMLへの自動変換ツール「oitei」を試す

はじめに イスラーム圏の歴史テキストを扱う 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)を人名として含む」という意味です。 ...

ODD編集Tips:その1

ODD編集Tips:その1

要素の属性を特定のものだけに制限する TEIのデフォルトでは、要素は多くの属性クラス(att.global、att.datableなど)を継承しており、多数の属性が使用可能です。特定の属性のみを許可したい場合は、以下のように設定します。 例: persNameでxml:idとcorrespのみを許可 <elementSpec ident="persName" mode="change"> <classes mode="change"> <!-- 属性クラスを削除(モデルクラスは維持) --> <memberOf key="att.global" mode="delete"/> <memberOf key="att.cmc" mode="delete"/> <memberOf key="att.datable" mode="delete"/> <memberOf key="att.editLike" mode="delete"/> <memberOf key="att.personal" mode="delete"/> <memberOf key="att.typed" mode="delete"/> </classes> <attList> <attDef ident="xml:id" mode="add" usage="opt"> <desc>要素の一意な識別子</desc> <datatype> <dataRef name="ID"/> </datatype> </attDef> <attDef ident="corresp" mode="add" usage="opt"> <desc>関連する人物情報へのリンク</desc> <datatype> <dataRef key="teidata.pointer"/> </datatype> </attDef> </attList> </elementSpec> ポイント <classes mode="change">を使用: mode="replace"で空にすると、モデルクラスも削除され要素自体が使えなくなる 属性クラスを個別に削除 : <memberOf key="att.xxx" mode="delete"/>で不要な属性クラスを削除 必要な属性を追加 : <attDef ident="xxx" mode="add">で許可したい属性を定義 注意点 要素がどの属性クラスに属しているかは、TEI Guidelinesで確認できる att.globalを削除するとxml:id、xml:langなども使えなくなるため、必要に応じて個別に追加する 要素に属性を追加する 既存の属性クラスを維持したまま、新しい属性を追加する場合: <elementSpec ident="pb" mode="change"> <attList> <attDef ident="facs" mode="add" usage="opt"> <desc>原本画像へのリンク</desc> <datatype> <dataRef key="teidata.pointer"/> </datatype> </attDef> </attList> </elementSpec> この場合、既存の属性クラスはそのまま維持され、facs属性が追加されます。

TEI ODDによるIIIF対応ファクシミリ記述の制約設計

TEI ODDによるIIIF対応ファクシミリ記述の制約設計

はじめに TEI(Text Encoding Initiative)でデジタル画像のメタデータを記述する際、facsimile要素を使用します。特にIIIF(International Image Interoperability Framework)対応のデジタルアーカイブでは、マニフェストやキャンバス、Image APIへの参照を適切に記述することが重要です。 本記事では、ODD(One Document Does it all)を使用して、ファクシミリ記述に必要な制約をスキーマとして定義する方法を紹介します。 準拠するガイドライン 本ODDは、日本語TEIガイドラインで紹介されている「IIIF画像とのリンク」仕様をベースにしています: IIIF画像とのリンク(2024年度版)- TEI-EAJ このガイドラインに準拠したデータを作成することで、TEI Viewer for EAJでの画像表示が可能になります。TEI Viewerは、TEIテキストとIIIF画像を連携して表示できるビューアであり、facsimile要素の情報を利用してテキストと画像の対応付けを行います。 設計目標 以下の要件を満たすスキーマを設計しました: 必須情報の明確化 : 画像の座標情報や識別子など、最低限必要な情報を必須属性として定義 IIIF対応 : マニフェスト、キャンバス、Image APIへの参照をオプショナルに記述可能 再利用性 : 独立したODDファイルとして、複数プロジェクトで共有可能 ビューア互換性 : TEI Viewer for EAJでの表示に必要な情報を確実に記録 最小限の記述例 <facsimile sameAs="https://example.org/iiif/manifest.json"> <surface ulx="0" uly="0" lrx="5600" lry="4000" xml:id="p1"> <graphic sameAs="https://example.org/image/001.tif"/> </surface> </facsimile> 完全な記述例(IIIF参照を含む) <facsimile sameAs="https://example.org/iiif/manifest.json"> <surface ulx="0" uly="0" lrx="5600" lry="4000" sameAs="https://example.org/canvas/p1" xml:id="p1"> <graphic url="https://example.org/image/001.tif/full/full/0/default.jpg" sameAs="https://example.org/image/001.tif"/> </surface> </facsimile> ODD定義の解説 1. facsimile要素 <elementSpec ident="facsimile" mode="change"> <desc>ファクシミリ画像情報。IIIFマニフェストへの参照を含む。</desc> <classes mode="replace"/> <content> <elementRef key="surface" minOccurs="1" maxOccurs="unbounded"/> </content> <attList mode="replace"> <attDef ident="sameAs" mode="replace" usage="opt"> <desc>IIIFマニフェストへの参照URL</desc> <datatype> <dataRef key="teidata.pointer"/> </datatype> </attDef> </attList> </elementSpec> ポイント : ...

Deep Zoom画像を完全復元:タイル画像からBigTIFFへの変換技術

Deep Zoom画像を完全復元:タイル画像からBigTIFFへの変換技術

はじめに Webサイト上で高解像度画像をスムーズにズーム表示するために使用されるDeep Zoom技術。Microsoft Deep Zoom Composerなどで生成されたタイル化された画像データから、元の高解像度画像を復元する必要に迫られることがあります。 本記事では、Deep Zoom形式で公開されている画像データから、元の高解像度TIFF画像を復元する技術について解説します。 Deep Zoom画像の仕組み タイル構造 Deep Zoom画像は、1枚の大きな画像を複数の小さなタイル画像に分割し、ピラミッド構造で保存します: レベル0 : 最も低解像度(通常1タイル) レベルN : 最高解像度(元画像の解像度に相当) 各レベルで解像度が2倍になる ファイル構成 dzc_output.xml # メタデータ dzc_output_files/ ├── 0/ │ └── 0_0.jpg # レベル0の唯一のタイル ├── 1/ │ ├── 0_0.jpg │ └── ... └── 16/ # 最高レベル ├── 0_0.jpg ├── 0_1.jpg └── ... # 数万枚のタイル 実装の課題と解決策 課題1: XMLメタデータの名前空間の違い Deep Zoomには複数のバージョンがあり、XMLの名前空間が異なります: http://schemas.microsoft.com/deepzoom/2008 http://schemas.microsoft.com/deepzoom/2009 解決策 : 複数の名前空間に対応した柔軟なXMLパーサーを実装 ...

TEI Processing Modelで実現する宣言的なマルチフォーマット変換

TEI Processing Modelで実現する宣言的なマルチフォーマット変換

はじめに TEI (Text Encoding Initiative) は人文学テキストのデジタル化において広く使われている標準規格です。本記事では、TEI P5で導入された Processing Model という機能を使って、TEI XMLから複数のフォーマット(HTML、LaTeX/PDF、EPUB3)への変換を実現した事例を紹介します。 https://www.tei-c.org/Vault/P5/3.0.0/doc/tei-p5-doc/en/html/TD.html#TDPM 対象プロジェクトは「校異源氏物語」で公開されているテキストを例とします。 https://kouigenjimonogatari.github.io/ 背景 これまで、以下の記事で紹介したように、変換処理を個別に行ってきました。 ODD/RNGファイルのカスタマイズによる、使用するタグの限定 XSLTを用いたHTMLへの変換 XSLTを用いたTeX/PDFへの変換 EPUBへの変換 それぞれの取り組みにおいて、個別の変換ルールなどを記載したファイルを作成する必要があり、その煩雑さが課題となっていました。 Processing Modelとは Processing Modelは、TEI要素の変換ルールを宣言的 に記述する仕組みです。従来は各出力フォーマット用に個別のXSLTを書く必要がありましたが、Processing Modelを使うことで: ODDファイル内で変換ルールを定義 できる 複数の出力フォーマット に対応可能(web、latex、epubなど) スキーマと変換ルールを一元管理 できる Processing Modelの構造 <elementSpec ident="persName" mode="change"> <desc>Personal name</desc> <model> <!-- HTML output --> <modelSequence output="web"> <model behaviour="inline"> <outputRendition>span</outputRendition> <desc>Inline span for person name</desc> </model> </modelSequence> <!-- EPUB3 output --> <modelSequence output="epub"> <model behaviour="inline"> <outputRendition>span</outputRendition> <desc>Inline span for person name in EPUB3</desc> </model> </modelSequence> <!-- LaTeX output --> <modelSequence output="latex"> <model behaviour="inline"> <outputRendition>\person</outputRendition> <desc>Custom LaTeX command for person names</desc> </model> </modelSequence> </model> </elementSpec> 主な要素: ...

TEI/XMLファイルをGitHubで公開する手順書

TEI/XMLファイルをGitHubで公開する手順書

はじめに この記事では、TEI(Text Encoding Initiative)形式のXMLファイルをGitHubにアップロードし、誰でも参照できるURLを作成する手順を説明します。 TEI/XMLは、歴史文献や文学作品などのテキストを構造的に記述するための国際標準形式です。GitHubを使うことで、あなたの研究データを世界中の研究者と共有できるようになります。 必要なもの パソコン(Windows、Mac、Linuxのいずれか) インターネット接続 TEI/XMLファイル(すでにお持ちのもの) メールアドレス(GitHubアカウント作成用) サンプルファイルについて TEI/XMLファイルをお持ちでない方は、以下の『校異源氏物語』のTEI/XMLファイルを練習用として使用できます: サンプルファイルURL : https://raw.githubusercontent.com/kouigenjimonogatari/kouigenjimonogatari.github.io/master/tei/01.xml このファイルをダウンロードする方法: 上記URLをブラウザで開く 右クリック→「名前を付けて保存」を選択 ファイル名を「koukin_genji_01.xml」などに設定して保存 ステップ1:GitHubアカウントの作成 1-1. GitHubのウェブサイトにアクセス ブラウザ(Chrome、Firefox、Safari等)を開きます アドレスバーに https://github.com と入力してEnterキーを押します 1-2. アカウント作成 右上の「Sign up」ボタンをクリックします 以下の情報を入力します: メールアドレス :普段お使いのメールアドレス パスワード :安全なパスワード(8文字以上、数字と記号を含む) ユーザー名 :他の人と重複しない名前(例:yamada-taro2024) 「Create account」をクリックします メールに届いた認証コードを入力します 💡 ヒント : ユーザー名は後から変更できないので、慎重に選びましょう。研究者として使う場合は、実名に基づいた名前がおすすめです。 ステップ2:新しいリポジトリの作成 リポジトリとは、ファイルを保管する「プロジェクトフォルダ」のようなものです。 2-1. リポジトリ作成画面へ GitHubにログインした状態で、右上の「+」マークをクリックします 「New repository」を選択します 2-2. リポジトリの設定 以下の項目を入力・選択します: Repository name(リポジトリ名) 英数字とハイフン(-)が使えます 例:tei-xml-collection、medieval-texts-tei Description(説明)※任意 プロジェクトの簡単な説明 例:「中世文献のTEI/XMLファイル集」 Public/Private(公開設定) Public を選択:誰でも閲覧可能(推奨) Private:招待した人のみ閲覧可能 Initialize this repository with:(初期化オプション) ✅ Add a README file にチェックを入れる その他はそのままで大丈夫です 緑色の「Create repository」ボタンをクリックします ステップ3:TEI/XMLファイルのアップロード 3-1. アップロード画面へ リポジトリが作成されると、ファイル一覧画面が表示されます 「Add file」ボタンをクリックします 「Upload files」を選択します 3-2. ファイルのアップロード 方法A:ドラッグ&ドロップ エクスプローラー(Windows)またはFinder(Mac)でTEI/XMLファイルがある場所を開きます アップロードしたいファイルを選択します(複数選択可) ブラウザの点線枠内にドラッグ&ドロップします 方法B:ファイル選択 「choose your files」をクリックします ファイル選択ダイアログでTEI/XMLファイルを選択します 「開く」をクリックします 実例:『校異源氏物語』のTEI/XMLファイルをアップロード サンプルファイルを使った具体例: ...

RELAX NGとSchematronを組み合わせたTEI XMLスキーマの実装ガイド

RELAX NGとSchematronを組み合わせたTEI XMLスキーマの実装ガイド

! 人手で検証を行った後、AIが記事を執筆しました。 はじめに TEI(Text Encoding Initiative)XMLを編集する際、要素や属性の構造検証だけでなく、より複雑なビジネスルールの検証が必要になることがあります。本記事では、RELAX NG(RNG)とSchematronを組み合わせて、構造検証と内容検証の両方を実現する方法を、実際のプロジェクトで直面した課題を例に解説します。 解決したい課題 日本の古典文学テキストをTEI XMLで校訂する際、以下のような要求がありました: ID参照の動的検証 : corresp属性で参照するIDが、実際に文書内のwitness要素に存在することを検証したい Oxygen XML Editorでの補完機能 : 編集時にIDの候補を自動表示したい 複数ID参照のサポート : スペース区切りで複数のIDを指定可能にしたい 特定要素のみ参照を許可 : witness要素のIDのみを参照可能とし、person要素のIDが含まれる場合はエラーにしたい なぜRNG + Schematronなのか? RELAX NGの得意分野 要素・属性の構造定義 データ型の指定 基本的な内容モデルの定義 Schematronの得意分野 XPathベースの複雑な検証ルール 文書内の相互参照チェック カスタムエラーメッセージの提供 この2つを組み合わせることで、構造と内容の両面から厳密な検証が可能になります。 実装例 1. 基本的なRNGスキーマ構造 <?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:sch="http://purl.oclc.org/dsdl/schematron" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" ns="http://www.tei-c.org/ns/1.0"> <!-- Schematron名前空間宣言 --> <sch:ns prefix="tei" uri="http://www.tei-c.org/ns/1.0"/> <!-- ここにSchematronルールを埋め込む --> <start> <ref name="TEI"/> </start> <!-- RNGによる構造定義 --> </grammar> 2. ID定義とanyURI型の活用 Oxygen XML Editorで自動補完を実現するために、anyURI型を使用します: ...

生成AIを用いてプロジェクトに特化したrngファイルを作成する

生成AIを用いてプロジェクトに特化したrngファイルを作成する

概要 TEI/XMLファイルを編集する際、検証に使用するrngファイルを変更することで、使用するタグや属性を限定することができます。これにより、作業者が使用するタグに混乱しない、作成されるTEI/XMLのばらつきが軽減する、といった利点が考えられます。 rngファイルを編集する方法として、以下の記事で紹介したように、Romaを使用する方法が一般的です。 この方法はトップダウン的に使用するタグや属性を限定していく方法ですが、今回は、すでに作成済みのTEI/XMLから、生成AIを用いて、ボトムアップ的にrngファイルを作成してみます。 対象データ 校異源氏物語テキストDBで公開されている以下のXMLファイルを対象とします。 https://kouigenjimonogatari.github.io/tei/01.xml このファイルでは、以下のtei_all.rngを使用しています。 http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng そのため、以下のように、挿入可能な多くのタグがサジェストされることがわかります。 生成AIによるrngファイルの作成 以下のようなプロンプトにより、対象とするXMLファイルのタグの使用状況などに応じて、rngファイルを作成します。 # XMLファイル用カスタムRNGスキーマ作成依頼 ## 目的 - 作業効率向上のため、使用する要素・属性を限定したRNGスキーマを作成 - 作業者がタグ選択に迷わず、一貫した構造で編集できる環境を構築 ## 提供するファイル - ファイル名: 01.xml ## 要望 1. **現在のXMLファイルを分析**し、実際に使用されている要素・属性を特定 2. **最小限かつ必要十分な要素セット**でRNGスキーマを作成 3. **入力補完・バリデーション**が効果的に働くよう設計 4. **コメント付き**で、各要素の用途を明記 ## 制約・方針 - 不要な要素は除外(例:○○、××は使用しない) - 必須属性を明確に定義 ## 期待する成果物 1. カスタムRNGファイル(.rng) 2. 簡潔な使用ガイド 結果、以下のrngファイルが作成されました。 <?xml version="1.0" encoding="UTF-8"?> <!-- カスタムRNGスキーマ: 校異源氏物語TEIファイル用 作成日: 2024年 【目的】 - 作業効率向上のため、実際に使用する要素・属性のみに限定 - 入力補完とバリデーションを効果的に機能させる - 作業者がタグ選択に迷わない明確な構造 --> <grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" ns="http://www.tei-c.org/ns/1.0"> <start> <ref name="TEI"/> </start> <!-- ==================== ルート要素 ==================== --> <define name="TEI"> <element name="TEI"> <a:documentation>TEI文書のルート要素</a:documentation> <ref name="teiHeader"/> <ref name="facsimile"/> <ref name="text"/> </element> </define> <!-- ==================== ヘッダー部分(編集対象外) ==================== --> <define name="teiHeader"> <element name="teiHeader"> <a:documentation> メタデータ領域(編集作業では変更しない) - fileDesc: 書誌情報 - encodingDesc: エンコーディング情報 </a:documentation> <ref name="fileDesc"/> <ref name="encodingDesc"/> </element> </define> <!-- 書誌情報 --> <define name="fileDesc"> <element name="fileDesc"> <ref name="titleStmt"/> <ref name="publicationStmt"/> <ref name="sourceDesc"/> </element> </define> <!-- タイトル情報 --> <define name="titleStmt"> <element name="titleStmt"> <element name="title"> <text/> </element> <element name="author"> <text/> </element> <oneOrMore> <ref name="respStmt"/> </oneOrMore> </element> </define> <!-- 責任表示 --> <define name="respStmt"> <element name="respStmt"> <element name="resp"> <attribute name="when"> <a:documentation>作業日(YYYY-MM-DD形式)</a:documentation> <data type="date"/> </attribute> <text/> </element> <element name="name"> <text/> </element> </element> </define> <!-- 出版情報 --> <define name="publicationStmt"> <element name="publicationStmt"> <element name="distributor"> <text/> </element> <element name="date"> <attribute name="when"> <data type="date"/> </attribute> <text/> </element> <element name="availability"> <element name="p"> <element name="ref"> <attribute name="target"> <data type="anyURI"/> </attribute> <text/> </element> </element> </element> </element> </define> <!-- 原資料情報 --> <define name="sourceDesc"> <element name="sourceDesc"> <element name="bibl"> <element name="author"> <text/> </element> <element name="title"> <text/> </element> <element name="publisher"> <text/> </element> </element> </element> </define> <!-- エンコーディング情報 --> <define name="encodingDesc"> <element name="encodingDesc"> <element name="p"> <mixed> <optional> <element name="ref"> <attribute name="target"> <data type="anyURI"/> </attribute> <text/> </element> </optional> </mixed> </element> </element> </define> <!-- ==================== 画像参照部分 ==================== --> <define name="facsimile"> <element name="facsimile"> <a:documentation> 画像情報を管理する領域 - IIIF対応の画像URLとゾーン座標を定義 </a:documentation> <ref name="surfaceGrp"/> </element> </define> <!-- 画像グループ --> <define name="surfaceGrp"> <element name="surfaceGrp"> <attribute name="facs"> <a:documentation>IIIFマニフェストURL(必須)</a:documentation> <data type="anyURI"> <param name="pattern">https://.*\.json</param> </data> </attribute> <oneOrMore> <ref name="surface"/> </oneOrMore> </element> </define> <!-- 個別画像情報 --> <define name="surface"> <element name="surface"> <a:documentation>1つの画像面を表す</a:documentation> <ref name="graphic"/> <oneOrMore> <ref name="zone"/> </oneOrMore> </element> </define> <!-- 画像リンク --> <define name="graphic"> <element name="graphic"> <attribute name="n"> <a:documentation>IIIFキャンバスURL</a:documentation> <data type="anyURI"/> </attribute> <attribute name="url"> <a:documentation>画像の直接URL</a:documentation> <data type="anyURI"/> </attribute> <empty/> </element> </define> <!-- 画像上の領域定義 --> <define name="zone"> <element name="zone"> <a:documentation> 画像上の矩形領域を定義 - ページやコラムの範囲を指定 </a:documentation> <attribute name="xml:id"> <a:documentation>ゾーンID(zone_XXXX形式)</a:documentation> <data type="ID"> <param name="pattern">zone_\d{4}</param> </data> </attribute> <attribute name="lrx"> <a:documentation>右下X座標</a:documentation> <data type="nonNegativeInteger"/> </attribute> <attribute name="lry"> <a:documentation>右下Y座標</a:documentation> <data type="nonNegativeInteger"/> </attribute> <attribute name="ulx"> <a:documentation>左上X座標</a:documentation> <data type="nonNegativeInteger"/> </attribute> <attribute name="uly"> <a:documentation>左上Y座標</a:documentation> <data type="nonNegativeInteger"/> </attribute> <empty/> </element> </define> <!-- ==================== テキスト本文(主要編集領域) ==================== --> <define name="text"> <element name="text"> <a:documentation>テキスト本文のコンテナ</a:documentation> <ref name="body"/> </element> </define> <!-- 本文 --> <define name="body"> <element name="body"> <a:documentation>本文領域</a:documentation> <oneOrMore> <ref name="p"/> </oneOrMore> </element> </define> <!-- 段落 --> <define name="p"> <element name="p"> <a:documentation> 段落要素 - 通常は文書全体で1つのp要素を使用 </a:documentation> <ref name="textContent"/> </element> </define> <!-- ==================== テキストコンテンツモデル ==================== --> <define name="textContent"> <a:documentation> 本文内で使用可能な要素群 </a:documentation> <zeroOrMore> <choice> <text/> <ref name="lb"/> <ref name="pb"/> <ref name="seg"/> </choice> </zeroOrMore> </define> <!-- 改行 --> <define name="lb"> <element name="lb"> <a:documentation> 改行マーカー - 原本の改行位置を示す - 空要素として使用 </a:documentation> <empty/> </element> </define> <!-- ページ境界 --> <define name="pb"> <element name="pb"> <a:documentation> ページ境界マーカー - 新しいページの開始を示す - 必ず対応するzone要素を参照 </a:documentation> <attribute name="n"> <a:documentation>ページ番号(数値)</a:documentation> <data type="positiveInteger"/> </attribute> <attribute name="facs"> <a:documentation>対応するzoneへの参照(#zone_XXXX形式)</a:documentation> <data type="string"> <param name="pattern">#zone_\d{4}</param> </data> </attribute> <empty/> </element> </define> <!-- テキストセグメント(最重要要素) --> <define name="seg"> <element name="seg"> <a:documentation> テキストセグメント 【重要】主要な編集対象要素 - 1行または意味的なまとまりごとに分割 - 各セグメントは固有のIDを持つ外部リソースに対応 - corresp属性で外部データベースとリンク </a:documentation> <attribute name="corresp"> <a:documentation> 外部リソースへのリンク(必須) 形式: https://w3id.org/kouigenjimonogatari/api/items/XXXX-XX.json </a:documentation> <data type="anyURI"> <param name="pattern">https://w3id\.org/kouigenjimonogatari/api/items/\d{4}-\d{2}\.json</param> </data> </attribute> <text/> </element> </define> </grammar> XMLへの適用 以下のように、作成したrngファイルを適用します。 ...

DToC: Dynamic Table of Contextsを試す

DToC: Dynamic Table of Contextsを試す

概要 DToC: Dynamic Table of Contextsを試す機会がありましたので、備忘録です。 https://www.leaf-vre.org/docs/features/dtoc 機械翻訳の結果は以下です。 セマンティックマークアップの威力と書籍のナビゲーション機能を融合させ、電子読書に革新をもたらします。従来の印刷書籍で長年親しまれてきた目次とキーワード索引という概観機能が、全文検索やタグベースのインデックス機能と動的に統合されることで、新たな読書体験を実現します。 最終的に、以下のような可視化を行うことができました。 https://dtoc.leaf-vre.org/view?document=https://dtoc-demo.vercel.app/P-III-b-1189/dtoc.json 対象データ 東洋文庫が所蔵するモリソンパンフレット「Marco Polo’s adventures : The greatest traveller the world has seen.」をサンプルデータとして利用しました。 https://www.toyo-bunko.org/open/show_detail_open.php?targetid=363479 https://www.toyo-bunko.org/morisonp2015/morisonpocr2016_showimg.php?tgfn=P-III-b-1189&tgfn2=01Geo01 背景 以下のワークショップに参加し、DToCの使用方法を教えてもらいました。 https://github.com/LEAF-VRE/dh2025_workshop 以下のチュートリアルも参考になりました。 https://www.leaf-vre.org/docs/training/tutorials/dtoc-tutorial mainとなるxmlを作成する まず、mainとなるxmlを作成します。以下のURLで確認できます。 https://dtoc-demo.vercel.app/P-III-b-1189/main.xml OCR Azure AI Document Intelligenceを用いてOCRを行いました。 https://azure.microsoft.com/en-us/products/ai-services/ai-document-intelligence 校正 & タグづけ OCR結果の校正と、人名や地名のタグ付与にあたり、「Google: Gemini 2.5 Pro」を使用しました。 https://deepmind.google/models/gemini/pro/ このように機械的な処理のため、誤りなどが含まれている可能性が高いですが、DToCで使用するためのTEI/XMLファイルを用意することができました。 index用のxmlを作成する 以下を参考にしました。 https://www.leaf-vre.org/docs/training/tutorials/dtoc-tutorial#step-2-create-an-index このindex作成にも「Google: Gemini 2.5 Pro」を使用し、先に作成したmain.xmlから機械的に作成しました。結果は以下です。 https://dtoc-demo.vercel.app/P-III-b-1189/index.xml JSONファイルを作成する DToCでロードするためのJSONファイルを作成します。この部分はGUIから行うことができました。最終的な結果は以下です。 https://dtoc-demo.vercel.app/P-III-b-1189/dtoc.json まず、以下にアクセスし、GitHubアカウントでログインします。 https://dtoc.leaf-vre.org/ 次に以下にアクセスします。 https://dtoc.leaf-vre.org/view そして、チュートリアル資料などを参考に、必要な項目を入力します。 Documentsには、前のプロセスで作成したXMLファイルのURLを入力します。 Corpus Partsでは、XMLファイルのどの部分を使用するか、を指定します。Curpus Partではmain.xmlのdivタグを、Curpus Indexではindex.xmlのdivタグをXPathで指定しました。 ...

DHConvalidatorにおける'ref'に関する不具合への対応

DHConvalidatorにおける'ref'に関する不具合への対応

本記事は、一部AIが執筆しました。 概要 DHConvalidatorは、デジタル人文学(DH)会議の抄録を一貫したTEI(Text Encoding Initiative)テキストベースに変換するためのツールです。 https://github.com/ADHO/dhconvalidator このツールの利用において、Microsoft Word形式(DOCX)からTEI XML形式への変換処理中に以下のようなエラーが発生するケースがありました: ERROR: nu.xom.ParsingException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'ref' この原因と対処方法について共有します。 原因の特定 調査の結果、問題の原因はWord文書内に埋め込まれた INCLUDEPICTUREフィールドコード であることが判明しました。 具体的には、Googleドキュメントから画像をコピー&ペーストした際に、以下のようなフィールドコードが文書内に残存していました: INCLUDEPICTURE "https://lh7-rt.googleusercontent.com/docsz/..." \* MERGEFORMATINET これらの外部画像参照リンクがTEI変換プロセスで適切に処理されず、XML検証エラーを引き起こしていました。 解決方法 この問題を解決するため、DOCXファイル内の問題のあるフィールドコードを自動的に除去するPythonスクリプトを開発しました。 スクリプトの特徴 安全な処理 : 画像コンテンツ自体は保持し、フィールドコード部分のみを削除 ZIP形式対応 : DOCXファイルの内部構造(ZIP + XML)を適切に処理 名前空間対応 : Word文書のXML名前空間を考慮した正確な要素検索 主要な処理ロジック DOCXファイルを一時ディレクトリに展開 word/document.xml内のフィールドコード構造を解析 INCLUDEPICTUREを含むフィールドを特定 フィールド制御要素(begin/separate/end)のみを削除し、画像要素は保持 修正されたXMLで新しいDOCXファイルを生成 実装のポイント フィールドコード判定 def is_includepicture_field(field_runs, ns): for run in field_runs: instr_text = run.find('.//w:instrText', ns) if instr_text is not None and instr_text.text: if 'INCLUDEPICTURE' in instr_text.text: return True return False 削除対象の選別 def should_remove_run(run, ns): # フィールド制御要素を持つか確認 has_field_control = (run.find('.//w:fldChar', ns) is not None or run.find('.//w:instrText', ns) is not None) # 実際の画像コンテンツを持つか確認 has_image_content = (run.find('.//w:drawing', ns) is not None or run.find('.//w:pict', ns) is not None) # フィールド制御要素があり、画像コンテンツがない要素を削除 return has_field_control and not has_image_content 結果 このスクリプトにより、問題のあるフィールドコードが除去され、TEI変換プロセスが正常に完了するようになりました。画像は適切に文書内に埋め込まれた状態で保持されます。 ...

校異源氏物語テキストDBのDTS(Distributed Text Services) APIの更新

校異源氏物語テキストDBのDTS(Distributed Text Services) APIの更新

概要 校異源氏物語テキストDBのDTS(Distributed Text Services) APIを更新したので、備忘録です。 背景 DTS(Distributed Text Services) APIは以下で説明されています。 https://distributed-text-services.github.io/specifications/ 以下の記事で、DTS APIの作成について紹介しました。 一方、以下を課題としていました。 今回開発したDTS APIも上記のガイドラインに非対応の箇所がある可能性がある点にご注意ください。 そこで、前回作成したAPIをv1とし、今回はdtsVersionの1-alphaに従ったv2のAPIを作成します。 API 以下がEntry Endpointです。v1とv2の違いは以下です。 v1 https://dts-typescript.vercel.app/api/v1/dts { "navigation": "/api/v1/dts/navigation", "@id": "/api/v1/dts", "@type": "EntryPoint", "collections": "/api/v1/dts/collections", "@context": "dts/EntryPoint.jsonld", "documents": "/api/v1/dts/document" } v2 https://dts-typescript.vercel.app/api/v2/dts { "@context": "https://distributed-text-services.github.io/specifications/context/1-alpha1.json", "dtsVersion": "1-alpha", "@id": "/api/v2/dts", "@type": "EntryPoint", "collection": "/api/v2/dts/collection{?id}", "navigation": "/api/v2/dts/navigation{?resource,ref,down}", "document": "/api/v2/dts/document{?resource,ref}" } 同様に、各種Endpointの記述を変更しています。 ビューアの改修 以下の記事で、DTSのビューア開発について紹介しました。 そして、以下を課題としていましたが、この点に対応できるように改修しました。 Navigation Endpointを使用していますが、現時点で複数階層には非対応です。 例えば、Navigation Endpointは以下のように記述します。 https://dts-typescript.vercel.app/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1&down=1 { "@context": "https://distributed-text-services.github.io/specifications/context/1-alpha1.json", "dtsVersion": "1-alpha", "@type": "Navigation", "@id": "/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1&down=1", "resource": { "@id": "urn:kouigenjimonogatari.1", "@type": "Resource", "document": "/api/v2/dts/document?resource=urn:kouigenjimonogatari.1{&ref}", "collection": "/api/v2/dts/collection?id=urn:kouigenjimonogatari.1", "navigation": "/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1{&ref}", "citationTrees": [ { "@type": "CitationTree", "citeStructure": [ { "@type": "CiteStructure", "citeType": "page", "citeStructure": [ { "@type": "CiteStructure", "citeType": "line" } ] } ] } ] }, "member": [ { "identifier": "5", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "6", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "7", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "8", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, ... ] } 特に、CitationTreeを使って、階層を記述します。ビューアがこの情報を処理するように修正することで、以下のように、レベルごとのナビゲーションボタンが表示されるようにしました。 ...

IIIF画像に対する多角形アノテーション支援ツールの改修

IIIF画像に対する多角形アノテーション支援ツールの改修

概要 IIIF画像に対する多角形アノテーション支援ツール「IIIF Annotator」の改修を行いました。具体的には、以下の2点に取り組みました。 Image Server未使用のマニフェストファイルへの対応 アノテーション付きIIIFマニフェストファイルのエクスポート機能 TEI/XMLファイルのエクスポート機能 以下、これらの改修について説明します。 背景 以下の記事で、アノテーション付与ツールを新規に作成した理由等を説明しました。 今回追加した機能は他のツールでも提供されている機能群になりますが、利便性向上のため追加実装しました。 Image Server未使用のマニフェストファイルへの対応 以下の記事で紹介しているように、IIIFマニフェストファイルにおいて、Image API(Image Server)を使用しないオプションを取ることができます。デメリットもありますが、Cantaloupe Image Serverなどのソフトウェアを導入せずに使用できる点に利点があります。 IIIF Annotatorについて、これまではImage Serverの使用を前提として実装していましたが、今回の改修により、Image Server未使用のマニフェストファイルも読み込めるようにしました。 具体的には以下のように、serviceの有無に応じて、OpenSeadragonに渡すtileSourcesを調整しました。 const tileSources = canvases .map((canvas: Canvas) => { const annotationPage = canvas.items?.[0]; const annotation = annotationPage?.items?.[0]; if (!annotation) return null; const body = annotation.body as { id: string; service?: { "@id": string }[]; }; if (body.service && body.service.length > 0) { return body.service[0]["@id"] + "/info.json"; } else { return { type: "image", url: body.id, }; } }) .filter( (tileSource: string | { type: string; url: string } | null) => tileSource !== null ); エクスポート機能 アノテーション付きIIIFマニフェストファイル、およびTEI/XMLファイルとしてエクスポートする機能を追加しました。エクスポートボタンを押すと、以下のような選択肢が表示されます。 アノテーション付きIIIFマニフェストファイルの用途としては、ダウンロードしたファイルをMirador等に読み込ませることで、アノテーション結果を確認することができます。 またTEI/XMLファイルについては、Oxygen XML Editorの作者モード等を使って、アノテーション結果を確認することができます。 まとめ IIIFのアノテーション結果の活用にあたり、参考になりましたら幸いです。

DTS (Distributed Text Services)のビューア開発

DTS (Distributed Text Services)のビューア開発

概要 DTS (Distributed Text Services)のビューアを開発したので、備忘録です。 以下のURLからお試しいただけます。 https://dts-viewer.vercel.app/ja/ 背景 DTS (Distributed Text Services)の公式ページは以下です。 https://distributed-text-services.github.io/specifications/ 以下の記事でも取り上げました。 今回、このDTS仕様に一部準拠したビューアを開発しました。 使い方 以下がトップページです。フォームにDTSのURLを入力します。ページ下部で例を提供します。技術的には、Entry pointを使用しています。 コレクションの一覧ページです。Collection Endpointを使用しています。 以下のAPIを例としています。 リンクをたどると、以下のようなリソースの一覧ページに遷移します。 ダウンロードボタンを押すと、TEI/XMLが表示されます。Document Endpointを使用しています。 ナビゲーションボタンを押すと、アクセス可能な部分テキストの一覧が表示されます。Navigation Endpointを使用していますが、現時点で複数階層には非対応です。 リンクをクリックすると、以下のような部分テキストをダウンロードすることができます。 工夫点 公式ページに以下のように記載されています。 The DTS Specification is currently in a public comment period following the 1-alpha release (機械翻訳)DTS仕様は、1-alphaリリースの後、現在パブリックコメント期間中です。 このような背景のため、既存のDTSの記述方法にばらつきがありました。そこで内部でできるだけDTS API (1.0 Draft)に変換し、その結果を可視化するようにしています。 DTS仕様が成熟するにつれ、このような問題は解決されるかと思います。 まとめ DTS仕様は以下のように説明されています。 The Distributed Text Services (DTS) Specification defines an API for working with collections of text as machine-actionable data. ...

Annotorious v2のpolygonツールを使って、polylineを作成する

Annotorious v2のpolygonツールを使って、polylineを作成する

概要 Annotorious v2のpolygonツールを使って、polylineを作成する方法の備忘録です。 背景 Annotorious v2のウェブサイトは以下です。 https://annotorious.github.io/getting-started/ 以下のように、polygonを記述することができます。 一方、同様の方法でpolylineを記述するツールは、以下のプラグインを含めて、提供されていないようでした。 https://github.com/annotorious/annotorious-v2-selector-pack カスタマイズ 以下のような多角形を作成した場合、 以下のようなJSONファイルが作成されます。 { "type": "Annotation", "body": [ { "type": "TextualBody", "value": "polygon", "purpose": "commenting" } ], "target": { "source": "https://www.e-codices.unifr.ch/loris/gau/gau-Fragment/gau-Fragment_frag001a.jp2/full/full/0/default/jpg", "selector": { "type": "SvgSelector", "value": "<svg><polygon points=\"3383.121337890625,1290.137451171875 945.135498046875,1658.426513671875 885.9696655273438,3003.352294921875 2508.54150390625,3348.424072265625 3485.021484375,2724.35791015625 2170.811767578125,2107.6337890625\" /></svg>" } }, "@context": "http://www.w3.org/ns/anno.jsonld", "id": "#c469b1a3-8902-4443-8f54-47df8bb87d7e" } 上記に対して、autoCloseのような変数を用意し、これがfalseの場合、polygonという文字列をpolylineに変更する処理を加えました。 anno.on("createAnnotation", function (selection: any) { if(!autoClose.value) { selection.target.selector.value = selection.target.selector.value.replace("polygon", "polyline"); } ... }); これにより、以下のように、polygonツールをベースとして、polygonとpolylineを使い分けることができます。 TEI/XMLでの記述 TEI/XMLでの多角形の記述例として、path要素を使用することができます。この場合、polygonであれば始点を終点の後に追加することで、多角形を表現することができます。 <facsimile> <surface ulx="0" uly="0" lrx="8176" lry="6132"> <graphic url="https://www.e-codices.unifr.ch/loris/gau/gau-Fragment/gau-Fragment_frag001a.jp2/full/full/0/default/jpg" /> <zone xml:id="layer_000" change="#ch_layer_000" n="layer_01" type="layer"> <zone xml:id="sign_layer_000_0000" change="#ch_sign_layer_000_0000" type="sign"> <!-- polygon --> <path points="1290.137451171875,3383.121337890625 1658.426513671875,945.135498046875 3003.352294921875,885.9696655273438 3348.424072265625,2508.54150390625 2724.35791015625,3485.021484375 2107.6337890625,2170.811767578125 1290.137451171875,3383.121337890625"></path> </zone> <zone xml:id="sign_layer_000_0001" change="#ch_sign_layer_000_0001" type="sign"> <!-- polyline --> <path points="1393.265625,5290.81005859375 1921.02783203125,3869.745849609375 2982.731689453125,3829.64013671875 3428.122802734375,4874.005859375 2683.244384765625,5741.7509765625 2138.024169921875,4582.19775390625"></path> </zone> </zone> </surface> </facsimile> アプリケーションによっては、始点と終点が一致しなくても閉じた図形を描くことがあるかもしれませんが、polygonとpolylineを使い分ける方法として、参考になりましたら幸いです。 ...

Google Cloud Vision APIとGakuNin RDMを用いたTEI/XMLファイル作成アプリの試作

Google Cloud Vision APIとGakuNin RDMを用いたTEI/XMLファイル作成アプリの試作

概要 Google Cloud Vision APIとGakuNin RDMを用いたTEI/XMLファイル作成アプリを試作しましたので備忘録です。 背景 Google Cloud Vision APIを使ってOCR結果を反映したTEI/XMLファイルを作成する環境が必要になりました。そこでバックエンドとしてGakuNin RDMを用いて、ユーザごとにファイルを管理して、OCRを実行可能な環境を試作しました。 使い方 フォルダの作成 以下にアクセスします。 https://ge-manager.vercel.app/ 画面右上から、GakuNin RDMを使ってログインします。 以下のようにプロジェクト一覧が表示されます。 適当な階層まで下り、フォルダの作成ボタンを押します。 ここでは、「sample」というフォルダを作成します。 そして、「GE Manager」のリンクを押します。 以下のようなページに遷移します。 処理の実行 今回は、「e-codices - Virtual Manuscript Library of Switzerland」の「fragm1a」を使用させていただきます。 https://www.e-codices.unifr.ch/loris/gau/gau-Fragment/gau-Fragment_frag001a.jp2/full/full/0/default/jpg 画像のURLを入力して、アップロードボタンを押します。アップロードされると、以下のような画面に変わります。 次に、「OCR実行」ボタンを押します。正しく完了すると、以下のように表示されます。 次に「TEI/XML作成」ボタンを押します。正しく完了すると、以下のようにTEI/XMLとともに表示されます。 Oxygen XML Editorでダウンロードしたファイルを表示した例です。Google Cloud Vision APIによるOCR結果を確認することができます。 GakuNin RDMのファイル 上記のプロセスで作成された各種ファイルは、GakuNin RDMのフォルダにファイルとして保存されます。 参考: URLを介してアクセス可能な画像ファイルを用意する mdx.jpのオブジェクトストレージを利用して、URLを介してアクセス可能な画像ファイルを用意する。 今回はge-editorというバケットを作成し、以下のようなファイルを用意します。 { "Version": "2008-10-17", "Statement": [ { "Sid": "ge-editor", "Effect": "Allow", "Principal": { "DDN": ["*"] }, "Action": ["s3:ListBucket", "s3:GetObject"], "Resource": "ge-editor" } ] } そして、以下を実行することで、上記のバケットにアップロードされたファイルをダウンロード可能にします。 ...