xb

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace XbrlParser
{
    public class XbrlDocument
    {
        private readonly XDocument _document;
        private readonly XNamespace _xbrli = "http://www.xbrl.org/2003/instance";
        private readonly Dictionary<string, XNamespace> _namespaces;

        public XbrlDocument(string filePath)
        {
            _document = XDocument.Load(filePath);
            _namespaces = _document.Root.Attributes()
                .Where(a => a.IsNamespaceDeclaration)
                .GroupBy(
                    a => a.Name.Namespace == XNamespace.None ? "" : a.Name.LocalName,
                    a => XNamespace.Get(a.Value))
                .ToDictionary(g => g.Key, g => g.First());
        }

        /// <summary>
        /// 要素名と年度を指定して値を取得します。
        /// </summary>
        /// <param name="elementName">要素名(プレフィックス付き)</param>
        /// <param name="year">年度(YYYY形式)</param>
        /// <returns>該当する値。見つからない場合はnull。</returns>
        public string GetValue(string elementName, int year)
        {
            var parts = elementName.Split(':');
            if (parts.Length != 2)
                throw new ArgumentException("要素名はプレフィックス付きで指定してください。例: gaap:Assets");

            var prefix = parts[0];
            var localName = parts[1];

            if (!_namespaces.ContainsKey(prefix))
                throw new ArgumentException($"名前空間プレフィックス '{prefix}' が見つかりません。");

            var ns = _namespaces[prefix];

            // 指定した年度のコンテキストを取得
            var contextRefs = GetContextRefsByYear(year);
            if (contextRefs == null || !contextRefs.Any())
                return null;

            // 要素を検索
            var elements = _document.Descendants(ns + localName)
                .Where(e => e.Attribute("contextRef") != null && contextRefs.Contains(e.Attribute("contextRef").Value));

            var element = elements.FirstOrDefault();

            return element?.Value;
        }

        /// <summary>
        /// 指定した年度に対応するコンテキストIDのリストを取得します。
        /// </summary>
        /// <param name="year">年度(YYYY形式)</param>
        /// <returns>コンテキストIDのリスト。見つからない場合は空のリスト。</returns>
        private List<string> GetContextRefsByYear(int year)
        {
            var contextRefs = new List<string>();

            // コンテキスト要素を取得
            var contexts = _document.Descendants(_xbrli + "context");

            foreach (var context in contexts)
            {
                var period = context.Element(_xbrli + "period");
                if (period == null)
                    continue;

                var instant = period.Element(_xbrli + "instant");
                var startDate = period.Element(_xbrli + "startDate");
                var endDate = period.Element(_xbrli + "endDate");

                DateTime contextDate;

                if (instant != null && DateTime.TryParse(instant.Value, out contextDate))
                {
                    if (contextDate.Year == year)
                        contextRefs.Add(context.Attribute("id")?.Value);
                }
                else if (startDate != null && endDate != null &&
                         DateTime.TryParse(endDate.Value, out contextDate))
                {
                    if (contextDate.Year == year)
                        contextRefs.Add(context.Attribute("id")?.Value);
                }
            }

            return contextRefs;
        }

        /// <summary>
        /// 名前空間URIを取得します。
        /// </summary>
        /// <param name="prefix">名前空間プレフィックス</param>
        /// <returns>名前空間URI。見つからない場合はnull。</returns>
        public string GetNamespaceUri(string prefix)
        {
            if (_namespaces.ContainsKey(prefix))
                return _namespaces[prefix].NamespaceName;

            return null;
        }
    }
}

使用例

using System;
using XbrlParser;

namespace XbrlExample
{
    class Program
    {
        static void Main(string[] args)
        {
            // XBRLファイルのパスを指定
            var xbrlFilePath = "sample.xbrl";

            // XbrlDocumentオブジェクトを作成
            var xbrlDoc = new XbrlDocument(xbrlFilePath);

            // 要素名と年度を指定して値を取得
            var elementName = "gaap:Assets";
            int year = 2022;

            var value = xbrlDoc.GetValue(elementName, year);

            if (value != null)
            {
                Console.WriteLine($"{year}年の{elementName}の値は {value} です。");
            }
            else
            {
                Console.WriteLine($"{year}年の{elementName}の値が見つかりませんでした。");
            }

            // 名前空間URIを取得
            var namespaceUri = xbrlDoc.GetNamespaceUri("gaap");
            if (namespaceUri != null)
            {
                Console.WriteLine($"プレフィックス 'gaap' の名前空間URIは {namespaceUri} です。");
            }
            else
            {
                Console.WriteLine("名前空間プレフィックス 'gaap' が見つかりませんでした。");
            }
        }
    }
}


いいなと思ったら応援しよう!