XBRLタクソノミの表示リンクをOSSのArrele APIを使ってたどってみよう

はじめまして、XBRLJapanの開発委員会のメンバーOです。

XBRLのタクソノミって有用な情報が含まれていますが細かく解析しようとするとなかなか大変ですよね。今回は、ArelleというOSSを使って、XBRLのタクソノミを利用する方法を紹介します。

#1 はじめに
過去の記事で、XBRLで公開された企業の財務情報から特定の科目を抽出する方法を紹介しました。
・[EDINET開示のXBRLデータから、平均給与等の従業員情報を自動で抽出してみよう(5/10)](https://qiita.com/XBRLJapan/items/b1e66f79d597df7b6037)

データとして取り出したい科目がわかっている場合、その科目の値を直接XBRLインスタンスから抽出することができます。

しかし、XBRLインスタンスには項目の値とそれに類する情報しか記載されていません。科目の定義や表示上の関係などは、XBRLタクソノミと呼ばれる科目の辞書に定義されています。

この記事では、XBRLタクソノミの表示リンク(Presentation Link)に含まれる構造関係を、ArelleのAPIを使って抽出してみます。

なお、XBRLの基本構造やXBRLタクソノミに関する説明は以下の記事に記載しておりますのでそちらをご覧ください。
・[XBRLをもっと知ろう(9/10)](https://qiita.com/XBRLJapan/items/81d965bb40b8170d9e7f)

# 2 事前準備
# 2.1 Arelleの準備
[Arelle](http://arelle.org/)と呼ばれるXBRLParserをインストールします。

インストール方法は以下の通りとなっております。
1. <https://github.com/Arelle/Arelle>からarelleのソースコードをダウンロード
2. ダウンロードしたソースコードに対してpathを通す

なお、他の記事を見るとpipコマンドを使用したインストールが紹介されておりますが、ArelleのAPIはpip非サポートとのことで、最新ではないとのことなので注意しましょう(開発元に確認済み)。pipでインストールしたものを使うと予期せぬエラーが出ることがあります。

## 2.2 XBRLデータのダウンロード
[EDINET](https://disclosure.edinet-fsa.go.jp/)から適当な企業の有価証券報告書をダウンロードしましょう。今回は某大手IT企業の2020年度の有価証券報告書を利用しています。


# 3 表示リンクの紹介
表示リンクには、ざくっと説明すると項目間の表示上の関係が定義されています。試しに上でダウンロードした有価証券報告書の連結経営指標等を見てみると、連結経営指標等に含まれる科目が一覧になっているのが見て取れると思います。以下の図がその例です。
![presentationLinkDetail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500494/17af6dc5-1a7d-8094-cb51-78291d82c8ef.png)
このような項目間の関係が拡張リンクロールと呼ばれるまとまりごとに定義されています。ちなみにorderは表示順、arcroleはどういう関係かを定義するための属性です。arcroleは図中ではpareht-childと表示されていますが、実際の値はhttp://www.xbrl.org/2003/arcrole/parent-childとなっており、親子関係であることを明示しています。

![presentationLink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500494/3ba3f349-38fc-d6e9-1fa4-6c90ff02aaf5.png)

この項目間の関係を解析することで、自動で表などを作成することが可能となります。

# 4 プログラム
連結経営指標等に定義されている項目の親子関係を辿るプログラムを紹介します。というわけでさっそくサンプルコードです。なお、ファイルパスなどは環境に合わせて適切な値を指定してください。

```python:Code
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from arelle import ModelManager
from arelle import Cntlr
from arelle import ModelDtsObject
from arelle import ModelValue
from arelle import XbrlConst

import sys

# 入力ファイルの指定 (ここにはダウンロードした有価証券報告書に含まれる.xbrlファイルを指定してください。
filePath = './data/sample.xbrl'

# 出力ファイルの指定
fo = open('./output.txt', 'w', encoding='utf-8')


# 再帰的に表示リンクをたどりながら出力する関数
def printLink(linkrole, modelObject, indent, relModels):
    
    indentStr = "  ";
    for i in range(indent):
        indentStr += "  ";
    
    for relModel in relModels.fromModelObject(modelObject):
        if relModel.linkrole == linkrole:
            print(indentStr, "from: ", relModel.fromModelObject.qname)
            print(indentStr, "to: ", relModel.toModelObject.qname)
            print("\n")
            # リンクを再帰的にたどる
            printLink(linkrole, relModel.toModelObject, indent+1, relModels)

sys.stdout = fo

ctrl = Cntlr.Cntlr()

# XBRLのモデルを作成
modelManager = ModelManager.initialize(ctrl)
modelXbrl = modelManager.load(filePath)

# presentationLinkのparentchildを取得
parentChilds = modelXbrl.relationshipSet(XbrlConst.parentChild)

# 今回は特定の拡張リンクロールを使う
targetLinkrole = "http://disclosure.edinet-fsa.go.jp/role/jpcrp/rol_BusinessResultsOfGroup"
rootElementName = "jpcrp_cor:BusinessResultsOfGroupHeading"

for i, modelObject in enumerate(modelXbrl.modelObjects):
    if type(modelObject) is ModelDtsObject.ModelConcept and str(modelObject.qname) == rootElementName:
        print(modelObject.qname)
        printLink(targetLinkrole, modelObject, 0, parentChilds)


```

結果は以下の通り。

```:Result
jpcrp_cor:BusinessResultsOfGroupHeading
   from:  jpcrp_cor:BusinessResultsOfGroupHeading
   to:  jpcrp_cor:BusinessResultsOfGroupTable


     from:  jpcrp_cor:BusinessResultsOfGroupTable
     to:  jppfs_cor:ConsolidatedOrNonConsolidatedAxis


       from:  jppfs_cor:ConsolidatedOrNonConsolidatedAxis
       to:  jppfs_cor:ConsolidatedMember


   from:  jpcrp_cor:BusinessResultsOfGroupHeading
   to:  jpcrp_cor:BusinessResultsOfGroupLineItems


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:RevenueIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp030000-asr_E01766-000:OperatingProfitIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:ProfitLossBeforeTaxIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:ProfitLossIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:ProfitLossAttributableToOwnersOfParentIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:ComprehensiveIncomeIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:ComprehensiveIncomeAttributableToOwnersOfParentIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp030000-asr_E01766-000:TotalEquityIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:TotalAssetsIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:EquityToAssetRatioIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:BasicEarningsLossPerShareIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:DilutedEarningsLossPerShareIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:EquityAttributableToOwnersOfParentIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:RatioOfOwnersEquityToGrossAssetsIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:RateOfReturnOnEquityIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:PriceEarningsRatioIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:CashFlowsFromUsedInOperatingActivitiesIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:CashFlowsFromUsedInInvestingActivitiesIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:CashFlowsFromUsedInFinancingActivitiesIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:CashAndCashEquivalentsIFRSSummaryOfBusinessResults


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:NumberOfEmployees


     from:  jpcrp_cor:BusinessResultsOfGroupLineItems
     to:  jpcrp_cor:AverageNumberOfTemporaryWorkers
```

# 5 最後に
サンプルプログラムでは項目間の親子関係を取り出しましたが、要素がわかればラベル(EDINETだと日本語と英語のラベルが定義)なども取り出せると思います。XBRLタクソノミにはインスタンスに含まれるデータの表示に有用な情報が色々と含まれていますので、ぜひ活用を検討してみましょう。


# 6 問い合わせ先

本記事に関する問い合わせは、以下のメールアドレスまでお願いします。
e-mail：xbrl-tech-qa@xbrl.or.jp
（もちろん、qiita上でのコメントも歓迎します）

本メールアドレスは、qiitaの記事を執筆しているXBRLJapanの開発委員会の問合せ窓口になります。
そのため、組織に関する一般的な問合せなどは内容によって回答できかねますが、XBRLに関する技術的な質問、意見、要望、助言等はお気軽にご連絡ください。
なお、委員会メンバが有志で対応しているため、回答に時間がかかることもありますが、ご了承ください。