無料のVisual Studio CodeとXML拡張機能でJATS XMLを編集する

JATS (Journal Article Tag Suite)のXML文書(学術情報XML[^xspa-JATS])を、無料のVisual Studio Code (VSCode)と無料の拡張機能XML[^RedHatXML] (以下、vscode-xml)を使って編集するときに、気になる次の~~3~~ 4つについて:

- バリデーション(validate、妥当性検証)
- コード補完(code completion)
- 外部実体(external entity)の解決
- ワークフロー

まず大事な外部実体の解決から。

## 外部実体の解決

J-STAGE[^jstage-manual]では、DOCTYPE宣言を次の固定値としていて、つまりDTDがJ-STAGEドメインのリモートにあるという前提です:

```xml
<!DOCTYPE article PUBLIC " -//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.1 20151215//EN " " https://www.jstage.jst.go.jp/dtds/1.1/JATS-journalpublishing1.dtd ">
```

J-STAGEのDTDや、DTDの内部で展開されるパラメーター実体(parameter entity、パラメーター・エンティティ)はリモートにあります。そこで、

- vscode-xmlの`xml.validation.resolveExternalEntities`を`true`に設定します[^vscode-xml-resolve-external-entity] (図参照)
- 信頼できるワークスペースで作業します。「このフォルダー内のファイルの作成者を信頼しますか？」に「はい、作成者を信頼します」と答えます
- J-STAGEがメンテナンス中だとDTDを取得できません(^_^;) (図参照)

**図** `xml.validation.resolveExternalEntities`を`true`に設定

![xml-setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/e4eb0eab-b0d9-4954-a33d-2ee9314ba06d.png)

![resolve-external-entities.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/c73689b2-f693-436c-b76f-0fe506f59caa.png)

**図** DTDを読み込めない例
![jstage-maintenance.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/2fe83b72-2cda-4957-8c47-7e7ea106486d.jpeg)


`xml.validation.resolveExternalEntities`の初期値は`false`になっていて、そのままだと、DTDは読み込むのですが、DTDが参照してる別ファイル内のパラメーター実体の宣言などが読み込まれません。JATSでは、こういった芋づる式に読み込まれるファイルが59個あるようです。

DTDなどを読み込めないと次の不都合が起きます:

- JATS XML文書がバリデーションでエラーになります
- DTDに基づいたコード補完[^vscode-xml-completion]が効きません。コード補完は便利です、挿入可能なタグや属性名の候補を出してくれますから(後述)

初期値で外部実体を解決しないという設定は、vscode-xmlに限らずXMLを扱うツール全般に言えることです。XML外部実体攻撃[^xxe-atack]を警戒してるのだと思います。

## バリデーション

設定したDTDに対して妥当性を検証して、問題のあるところには赤い波線が表示されて、その波線にカーソルを置くと、問題の内容や参考ページへのリンクが表示されます。図では`journal-meta`要素の中が空っぽなので怒られてます。

**図** 問題のあるところに赤い波線
![validation1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/180d91d1-acc9-47b4-bfa6-91bd262b6f20.png)

バリデーションを手動でトリガーできます。Visual Studio Codeのコマンド パレット[^command-palette]を開いて、`xml: re`とタイプして`XML: Revalidate current XML file`を選ぶと、今開いてるXML文書をバリデートできます。

**図** 開いてるXML文書を手動でバリデート
![revalidate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/8dcb2ffb-70e6-4718-9197-34f82b3b8d35.png)


## コード補完

DTDがあると、カーソル位置に挿入できる要素や属性を補完してくれます。

### 要素のコード補完

次の図は、`article`要素の配下で`<`と打ち込んだところで、そこに挿入できる要素の候補が表示されてます。

**図** DTDに基づいて入力できる要素を表示
![code-completion-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/1c3fe975-a00d-4a1f-b29b-8358d5be74df.png)

### 属性のコード補完

属性もコード補完されます。図は、`contrib`要素のタグの中で`c`とタイプしたところで、設定できる属性の候補が表示されます。`c`とタイプしたからといって、`c`で始まる属性名だけ表示されるわけではありません。

![code-completion-attribute.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/1e7d0e41-7763-41f6-8dbb-b737147afd7a.png)

### Copilotのコード提案

生成AIのCopilotの機能だと思うのですが、要素の配下やタグの中にカーソルを置いて時間が経つと、そこから続くコードが提案されます[^copilot]。図は`front`要素の配下にカーソルを置いて少し経ったところで、`front`配下の構造の提案されてます。ここで`TAB`キーを押すと、これらが確定します。これがDTDに基づいて妥当なのか…は、ちょっと分からないですが、確定したらバリデートされるので、問題あれば分かりますね。

![copilot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3930858/53947a69-80ba-4af3-8285-d72e8bfaea2c.png)

## ワークフロー

JATS XML文書をゼロから作成・編集することは、あまりないでしょう。たいていは、著者あるいは学会から入稿されたWord形式、LaTeX形式、あるいはHTML形式(後述)の査読・掲載決定済み原稿をツールでJATS XMLに変換するでしょう。そのJATS XMLを出発点として、DOIを追加したり、著者・所属をJATSの構造に構造化したり、参考文献を構造化したりするのではないでしょうか。特に、著者・所属や参考文献は細かくタグ付けされます。例えば、著者が`山田太郎、Jane Smith`なら、こんなふうに分解したりします:
```xml
<contrib-group>
  <contrib contrib-type="author">
    <name xml:lang="ja" name-style="eastern">
      <surname>山田</surname>
      <given-names>太郎</given-names>
    </name>
  </contrib>
  <contrib contrib-type="author">
    <name xml:lang="en" name-style="western">
      <surname>Smith</surname>
      <given-names>Jane</given-names>
    </name>
  </contrib>
</contrib-group>
```

この作業でCopilotのコード提案を利用すると、提案される範囲は限定的で、そんなに外れてないかも…やってみないと分かりませんが (^_^;)

VivliostyleではMarkdownで論文を書いて、所定の書式をCSSで指定して組版できます[^vivliostyle-gihyo]。組版の途中で生成されるHTML、あるいはWebPub[^vivliostyle-web]のHTML、あるいは元々のMarkdown形式で論文データを入稿するのもありかなと思うところです。gihyo.jpの記事のサンプルのHTMLを、JATS XML変換するサンプル・プログラムを作ってみました[^vivliostyle-jats]。この出力をVisual Studio Code + vscode-xmlで触ってみてください。


[^xspa-JATS]: JATS XMLとは - 学術情報XMLとは - 学術情報XML推進協議会 https://xspa.jp/what/jats/
[^RedHatXML]: XML Language Support by Red Hat https://marketplace.visualstudio.com/items?itemName=redhat.vscode-xml
[^vscode-xml-resolve-external-entity]: Resolve External Entities https://github.com/redhat-developer/vscode-xml/blob/main/docs/Validation.md#resolve-external-entities
[^vscode-xml-completion]: Completion based on DTD https://github.com/redhat-developer/vscode-xml/blob/f6aaeba81da7f74292e72341a09c4fe7bbc0df20/docs/Features/XMLFeatures.md#completion-based-on-dtd
[^jstage-manual]: J-STAGE全文 XML利用者向けマニュアルhttps://www.jstage.jst.go.jp/static/pages/GuidelineAndManuals/zenbun-xml-jats1_1-manual/-char/ja
[^xxe-atack]: XML外部実体攻撃 https://ja.wikipedia.org/wiki/XML%E5%A4%96%E9%83%A8%E5%AE%9F%E4%BD%93%E6%94%BB%E6%92%83
[^copilot]: GitHub Copilotを使用してIDEでコードの提案を取得する https://docs.github.com/ja/copilot/using-github-copilot/getting-code-suggestions-in-your-ide-with-github-copilot
[^command-palette]: GitHub Codespaces で Visual Studio Code のコマンド パレットを使う https://docs.github.com/ja/codespaces/reference/using-the-vs-code-command-palette-in-codespaces
[^vivliostyle-gihyo]: VFMで学会論文を書いてVivliostyleで組んで投稿する https://gihyo.jp/article/2025/02/vivliostyle-05
[^vivliostyle-web]: Web 出版物（WebPub）の出力 https://github.com/vivliostyle/vivliostyle-cli/blob/main/docs/ja/special-output-settings.md#web-%E5%87%BA%E7%89%88%E7%89%A9webpub%E3%81%AE%E5%87%BA%E5%8A%9B
[^vivliostyle-jats]: 論文ThemeのHTMLファイルをJATSに変換 https://yamahige.github.io/study/vivliostyle-theme-ipsj-tech-2-jats/index-google-xml-formatter.html