はじめに

TEI(Text Encoding Initiative)のODD(One Document Does it all)ファイルから、スキーマ(RNG)やドキュメント(HTML)を生成する作業は、TEIプロジェクトにおいて重要な工程です。本記事では、Roma(TEIのODDエディタ)が内部で使用しているTEI Garage APIの仕組みを解析し、スクリプトから直接APIを呼び出してODDを変換する方法を紹介します。

TEI Garageとは

TEI Garageは、TEIコミュニティが提供するWebサービスで、様々なフォーマット間の変換を行うことができます。特にODDファイルの処理において、以下の機能を提供しています:

  • ODD → Compiled ODD への変換
  • Compiled ODD → RELAX NG スキーマへの変換
  • ODD → HTML ドキュメントへの変換
  • その他多数のフォーマット変換

Romaの内部動作を解析

Romaのネットワークトラフィックを観察すると、以下のような変換チェーンを使用していることがわかりました:

HTMLドキュメント生成の場合

ODDODDC(CompiledODD)TEIxHTML

実際のAPIエンドポイント:

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

RNGスキーマ生成の場合

ODDODDC(CompiledODD)RELAXNG

実際のAPIエンドポイント:

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/relaxng%3Aapplication%3Axml-relaxng/conversion

変換パラメータの詳細

Romaは変換時に以下のようなXML形式のプロパティを送信しています:

<c/o<<cnc/c/ovo<<<<<co<<<<<cnenppppponpppppovrvrrrrrnvrrrrrneseoooooveooooovrirppppperpppppesoseeeeerseeeeerinirrrrrsirrrrrsosotttttiotttttin>nyyyyyonyyyyyosnn>iiiiii>iiiiii>ndddddndddddd=====d=====e"""""e"""""xoooopxoooop=xxxxl=xxxxl"gggg."gggg.0aaaap1aaaap"rrrrs"rrrrs>aaaan>aaaanggggcggggceeee.eeee.....d....dggltlggltleeae.eeae.ttnxettnxeIOgtgIOgtgmn"Oemn"Oeal>n.al>n.gijltgijltenayeenayese<"ise<"i"I/>."I/>.>mpfp>mptpfararfarrragoloagouolepsflepefsseeisse<ie"r<le"r/l<>t/e<>tpe/fypN/fyrNpa>rapa>oarlomrlpmospeoseepeesperse<r"e<t"r/t>r/y>tpydtp>dyr>eyre>of>ofpapaeueurlrltttty<y<>/>/pprrooppeerrttyy>>

各プロパティの意味:

  • oxgarage.getImages: 画像を含めるかどうか
  • oxgarage.getOnlineImages: オンライン画像を取得するかどうか
  • oxgarage.lang: 出力言語(ja=日本語、en=英語)
  • oxgarage.textOnly: テキストのみの出力にするか(RNG生成時はtrue推奨)
  • pl.psnc.dl.ege.tei.profileNames: 使用するプロファイル(通常はdefault)

実装:Bashスクリプトによる自動変換

以下は、TEI Garage APIを使用してODDファイルを変換するBashスクリプトです:

####OOifBD#i#ef!DUfiAIfli/TUoDTSRHRibEsu_P[E_T[NfiIatFUeee_NMe#P#A#ceGe#P#A#cengpIT-ccxNAL"cRPuc[cRPuc/GeuL_zhhiAM$hOAIcrhhOAIcrhba:tETootMEOoPP_Ulo"oPP_Uloar-=Y"E=UEIUR-"$EIUR-"sat"P$""1=$T"RRL-F$"O"RRL-F$"hg/y$EOU$(PCTLs{HUCTLs{Recp1=Ds(dUoI=uATToI=uANoe""DaobiTnE"pPMPnE"pPGAn:$_guar_vShlILUvShlIPv2FetsnTeH=to_TeR=to_sIeh"I:peaYrT't"aUd_rN't"aUcrtLunmPtM<p$dRoTtG<p$dRh使tmE$taeEiLcOs{=LcYicOs{=Le-l"0-m"noD:D@}uPnoD:D@}mote"gnD/I"?mEg-nD/I"?ado]y$=v/R$pe"v/R$pOdrop"OOet_OrnOtet_OrsD.de$D"DreNDot=DereNDoaDsrd:ODhDsOiADpaDxsOiADpvhn-D_tiDgM_et"tiDgM_eeg[fhDFmtoDaEFrirtOoDaEFrdit_IlonCr}ItononnCr}Ito-lmFL"sa/Linglsa/LitdzelIEH>g$Ee"Ry>g$Eeod>L"]T<e{"ssN<e{"s-"oE);McT.B=a]GtcR.B=$f$r"LoEtA\$v;roEtA\${iOotnIeS{esunLeS{DlUurhdviEPdtcevAiEPIeTtnoeoe-_RhheX-_RR>PpgdncrcNOteerNcNO_Uu"dusx.APonmsG.APNTt)miHoMEaioMEAo_-eoTrER$.orERMuTtnnMg}T{.ng}TEtYytL/.ID./.I}pPpaiehEI"ierE/uEetngtSRngnS$t">idem}_deg}{-"oe-l"Ne-""Bt]nxw"AxwAy;.=eM=e\Sp."b\E"bEet.0s}0s_>h""e/"eNe>r$>rAn<v{<vMpiBpiErcArc}oeSoe.p/Ep/reC_eCnroNrogtnAtn"yvMyveEeir}irds.ds=ih=i"ot"oonmonxslxsg/"g/aOaOrDrDaDaDg%g%e3e3.A.AgtgteeeetxtxItItm%m%a3a3gAgAexexsmsm"l"l>/>/fOfOaDaDlDlDsCsCe%e%<3<3/A/Aptptrereoxoxptpte%e%r3r3tAtAyxyx>m>m<l<lp/p/rTrroEoepIple%ear3rxtAtnytyge%ixi3dtdA=%=a"3"poAopxxxlgmgialacr/raaxatghgieteo.m.nglg%e%e3t3tAOAOxnanmlpllipi-nlnreieeIcIlmamaataxgigneoegsns/"%"c>3>ofAfnaxavlhlestsremes<l<i/%/op2pnrBr"oxopmpeler/rtctyoy>n><v<peprrrosopipeoernrt"tyyiidd==""ooxxggaarraaggee..llaanngg"">>jjaa<<//pprrooppeerrttyy>><<pprrooppeerrttyyiidd==""ooxxggaarraaggee..tteexxttOOnnllyy"">>ftarlusee<<//pprrooppeerrttyy>><<pprrooppeerrttyyiidd==""ppll..ppssnncc..ddll..eeggee..tteeii..pprrooffiilleeNNaammeess"">>ddeeffaauulltt<<//pprrooppeerrttyy>><<//ccoonnvveerrssiioonn>><<ccoonnvveerrssiioonniinnddeexx==""11"">><<pprrooppeerrttyyiidd==""ooxxggaarraaggee..ggeettIImmaaggeess"">>ffaallssee<<//pprrooppeerrttyy>><<pprrooppeerrttyyiidd==""ooxxggaarraaggee..ggeettOOnnlliinneeIImmaaggeess"">>ffaallssee<<//pprrooppeerrttyy>><<pprrooppeerrttyyiidd==""ooxxggaarraaggee..llaanngg"">>jjaa<<//pprrooppeerrttyy>><<pprrooppeerrttyyiidd==""ooxxggaarraaggee..tteexxttOOnnllyy"">>tfraules<e/<p/rporpoepretryt>y<>p<rporpoepretrytyidi=d"=p"lp.lp.spnscn.cd.ld.le.geeg.et.etie.ip.rporfoiflielNeaNmaemse"s>"d>edfeafualutl<t/<p/rporpoepretryt>y<>/<c/ocnovnevresrisoino>n<>/<c/ocnovnevresrisoinosn>s'>'

Pythonによる実装例

より柔軟な処理が必要な場合は、Pythonを使用することもできます:

#iiffdi!mmrref/ppoofuoommsrrc"TA"#tp#iea#w_iooicrttpuo"Er"er/flpinfdufo/arn"Ig"xocAsitadtnbsrtlvstpoPoe_hml_poviyehleG:oo_e<<nIuee:eeufpprieeeppsfuupsensqliraduorc/c/vtnxnxroiarefl_nrryittryr/uibtrdtntococepdtdtlplriss_(iisl_pisteeb._a_plinonorup#peeanpresnn.etun._nspogfuyev<<<<<nv<<<<<nsto=o==nsmtoe#oopr:ppr=ytteytteovtiadeitsepppppvepppppvi_iri(s(nsuurerre=s((x=p_(xdsmrdl_X=rrrrrrerrrrrreotnnnfo=fspttitiit.""iet"idpps(AetM=sooooorsooooornyt.gt.'d="eoppnunnu"aUtsyOt(yoeoP:yL'ipppppsipppppssphrhd{Cnuutrttr_rs(y=pu(otrdIptfoeeeeeioeeeeei>e=t=nt_'{o=stt(n((n_gao1set1dhtidOer'nrrrrronrrrrro'mgtfu'ne__ffrmvgu).sp)dom_使D:u'tttttntttttn'='l''pippvr.ff"o"eNa)etaynu_nPpfDe'iyyyyy>iyyyyy>'=O'OsllreesiiSuEsoi:prsotf3aoi''<nnDD:eoorqtllutrpnn!ug.titrlhcdiiiiidiiiii'DD/,aptuaeecproe_=ptvatlhteOtioedddddedddddh%%/deiet.cuon_y-[riye,Dmfnx=====x=====t33t''rnsu=wetrs"3tt1gnp,qDlv="""""="""""mAAer:tgtsrs_:e::hy]veuo'oe"oooop"ooooplttibis_Pisf.op[[oouur0xxxxl1xxxxl'eeg'fe{.catfi{tne2'muttts"gggg."gggg.:xxa)}sopoteulre:]huteppi>aaaap>aaaapttr'dodh_leexctspuuorrrrsrrrrs%%aa:dse(blstohmtuttnaaaanaaaan33gs_toyyp)ntlt_'_sggggcggggcAAepf(=dtovm'b_trt>eeee.eeee.xx.fria=desnel,etyny....d....dmmt:olp_sasrypgpggltlggltlllepei2f(veto''pe'eeeae.eeae.//ie}_0ire._rrhe=ttnxettnxeOO-ru0ledsont)'=IOgtgIOgtgDDcttr:estdrgmh=mn"Oemn"OeDD.iol)ptadn'ltal>n.al>n.CCoe,.oot.g]'m'gijltgijlt%%rs{wnup":lrenayeenaye33g}ofis{sy)o'nse<"ise<"iAA/uiteo_r)g"I/>."I/>.ttetlh.uc:'>mp{p>mp{peegpe_ctoo'fartrfartrxxeussopddreagoeoagoeott-t=unuednllepxflepxf%%w_fftt}-gsssetisseti33etife_"f'ee"r_le"r_lAAbylinf)i"<>toe<>toexxspextil)'/fynN/fynNmmees()lefpa>lapa>lallr.,ee>arlymrlym//vux}los}eos}eTrippt"spe<spe<sEecpa))oee</"e</"Ileeru'r/p>r/p>%a/rattprdtprd3xC(mpyroeyroeAno)su>opf>opftgn}=tpeapeae%v.p-eruerux3e.atrtlrtltAr.rytyttyt%as"apy><y><3pi)me>/>/Apos>ppxln)"rrmis)oolc/pp/a{eexterrhintttodyymnp>>l%o%3i3AnAxtam}pl/p-clroienclvaaetxrinsogin'o%n3'Axhtml%2Bxml'

エラーハンドリングと注意点

1. APIレスポンスの検証

変換が失敗した場合、TEI GarageはHTMLエラーページを返すことがあります。必ず応答を検証してください:

#iffigreceecaxphtiot-"q"$1E{"rOHrUToTTrPPUoTSc_tcFauItrLurEse}"d""d$u{rOiUnTgPUcTo_nFvIeLrEs}i"o;n"then

2. ファイルサイズの制限

TEI Garage APIには、アップロードファイルサイズの制限があります(通常は数MB程度)。大きなODDファイルの場合は、ローカルでの変換ツール(Saxon-HEなど)の使用を検討してください。

3. ネットワークタイムアウト

変換処理には時間がかかることがあるため、適切なタイムアウト設定が必要です:

#cucrUlRL-max-time300-soutput.html

複数ファイルの一括変換

複数のODDファイルを一括変換する場合のスクリプト例:

##fd!oo/rnbeioe#eendc/cc/OdhHcchhbD_oTooooaDfMnnsi"Lvv""hlPeeC-erRrro-oNttm-icG--p"neoolsddesddti..eonssddghhd$;$""oo$$dddoododdd__ddff__iifflliieell".ee.""."hrtnmgl

APIエンドポイントのURL構造

TEI GarageのAPIエンドポイントは、以下の構造を持っています:

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

0

各部分はURLエンコードされた形式で指定します:

  • ODD%3Atext%3Axml = ODD:text:xml
  • ODDC%3Atext%3Axml = ODDC:text:xml(Compiled ODD)
  • TEI%3Atext%3Axml = TEI:text:xml
  • xhtml%3Aapplication%3Axhtml%2Bxml = xhtml:application:xhtml+xml
  • relaxng%3Aapplication%3Axml-relaxng = relaxng:application:xml-relaxng

他の変換オプション

TEI Garageは他にも様々な変換をサポートしています:

ODD → XSD (XML Schema)

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

1

ODD → DTD

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

2

ODD → Schematron

https://teigarage.tei-c.org/ege-webservice/Conversions/ODD%3Atext%3Axml/ODDC%3Atext%3Axml/TEI%3Atext%3Axml/xhtml%3Aapplication%3Axhtml%2Bxml/conversion

3

まとめ

TEI Garage APIを直接使用することで、Romaを経由せずにODDファイルの変換を自動化できます。この方法のメリット:

  1. 自動化 : CI/CDパイプラインに組み込み可能
  2. バッチ処理 : 複数ファイルの一括変換が容易
  3. カスタマイズ : 変換パラメータを細かく制御可能
  4. 言語非依存 : curlが使える環境ならどこでも実行可能

特に、ODDファイルのバージョン管理と自動ビルドを組み合わせることで、スキーマとドキュメントの一貫性を保ちながら、効率的な開発フローを構築できます。

参考資料

関連記事