Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples of using Gepsio beyond "Hello world" #12

Open
ValeriyTitov opened this issue Jul 2, 2018 · 15 comments
Open

Examples of using Gepsio beyond "Hello world" #12

ValeriyTitov opened this issue Jul 2, 2018 · 15 comments

Comments

@ValeriyTitov
Copy link

Hello, from time to time im returning Gepsio homepage :)
Examples you made just showing "flat" lists of context/facts/items in foreach cycle.

Can you provide more extended example of using Gepsio ?

  • Find labels for facts
  • Correlate facts to each other
@JeffFerguson
Copy link
Owner

Sure thing! I'd be happy to.

When you say "Find labels for facts", are you talking about the label linkbase, and maybe showing a list of facts and their associated labels?

@ValeriyTitov
Copy link
Author

Thanks for reply!
Yes, i couldn't find a way to:

  • Display associated labels for a list of facts.
  • Find relationship between facts (example of use Definition linkbase ?)

@JeffFerguson
Copy link
Owner

Not a problem. I'll get a sample written for you. I'm assuming that you'd like to see in written in C#?

@ValeriyTitov
Copy link
Author

Yes, C# if you can.

@JeffFerguson
Copy link
Owner

Do you have a URL to a particular document that you would like me to use in the sample?

@ValeriyTitov
Copy link
Author

Well, i already posted instance document and link to taxonomy in How to attach label for a fact ? thread with no luck...
This XBRL instance document contained 4 facts about 2 accountants:

Name: John Smith
Name: Marry Williams
BirthDate: 1985-03-28
BirthDate: 1980-03-01

However, i think best way is to use samples from XBRL instances what comes with Gepsio. So other people can understand.

@JeffFerguson
Copy link
Owner

Fair enough. I'll get right on it! Thank you!

My other idea is that Gepsio should have a property called Label on all Fact objects so that you can find the labels without having to do any work. Maybe I will put that in the next release after I build out the sample.

@JeffFerguson
Copy link
Owner

Here is what I came up with:

using System;
using JeffFerguson.Gepsio;

namespace FactLabels
{
    class Program
    {
        static void Main(string[] args)
        {
            var doc = new XbrlDocument();
            doc.Load("https://www.sec.gov/Archives/edgar/data/789019/000119312512026864/msft-20111231.xml");
            foreach(var currentFragment in doc.XbrlFragments)
            {
                foreach(var currentFact in currentFragment.Facts)
                {
                    var matchingLabel = FindLabelForFact(currentFact, currentFragment);
                    if(string.IsNullOrEmpty(matchingLabel) == false)
                    {
                        Console.WriteLine($"The label for fact {currentFact.Name} is '{matchingLabel}'.");
                    }
                }
            }
        }

        /// <summary>
        /// Return the label for a fact.
        /// </summary>
        /// <param name="currentFact">
        /// The fact whose label should be returned.
        /// </param>
        /// <param name="xbrlFragment">
        /// The fragment containing the fact.
        /// </param>
        /// <returns>
        /// The label for the fact. An empty string is returned if a label is not available.
        /// </returns>
        private static string FindLabelForFact(Fact currentFact, XbrlFragment xbrlFragment)
        {
            foreach(var currentSchema in xbrlFragment.Schemas)
            {
                if(currentSchema.LabelLinkbase != null)
                {
                    var labelId = FindLabelIdForFact(currentFact, currentSchema.LabelLinkbase);
                    if(string.IsNullOrEmpty(labelId) == false)
                    {
                        return FindLabelForLabelId(labelId, currentSchema.LabelLinkbase);
                    }
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// Return the label for a label ID.
        /// </summary>
        /// <param name="labelId">
        /// The ID of a label.
        /// </param>
        /// <param name="labelLinkbase">
        /// The label linkbase to search for the given label ID.
        /// </param>
        /// <returns>
        /// The label for the label ID. An empty string is returned if a label is not available.
        /// </returns>
        private static string FindLabelForLabelId(string labelId, LabelLinkbaseDocument labelLinkbase)
        {
            foreach(var currentLabelLink in labelLinkbase.LabelLinks)
            {
                foreach(var currentLabel in currentLabelLink.Labels)
                {
                    if(currentLabel.Label.Equals(labelId) == true)
                    {
                        return currentLabel.Text;
                    }
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// Return the label ID for a fact.
        /// </summary>
        /// <param name="currentFact">
        /// The fact whose label should be returned.
        /// </param>
        /// <param name="labelLinkbase">
        /// The label linkbase to search.
        /// </param>
        /// <returns>
        /// The label ID for the fact. An empty string is returned if a label is not available.
        /// </returns>
        private static string FindLabelIdForFact(Fact currentFact, LabelLinkbaseDocument labelLinkbase)
        {
            var factAsItem = currentFact as Item;
            if(factAsItem == null)
            {
                return string.Empty;
            }
            if(string.IsNullOrEmpty(factAsItem.SchemaElement.Id) == true)
            {
                return string.Empty;
            }
            foreach(var currentLink in labelLinkbase.LabelLinks)
            {
                var matchingArc = currentLink.GetLabelArc(factAsItem.SchemaElement.Id);
                if(matchingArc != null)
                {
                    return matchingArc.ToId;
                }
            }
            return string.Empty;
        }
    }
}

I will add this to the Wiki.

With that said, I think that there is opportunity for Gepsio to provide additional value in a future release. I don't believe that you should have to write this much code. There should be a property on an Item called Label, of type string, that would do all of this work for you and provide the correct label in one line of code. I'll log an issue for that.

@ValeriyTitov
Copy link
Author

ValeriyTitov commented Jul 16, 2018

Hi, thanks for the example.
I had some issues running it.

  1. IEnumarable not supported on CurrentFragment,.Schema error
    Solution: Update Gepsio to latest dev-branch version

  2. Input string is invalid"
    For instance you provided "https://.../msft-20111231.xml", Gepsio throws an exception while converting "1.0200" to decimal in CalculationArc.cs\CalculationArc(INode CalculationArcNode).
    This happens because of dot seperator.
    Solution: Use Convert.ToDecimal(OrderString, System.Globalization.CultureInfo.InvariantCulture);
    After making this changes, Gepsio works fine and shows labels for instance you provided.

  3. No support for reference linkbases
    I can no longer open my Instance document, while previous versions of Gepsio worked fine.
    Solution: I could'nt find a solution. I cannot load my document with new dev branch.

New Gepsio from Step 1 throws an exception in LinkbaseDocumentCollection.cs\ReadLinkbaseReference while trying to load my instance document (instance with 2 accountants).

Once again, I had to rewrite code to force Gepsio load Taxonomy from local copy.
Could this be the source of problem ?

3.1 XbrlSchemaCollection.cs - Add well-known files locations to link for they local copies.
3.2 SchemaSet.cs - write CustomXmlUrlResolver;
3.2 xbrlschema.cs - rewrite GetFullSchemaPath to use local files.

@JeffFerguson
Copy link
Owner

Which version of Gepsio were you originally referencing from NuGet? NuGet is up to 2.1.0.13.

@JeffFerguson
Copy link
Owner

I'll log a bug for Issue 2. Thank you for reporting that! Yes, Gepsio needs to use the invariant culture there.

@JeffFerguson
Copy link
Owner

Also, your reference linkbase issue is documented separately in Issue 13.

@ValeriyTitov
Copy link
Author

ValeriyTitov commented Jul 19, 2018

Hi!
Sorry for late response. It worked parially for me.

  1. I commented out exception as suggest in Issue 13
  2. Document loads, but Gepsio can not find any labales.
  3. After investigating, i decided to remove "namespace" in FindLabelIdForFact since all IDs starts with "purcb_dic_" in this schemaElement.
 s = factAsItem.SchemaElement.Id.Substring(10); //remove "purcb_dic_"
 var matchingArc = currentLink.GetLabelArc(s);
  1. After making those changes, Gepsio able to find labels.

Dont know if it correct...

@ValeriyTitov
Copy link
Author

Any suggestion how to find relationship between facts ?
As i understand, fact should reference same dimensions and they values ?

@ValeriyTitov
Copy link
Author

Oh, some better way i supose.
I need to find label by SchemaElement.Name.

   s = factAsItem.SchemaElement.Name;
   var matchingArc = currentLink.GetLabelArc(s);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants