ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
Drupal Key authを用いたコンテンツの登録と多言語対応

Drupal Key authを用いたコンテンツの登録と多言語対応

概要 以下の記事で、Basic認証を使ったPythonによるコンテンツ登録を行いました。 今回は、以下の記事を参考に、API Key Authenticationを試しました。 https://designkojo.com/post-drupal-using-jsonapi-vuejs-front-end API Key Authentication 以下のモジュールを使用しました。 https://www.drupal.org/project/key_auth ユーザの編集画面に「Key authentication」というタブが表示され、APIキーを生成できました。 APIキーを使用する場合には、以下のようなプログラムで実行することができました。 import requests endpoint = 'http://{ipアドレス or ドメイン名}/jsonapi/node/article' key = '{APIキー}' headers = { 'Accept': 'application/vnd.api+json', 'Content-Type': 'application/vnd.api+json', "api-key": key } payload = { "data": { "type": "node--article", "attributes": { "title": "What's up from Python", "body": { "value": "Be water. My friends.", "format": "plain_text" } } } } r = requests.post(endpoint, headers=headers, json=payload) r.json() 多言語対応における注意点 注意点として、翻訳データの作成はできないようでした。 https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/translations 作成済みの翻訳データの更新は可能ですが、翻訳データがないノードに対しては、以下のエラーが発生しました。 { "jsonapi": { "version": "1.0", "meta": { "links": { "self": { "href": "http://jsonapi.org/format/1.0/" } } } }, "errors": [ { "title": "Method Not Allowed", "status": "405", "detail": "The requested translation of the resource object does not exist, instead modify one of the translations that do exist: ja." } ] } この点について、既に対応策ができているかもしれません。引き続き調査したいと思います。 ...

Wagtailを試す

Wagtailを試す

概要 Wagtailを試してみましたので、躓いた点などの備忘録です。 基本的には、以下のチュートリアルを参考に進めました。 https://docs.wagtail.org/en/v5.0.1/getting_started/tutorial.html 検索機能 「はじめての記事」という日本語のタイトルを持つページを追加した際、以下ではヒットしませんでした。 http://localhost:8000/admin/pages/search/?q=はじめて 一方、以下ではヒットしました。日本語の部分一致検索はデフォルトではできないようでした。 http://localhost:8000/admin/pages/search/?q=はじめての記事 Wagtail API APIについては、以下に記載がありました。 https://docs.wagtail.org/en/v5.0.1/advanced_topics/api/index.html 上記のサイトを参考に、rest_frameworkも追加することで、以下のように結果を得ることができました。 ただし、localhost:8000で立ち上げているアプリに対して、得られる結果のホスト名がlocalhostになっていました。 この点については、以下の記事を参考に、管理画面から修正できました。 https://stackoverflow.com/questions/52540254/edit-approved-email-points-to-localhost 具体的には、以下の/admin/sites/のページで、ポート番号を変更しました。 ?searchパラメータ 先の検索機能と同様、日本語については完全一致が必要なようでした。 http://localhost:8000/api/v2/pages/?search=はじめての記事 Elasticsearch Elasticsearchとの連携を試みました。 https://docs.wagtail.org/en/v5.0.1/topics/search/backends.html 今回はawsのopensearchを試してみましたが、以下のようなエラーが出てしまいました。 elasticsearch.exceptions.UnsupportedProductError: The client noticed that the server is not Elasticsearch and we do not support this unknown product 以下で同様のissueが上がっていましたが、現時点ではまだ未対応のようでした。 https://github.com/wagtail/wagtail/issues/7920 まとめ 誤った内容も含まれているかもしれませんが、Wagtailの利用にあたり、参考になりましたら幸いです。

Django REST framework JSON:API(DJA)に独自のモデルのビューをカスタマイズする

Django REST framework JSON:API(DJA)に独自のモデルのビューをカスタマイズする

概要 以下の記事で追加したモデルのビューをカスタマイズしてみます。 sort ordering_fieldsを追加してみます。 ... class UserInfoViewset(ModelViewSet): ordering_fields = ("user_name", ) # ここを追加 queryset = UserInfo.objects.all() serializer_class = UserInfoSerializer def get_object(self): entry_pk = self.kwargs.get("entry_pk", None) if entry_pk is not None: return Entry.objects.get(id=entry_pk).blog return super().get_object() ... 結果、「Filters」の表示で、user_nameのみが選択できるようになりました。 例えば、ageでソートを行うと、validation errorが返却されました。 フィルタ ... class UserInfoViewset(ModelViewSet): queryset = UserInfo.objects.all() serializer_class = UserInfoSerializer ordering_fields = ("user_name", ) # ここから下を追加 # override the default filter backends in order to test QueryParameterValidationFilter # without breaking older usage of non-standard query params like `page_size`. filter_backends = ( QueryParameterValidationFilter, OrderingFilter, DjangoFilterBackend, SearchFilter, ) rels = ( "exact", "iexact", "contains", "icontains", "gt", "gte", "lt", "lte", "in", "regex", "isnull", ) filterset_fields = { "id": ("exact", "in"), "user_name": rels } search_fields = ("user_name", ) ... ... 上記により、以下のようなフィルタが可能になりました。 ...

Django REST framework JSON:API(DJA)に独自のモデルを追加する

Django REST framework JSON:API(DJA)に独自のモデルを追加する

概要 以下の記事で、Django REST framework JSON:API(DJA)の基本的な操作方法を確認しました。 本記事では、DJAに独自のモデルを追加してみます。 参考 以下の記事を参考に、UserInfoモデルを追加してみます。 https://tech-blog.rakus.co.jp/entry/20220329/python 手順 モデルを定義 以下を追記します。 # ユーザ情報を格納する class UserInfo(BaseModel): user_name = models.CharField(verbose_name='ユーザ名',max_length=32) # ユーザ名 birth_day = models.DateField(verbose_name='生年月日') # 生年月日 age = models.PositiveSmallIntegerField(verbose_name='年齢',null=True,unique=False) # 年齢 created_at = models.DateTimeField(verbose_name='作成日時',auto_now_add=True) データベースを構築 以下を実行します。 % django-admin makemigrations --settings=example.settings Migrations for 'example': example/migrations/0013_userinfo.py - Create model UserInfo % django-admin migrate --settings=example.settings Operations to perform: Apply all migrations: auth, contenttypes, example, sessions, sites Running migrations: Applying example.0013_userinfo... OK 参考までに、以下のようなファイルが作成されます。 # Generated by Django 4.1.8 on 2023-06-04 17:35 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ("example", "0012_author_full_name"), ] operations = [ migrations.CreateModel( name="UserInfo", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ("modified_at", models.DateTimeField(auto_now=True)), ("user_name", models.CharField(max_length=32, verbose_name="ユーザ名")), ("birth_day", models.DateField(verbose_name="生年月日")), ("age", models.PositiveSmallIntegerField(null=True, verbose_name="年齢")), ( "created_at", models.DateTimeField(auto_now_add=True, verbose_name="作成日時"), ), ], options={ "abstract": False, }, ), ] コンポーネントの作成 Serializer 以下を追記します。 ...

Django REST framework JSON:API(DJA)を試す

Django REST framework JSON:API(DJA)を試す

概要 Django REST framework JSON:API(DJA)を試す機会がありましたので、その備忘録です。 https://django-rest-framework-json-api.readthedocs.io/en/stable/index.html インストール 以下のページに記載があるexample appを起動します。 https://django-rest-framework-json-api.readthedocs.io/en/stable/getting-started.html git clone https://github.com/django-json-api/django-rest-framework-json-api.git cd django-rest-framework-json-api python3 -m venv env source env/bin/activate pip install -Ur requirements.txt django-admin migrate --settings=example.settings django-admin loaddata drf_example --settings=example.settings django-admin runserver --settings=example.settings 結果、以下の画面などが得られました。 http://localhost:8000 for the list of available collections (in a non-JSON:API format!), http://localhost:8000/swagger-ui/ for a Swagger user interface to the dynamic schema view, or http://localhost:8000/openapi for the schema view’s OpenAPI specification document. ...

IIIFマニフェストファイルからPDFファイルを作成する

IIIFマニフェストファイルからPDFファイルを作成する

概要 IIIFマニフェストファイルからPDFファイルを作成する機会がありました。このソリューションとして、以下のリポジトリが見つかりましたが、うまく動かすことができませんでした。 https://github.com/jbaiter/pdiiif そこで、上記リポジトリはJavaScriptを使用していますが、今回はPythonを用いた変換ツールを作成しました。 使い方 以下のノートブックからお試しいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/iiif2pdf.ipynb 初回インストール時に、img2pdfをインストールしますが、PILのバージョンの関係で、「RESTART RUNTIME」ボタンが表示されますので、クリックの上、再度同じセルを実行してください。 オプションとして、「IIIFマニフェストURLの指定」「画像が格納されているフォルダのパスの指定」「ローカルに存在するIIIFマニフェストファイルのパスの指定」の3種類を用意しています。 注意点として、2023年5月末時点では、IIIF Presentation API v2にのみ対応しています。v3へは今後の対応を検討しています。 まとめ IIIFからのPDFファイルの作成にあたり、参考になりましたら幸いです。

JPCOARスキーマ(v1)を用いたxmlファイルのバリデーションツールの試作

JPCOARスキーマ(v1)を用いたxmlファイルのバリデーションツールの試作

以前に以下の記事を執筆しました。JPCOARスキーマを用いたxmlファイルのバリデーションを試しました。 今回は、上記の記事での検証を元に、Google Colabを用いた検証ツールを作成しました。以下のURLからお試しいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/JPCOARスキーマ_v1を用いたxmlファイルのバリデーション.ipynb 公開済みのxmlファイルのURLを指定する、またはローカルファイルをアップロードすることで、対象ファイルのバリデーションを行うことができます。 JPCOARスキーマ(v1)を用いたxmlファイルの作成にあたり、参考になりましたら幸いです。

Google Colabを用いたNDL古典籍OCRチュートリアルの不具合の修正および機能追加を行いました。

Google Colabを用いたNDL古典籍OCRチュートリアルの不具合の修正および機能追加を行いました。

概要 以下の記事で紹介している、Google Colabを用いたNDL"古典籍"OCRアプリのチュートリアルを作成しています。 今回、以下の更新を行いました。 利用条件の追加 不具合の修正 IIIF Presentation API v3のマニフェストファイルの入力への対応 更新したノートブックは、これまでと同じ以下のURLでアクセスいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/NDL古典籍OCRの実行例.ipynb 利用条件の追加 ノートブック自体はCC0でご利用ください。ただし、「NDL古典籍OCRアプリケーション」は国立国会図書館がCC BY 4.0ライセンスで公開するものですので、クレジットの表示をお願いいたします。また、OCR適用対象の資料の利用条件などについても、それぞれご確認ください。 不具合の修正 OCR結果が出力されない不具合が発生していました。また、ライブラリのインストールにも長い時間がかかるようになっていました。これらの2点を修正しています。 IIIF Presentation API v3のマニフェストファイルの入力への対応 これまで、IIIF Presentation API v2のマニフェストファイルの入力のみに対応していました。 今回、v3への対応を行いました。この検証にあたり、以下の記事で紹介したIIIF Presentation API v3のマニフェストファイルを使用しました。 まとめ この間、不具合が発生しており申し訳ありません。NDL古典籍OCRの活用に役立つことができれば幸いです。

Pythonを使ってDrupalのタクソノミーの登録とコンテンツへの追加

Pythonを使ってDrupalのタクソノミーの登録とコンテンツへの追加

概要 以下のシリーズの続きです。 今回は、タクソノミーの登録とコンテンツへの追加を行います。 タクソノミーの登録 事前に、ne_classというタクソノミーをGUIを通じて作成しました。以下のようなURLで一覧できます。 /jsonapi/taxonomy_term/ne_class 以下、新しいタクソノミーを登録するプログラムです。host, username, passwordは適宜設定してください。 payload = { "data": { "type": "taxonomy_term--ne_class", "attributes": { "name": "干瀬", } } } _type = "ne_class" url = f"{host}/jsonapi/taxonomy_term/{_type}" r = requests.post(url, headers=headers, auth=(username, password), json=payload) r.json() 以下のような結果が得られます。 {'jsonapi': {'version': '1.0', 'meta': {'links': {'self': {'href': 'http://jsonapi.org/format/1.0/'}}}}, 'data': {'type': 'taxonomy_term--ne_class', 'id': '17c70bd6-e6fc-46e2-bb5d-2377ba9c8ab8', ... コンテンツへの追加 事前に、PlaceというコンテンツタイプをGUIを通じて作成しました。また、field_ne_classを作成して、上記のタクソノミーne_classを値の候補として設定しました。 relationshipsのidに先程取得したタクソノミーのidを指定しています。 payload = { "data": { "type": "node--place", "attributes": { "title": "xxx" }, "relationships": { "field_ne_class": { "data": { "type": "taxonomy_term--ne_class", "id": "17c70bd6-e6fc-46e2-bb5d-2377ba9c8ab8", } } } } } _type = "place" url = f"{host}/jsonapi/node/{_type}" r = requests.post(url, headers=headers, auth=(username, password), json=payload) r.json() まとめ タクソノミーの追加やコンテンツへの関連付けも機械的に行うことができそうです。他のよりよい方法もあるかと思いますが、参考になりましたら幸いです。 ...

Pythonを使ってDrupalのコンテンツを更新・削除する

Pythonを使ってDrupalのコンテンツを更新・削除する

概要 以下の記事で、コンテンツの新規登録の方法を記載しました。 今回は、既存のコンテンツの更新・削除を試みます。 アイテムの絞り込み 以下のようなプログラムにより、登録済みのコンテンツを取得することができます。今回は、titleが「更新前のタイトル」のコンテンツを取得しました。res["data"]は配列になります。 username = "xxx" password = "xxx" host = "xxx" query = { "title": "更新前のタイトル" } item_type = "article" filters = [] for key, value in query.items(): filters.append(f'filter[{key}]={value}') filter_str = '&'.join(filters) endpoint = f'{host}/jsonapi/node/{item_type}?{filter_str}' r = requests.get(endpoint, headers=headers, auth=(username, password)) res = r.json() len(res['data']) 更新対象のコンテンツのID取得 730f844d-b476-4485-8957-c33fccb7f8acのようなIDが得られます。 item = res['data'][0] item_id = item['id'] 更新 typeとidを指定して更新します。 ...

Pythonを使ってDrupalにコンテンツを追加する

Pythonを使ってDrupalにコンテンツを追加する

概要 Pythonを使ってDrupalにコンテンツを追加する機会がありましたので、その備忘録です。以下の記事を参考にしました。 https://weimingchenzero.medium.com/use-python-to-call-drupal-9-core-restful-api-to-create-new-content-9f3fa8628ab4 Drupalの準備 Amazon Lightsailに作成しました。以下の記事などが参考になります。 https://annai.co.jp/article/use-aws-lightsail モジュール 以下をインストールします。 HTTP Basic Auth JSON:API RESTful Web Services Serialization JSON:APIの設定変更 以下にアクセスして、設定を変更します。 </admin/config/services/jsonapi> Python {ipアドレス or ドメイン名}、{パスワード}を適宜設定してください。 Amazon Lightsailの場合、初期ユーザ名はuserです。またパスワードは以下のコマンドで確認します。 cat ~/bitnami_application_password import requests from requests.auth import HTTPBasicAuth endpoint = 'http://{ipアドレス or ドメイン名}/jsonapi/node/article' u = 'user' p = '{パスワード}' headers = { 'Accept': 'application/vnd.api+json', 'Content-Type': 'application/vnd.api+json' } payload = { "data": { "type": "node--article", "attributes": { "title": "What's up from Python", "body": { "value": "Be water. My friends.", "format": "plain_text" } } } } r = requests.post(endpoint, headers=headers, auth=(u, p), json=payload) r.text その他 以下のようにnote_typeの登録も試みました。 payload = { "data": { "type": "node_type--node_type", "attributes": { "title": "テスト", "description": "node_typeのテストです。" } } } url = f"{host}/jsonapi/node_type/node_type" r = requests.post(url, headers=headers, auth=(username, password), json=payload) r.json() 結果、以下のように、Method Not Allowedとなりました。 ...

ExcelからRDFを作成する

ExcelからRDFを作成する

概要 RDFデータの作成にあたり、Excelで作成したデータから、RDFデータに変換するPythonライブラリを試作しました。まだまだ中途半端な状態ですが、備忘録です。 ノートブック 以下のノートブックから試用いただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/ExcelからRDFデータを作成する.ipynb 変換元のExcelデータ 以下のようなExcelファイルを作成します。 https://docs.google.com/spreadsheets/d/16SufG69_aZP0u0Kez8bisImGvVb4-z990AEPesdVxLo/edit#gid=0 上記の例では、「prefix」という名前のシートに、使用するprefixの情報をまとめています。 また、「target」というシートに、具体的なデータを入力しています。Omeka SのBulk Importの仕様を参考にして、言語ラベル「@ja」や、type「^^uri」などを指定します。 上記のデータの作成方法については、改めて説明ページを用意したいと思います。 変換処理 上記のノートブックを参考にしてください。prefixの情報を格納したシートと、処理対象のデータを含むシートを指定して、RDFデータへの変換処理を実施します。 まとめ 同様のニーズに答える既存のツールが多々あるかと思いますが、参考になりましたら幸いです。

TEI/XMLファイルからrespStmtのnameの値を抽出する方法(GPT-4による解説)

TEI/XMLファイルからrespStmtのnameの値を抽出する方法(GPT-4による解説)

TEI/XMLファイルからrespStmtのnameの値を抽出する方法: PythonでBeautifulSoupとElementTreeを使ったアプローチ この記事では、PythonのBeautifulSoupとElementTreeを使って、TEI/XMLファイルからrespStmtのnameの値を抽出する方法を紹介します。 方法1: ElementTreeを使う まず、Pythonの標準ライブラリであるxml.etree.ElementTreeを使って、respStmtのnameの値を抽出します。 import xml.etree.ElementTree as ET # XMLファイルを読み込む tree = ET.parse('your_file.xml') root = tree.getroot() # 名前空間を定義 ns = {'tei': 'http://www.tei-c.org/ns/1.0'} # respStmtのnameの値を抽出 name = root.find('.//tei:respStmt/tei:name', ns) # nameのテキストを表示 if name is not None: print(name.text) else: print("nameタグが見つかりませんでした。") 方法2: BeautifulSoupを使う 次に、BeautifulSoupを使って、respStmtのnameの値を抽出します。まず、beautifulsoup4とlxmlライブラリがインストールされていることを確認してください。インストールされていない場合は、以下のコマンドでインストールできます。 pip install beautifulsoup4 lxml 以下のコードで、BeautifulSoupを使ってrespStmtのnameの値を抽出できます。 from bs4 import BeautifulSoup # XMLファイルを読み込む with open('your_file.xml', 'r', encoding='utf-8') as file: content = file.read() # BeautifulSoupオブジェクトを作成 soup = BeautifulSoup(content, 'lxml-xml') # respStmtのnameの値を抽出 name = soup.find('respStmt').find('name') # nameのテキストを表示 if name: print(name.text) else: print("nameタグが見つかりませんでした。") どちらの方法でも、respStmtのnameの値をPythonで簡単に抽出することができます。あなたのプロジェクトに適した方法を選んでください。

nbdevを使用する際の備忘録

nbdevを使用する際の備忘録

概要 Pythonでパッケージを作成する際、nbdevを使用しています。 https://nbdev.fast.ai/ nbdevは以下のように説明されています。 Write, test, document, and distribute software packages and technical articles — all in one place, your notebook. (機械翻訳) ソフトウェア パッケージや技術記事の作成、テスト、文書化、配布をすべて 1 か所のノートブックで行います。 本記事では、nbdevを使用する際の備忘録です。 インストール 以下のチュートリアルのページが参考になります。 https://nbdev.fast.ai/tutorials/tutorial.html 以下、かいつまんで流れを説明します。 関連するツールをインストールした後、GitHubリポジトリを作成し、クローンした先で以下を実行します。 nbdev_new その後、以下も実行しておきます。 nbdev_install_hooks そしてnbsフォルダの中の00_core.ipynbなどを編集して、本ノートブックの最後のセルにある以下を実行します。 import nbdev; nbdev.nbdev_export() その結果、Pythonモジュールが自動的に作成されます。 パッケージをインストールする 同一フォルダ内 以下を実行します。 pip install -e '.[dev]' 別のフォルダから 一例ですが、絶対パスを指定してインストールします。 例: /Users/hogehoge/tei_xml_tools の場合 pip install -e /Users/hogehoge/tei_xml_tools -eオプションを付けることで、開発中にパッケージに加えられた変更をすぐに使用できます。 ライブラリの使用 以下のように%を使用することで、開発中の内容を反映することができました。 # %load_ext autoreload %reload_ext autoreload %autoreload 2 from tei_xml_tools.core import * まとめ その他、ドキュメントのプレビューやpypiにアップロードを行うためのコマンドも提供されています。機会があれば、nbdevの使い方全般についても記事にしたいと思います。

IIIF Image API level 0による画像公開方法

IIIF Image API level 0による画像公開方法

概要 IIIF Image API level 0は、事前に作成した静的なタイル画像を用いて画像配信を行います。これにより、GitHub PagesやAmazon S3といった静的ファイルのホスティングサービスのみでの画像公開が可能となります。一方、任意の範囲の画像切り出しができないといった欠点も挙げられます。 本記事は、IIIF Image API level 0を用いた画像公開の一例について紹介します。 ツール 以下のノートブックでお試しいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/IIIF_Image_API_静的ファイル作成ツール.ipynb 本ノートブックは、以下のスクリプトを参考にしています。 https://github.com/zimeon/iiif/blob/main/iiif_static.py 公開例 GitHub Pagesで公開するタイル画像を表示している例です。 https://www.kanzaki.com/works/2016/pub/image-annotator?u=https://nakamura196.github.io/iiif_static/files/tile/kunshujo/info.json まとめ 静的なファイルのみでIIIF Image API(のlevel 0)に対応する方法について紹介しました。 本手法の利点と欠点を考慮したうえで、ご活用いただけますと幸いです。

Google Colabを用いたNDL

Google Colabを用いたNDL

概要 Google Colabを用いたNDL"古典籍"OCRアプリを作成しました。以下のURLからお試しいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/NDL古典籍OCRの実行例.ipynb NDL古典籍OCRの説明は以下です。 https://github.com/ndl-lab/ndlkotenocr_cli また、ノートブックの作成にあたっては、@blue0620さんのノートブックを参考にしています。ありがとうございます! https://twitter.com/blue0620/status/1617888733323485184 今回作成したノートブックでは、入力フォーマットの追加や、Googleドライブへの保存機能などを追加しています。 使い方 NDLOCRアプリの使い方とほぼ同様です。以下の動画を参考にしてください。 https://youtu.be/46p7ZZSul0o 工夫 工夫した点として、認識結果をIIIFマニフェストの形に変換し、Miradorビューアで閲覧できるようにしました。具体的には、以下のような出力が得られます。 後者のリンクをクリックすることで、以下のようなMiradorビューアが表示され、認識結果を確認することができます。 このIIIFマニフェストファイルも、Googleドライブに格納しています。 参考 NDLOCRのチュートリアルについては、以下を参考にしてください。

JPCOARスキーマを用いたxmlファイルのバリデーション

JPCOARスキーマを用いたxmlファイルのバリデーション

概要 JPCOARスキーマでは、XMLスキーマ定義を以下のリポジトリで公開してくださっています。スキーマの作成およびデータの公開を行っていただき、ありがとうございます。 https://github.com/JPCOAR/schema 本記事では、上記のスキーマを使ったxmlファイルのバリデーションを試してみたので、その備忘録です。(今回のようなバリデーションは初めてのため、不正確な用語や情報を含む可能性があります。申し訳ありません。) Google Colabのノートブックも用意しました。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/JPCOARスキーマを用いたxmlファイルのバリデーション.ipynb 準備 リポジトリのクローン cd /content/ git clone https://github.com/JPCOAR/schema.git ライブラリのインストール pip install xsd-validator xsdファイルのロード(v1) from xsd_validator import XsdValidator validator = XsdValidator('/content/schema/1.0/jpcoar_scm.xsd') v1を試す OKな例 <?xml version="1.0" ?> <jpcoar:jpcoar xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:jpcoar="https://github.com/JPCOAR/schema/blob/master/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://github.com/JPCOAR/schema/blob/master/1.0/jpcoar_scm.xsd"> <dc:title>JPCOARスキーマを用いたxmlファイルのバリデーション</dc:title> <dc:type rdf:resource="http://purl.org/coar/resource_type/c_6501">article</dc:type> </jpcoar:jpcoar> validator.assert_valid("/content/ok.xml") # エラーなし NGな例 dc:typeの後にjpcoar:subjectを置くことによるエラー? <?xml version="1.0" ?> <jpcoar:jpcoar xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:jpcoar="https://github.com/JPCOAR/schema/blob/master/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://github.com/JPCOAR/schema/blob/master/1.0/jpcoar_scm.xsd"> <dc:title>JPCOARスキーマを用いたxmlファイルのバリデーション</dc:title> <dc:type rdf:resource="http://purl.org/coar/resource_type/c_6501">article</dc:type> <jpcoar:subject subjectScheme="Other">テスト</jpcoar:subject> </jpcoar:jpcoar> validator.assert_valid("/content/ng.xml") XsdValidationErrorWithInfo: /content/ng.xml: line 9 column 41: cvc-complex-type.2.4.a: Invalid content was found starting with element ‘{"https://github.com/JPCOAR/schema/blob/master/1.0/":subject}’. One of ‘{"https://schema.datacite.org/meta/kernel-4/":version, “http://namespace.openaire.eu/schema/oaire/":version, “https://github.com/JPCOAR/schema/blob/master/1.0/":identifier, “https://github.com/JPCOAR/schema/blob/master/1.0/":identifierRegistration, “https://github.com/JPCOAR/schema/blob/master/1.0/":relation, “http://purl.org/dc/terms/":temporal, “https://schema.datacite.org/meta/kernel-4/":geoLocation, “https://github.com/JPCOAR/schema/blob/master/1.0/":fundingReference, “https://github.com/JPCOAR/schema/blob/master/1.0/":sourceIdentifier, “https://github.com/JPCOAR/schema/blob/master/1.0/":sourceTitle, “https://github.com/JPCOAR/schema/blob/master/1.0/":volume, “https://github.com/JPCOAR/schema/blob/master/1.0/":issue, “https://github.com/JPCOAR/schema/blob/master/1.0/":numPages, “https://github.com/JPCOAR/schema/blob/master/1.0/":pageStart, “https://github.com/JPCOAR/schema/blob/master/1.0/":pageEnd, “http://ndl.go.jp/dcndl/terms/":dissertationNumber, “http://ndl.go.jp/dcndl/terms/":degreeName, “http://ndl.go.jp/dcndl/terms/":dateGranted, “https://github.com/JPCOAR/schema/blob/master/1.0/":degreeGrantor, “https://github.com/JPCOAR/schema/blob/master/1.0/":conference, “https://github.com/JPCOAR/schema/blob/master/1.0/":file}’ is expected. ...

RELAX NGスキーマを操作するライブラリjingtrangを試す:rngファイルの作成編

RELAX NGスキーマを操作するライブラリjingtrangを試す:rngファイルの作成編

概要 以下の記事で、jingtrangおよびrngファイルを用いたxmlファイルの検証を行いました。 このjingtrangライブラリでは、xmlファイルからrngファイルを作成できるということで、試してみます。 Google Colabのノートブックも用意しました。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/jingtrangを試す:作成編.ipynb rngファイルを作成する rngファイルを作成する元ファイルとして、以下を用意しました。 <root><title>aaa</title></root> 上記のファイルに対して、以下を実行します。 pytrang base.xml base.rng 結果、以下のファイルが作成されました。 <?xml version="1.0" encoding="UTF-8"?> <grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <start> <element name="root"> <element name="title"> <data type="NCName"/> </element> </element> </start> </grammar> このrngファイルに対して、以下のようにテストしてみました。 OK:テキストが異なるもの <root><title>bbb</title></root> pyjing base.rng ex1.xml NG:titleがない <root><aaa>bbb</aaa></root> pyjing base.rng ex2.xml /content/ex2.xml:1:12: error: element "aaa" not allowed anywhere; expected element "title" /content/ex2.xml:1:28: error: element "root" incomplete; missing required element "title" NG: 属性がある <root><title lang="en">aaa</title></root> pyjing base.rng ex3.xml /content/ex3.xml:1:24: error: found attribute "lang", but no attributes allowed here まとめ 上記のような形で、あるxmlファイルから、rngファイルを作成することができました。rngファイルの記述方法についてはさらなる勉強が必要ですが、今回のような具体例から試行錯誤ができる仕組みは有効かと思います。 ...

RELAX NGスキーマを操作するライブラリjingtrangを試す:検証編

RELAX NGスキーマを操作するライブラリjingtrangを試す:検証編

概要 あるスキーマに従ったXMLファイルを作成する機会があったのですが、そのスキーマに合致したXMLファイルを作成できているか、確認する必要がありました。 上記の要件に対して、RELAX NGスキーマを操作するライブラリjingtrangを使ってみましたので、その備忘録です。 https://pypi.org/project/jingtrang/ Google Colabのノートブックも用意しました。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/jingtrangを試す.ipynb Validationを試す # ライブラリのインストール pip install jingtrang # rngファイルのダウンロード(tei_allを使用) wget https://raw.githubusercontent.com/nakamura196/test2021/main/tei_all.rng # validation対象のXMLファイルの用意(校異源氏物語テキストのダウンロード) wget https://kouigenjimonogatari.github.io/tei/01.xml OKな例 以下のように実行すると、何も出力されませんでした。 pyjing tei_all.rng 01.xml NGな例 一方、TEIのスキーマに合致しない以下のようなxmlファイルを用意しました。 <a>bbb</a> その実行結果は以下です。a要素ではなく、TEIまたはteiCorpus要素が必要と出力されました。このように、スキーマに合致するか否かのチェックができました。 pyjing tei_all.rng ng.xml /content/ng.xml:1:4: error: element "a" not allowed here; expected element "TEI" or "teiCorpus" (with xmlns="http://www.tei-c.org/ns/1.0") まとめ 無事に検証を行うことができました。 ただ今回のニーズはTEI/XMLの以外のスキーマに適合するかを検証する必要がありましたので、このrngファイルの作成方法や内容について、別の記事にまとめたいと思います。

WordをTEI/XMLに変換する

WordをTEI/XMLに変換する

概要 WordをTEI/XMLファイルに変換する機会がありました。調べてみたところ、TEIGarage ConversionなどのTEI公式のツールに加えて、以下のTEI Publisherでの変換例が見つかりました。 https://teipublisher.com/exist/apps/tei-publisher/test/test.docx.xml 上記の例では、Wordのスタイル情報を中心に、TEIのタグに変換しているようだったので、この方法を試してみました。なお今回は、TEI Publisherとは独立して使用することを目的として、python-docxライブラリを使用しました。 Wordファイル 以下のようなWordファイルを試作しました。いずれも仮ですが、「tei:persName」や「tei:warichu」といったスタイルを作成し、色などのスタイルを変更しました。スタイルを当てていくことで、簡易な構造化を行う仕組みです。 TEI/XMLへの変換 上記のようなWordファイルを入力として、スタイル情報を中心に、TEI/XMLに変換するスクリプトを作成しました。いずれpipなどを使って共有したいと考えています。 変換したTEI/XMLの例は以下です。まだまだ改善が必要ですが、validなTEI/XMLファイルに変換することができました。 <lb/> <seg> ワードの入力サンプル </seg> <lb/> <lb/> <seg type="dateline"> 日付の行にスタイル「dateLine」を使用してください。先頭に2文字の空白が入ります。 </seg> <lb/> <seg type="personline"> 名前の行にスタイル「personLine」を使用してください。末尾に2文字の空白が入ります。 </seg> <lb/> <seg> <ruby> <rb> 中村 </rb> <rt> なかむら </rt> <rt place="left"> さとる </rt> </ruby> の形で両側ルビを記述します。緑色が左ルビです。 </seg> <lb/> <lb/> <seg> <seg type="red"> 朱書 </seg> はスタイル「 <seg type="red"> red </seg> 」を使用してください。 </seg> <lb/> <lb/> <seg> 文字のサイズについては検討中です。 </seg> <lb/> <lb/> <seg> <persName> 中村覚 </persName> のような人名には、スタイル「 <persName> persName </persName> 」を使用してください。 </seg> <lb/> <lb/> <seg> 割注は <note type="割書"> あああああ <milestone unit="wbr"/> いいい </note> のように入力してください。正しく改行されるまで、全角スペースを入力してください。 <note type="割書"> こんな <milestone unit="wbr"/> スタイル </note> もあります。「こんな」の後に全角スペースを入れています。 </seg> <lb/> <lb/> <seg type="dateline"> 二〇二三年一月十七日 </seg> <lb/> <seg type="personline"> 作成:中村覚 </seg> <lb/> 別途開発中のTEI/XMLビューアで表示した例が以下です。<rt place="left">や朱書などのスタイルがまだ適用できていませんが、人名や割書などは再現することができました。 ...