Correction on Calculation Arc Conflicts and Precedence

The post titled “Calculation Arc Conflicts and Precedence” discussed strategies for determining which calculation arc took precedence when similar arcs were found. The strategies in that post were incorrect, and this post aims to set the record straight.

A very kind reader named Owen Jones pointed out that the key to resolving conflicts with similar arcs has to do with the arc’s priority attribute. This attribute and its usage is discussed in section 3.5.3.9.7 of the XBRL 2.1 Specification:

Arcs that represent prohibiting and overriding relationships are controlled by two attributes, @use and @priority, which are available on all arc elements defined in this specification… The content of the @priority attribute MUST be an integer. The default value of the @priority attribute is “0”. The @priority attribute is used when applying the rules of prohibition and overriding in a network of relationships. Each relationship has a priority equal to the value of the priority attribute on the Arc that represents the relationship.

So, returning to the example in the earlier blog post, we have two calculation arcs. The arc in the calculation linkbase found in the schema reference is as follows:

    <calculationArc xlink:type="arc"
      xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item"
      xlink:from="t_P1" xlink:to="t_P3"
      order="1"
      weight="1"
      use="optional" 
      t:strAttr="abc"
      t:decAttr="1.23"
      t:dblAttr="4.56"
      t:boolAttr="true"
      />

The arc in the calculation linkbase found in the XBRL instance is as follows:

    <calculationArc xlink:type="arc"
      xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item"
      xlink:from="t_P1" xlink:to="t_P3"
      order="1"
      weight="1"
      priority="1"
      use="prohibited"
      t:strAttr="abc"
      t:decAttr="1.23"
      t:dblAttr="4.56"
      t:boolAttr="true"
      />

Both arcs use the same xlink:from and xlink:to values, which is at the heart of the conflict that needs to be resolved. The arc from the schema reference linkbase does not have a priority attribute, so its default priority is 0. The arc from the XBRL instance linkbase reference has an explicit priority attribute with a value of 1. The arc with the higher priority value is the one to use during conflict resolution, so, in this case, the arc to use is the arc from the calculation linkbase found in the XBRL instance.

Thank you to Owen Jones for the insightful comments!

Calculation Arc Conflicts and Precedence

The 331-equivalentRelationships-instance-02.xml conformance test in the XBRL-CONF-2014-12-10 conformance suite presents another opportunity for Gepsio to improve in its next version.

The landscape for this test, with regards to calculation arcs, is as follows:

  • the document instance contains a schema reference
  • the schema reference contains a calculation linkbase reference
  • the calculation linkbase reference referenced in the schema contains three locators for elements t_P1, t_P2, and t_P3
  • the calculation linkbase reference referenced in the schema contains an optional calculation arc from t_P1 to t_P2 and a second optional calculation arc from t_P1 to t_P3

This all defines a summation of t_P1 = t_P2 + t_P3. With me so far? Good.

The trick is that the XBRL instance itself references a second calculation linkbase, and that linkbase contains two locators, one for t_P1 and one for t_P3, as well as a prohibited calculation arc from t_P1 to t_P3.

What this test offers, therefore, is two arcs with conflicting information. Which one takes precedent? The calculation linkbase from the schema reference says that t_P1 = t_P2 + t_P3 but the calculation linkbase from the XBRL instance itself says that the arc from t_P1 to t_P3 is prohibited, which would basically invalidate the equation and prevent the calculation from being made since one of its arcs is prohibited.

This all presents an opportunity for Gepsio. In Gepsio 2.1.0.15 (which is the current version as of this writing), only calculation linkbases pulled from schema references are considered, and the calculation linkbase validation reference doesn’t consider any information from calculation linkbases pulled directly from XBRL instances. This conformance test proves that Gepsio is in error in this design and that it must consider all calculation linkbases found throughout the XBRL instance.

The XBRL Specification does not seem to specify what happens in this situation, in which there are two calculation linkbases with conflicting information in them. From the test itself, it can be inferred that the actual approach is that any information in the XBRL instance itself takes precedence over the information pulled from a schema reference. If a reader can point to a source that explicitly describes this assumption, then – by all means – feel free to leave a comment and describe where that information can be found.

To get this conformance test to pass, Gepsio will need to abide by a couple of new designs:

  • the calculation linkbase validation engine must consider calculation linkbase information pulled from the XBRL instance as well as information pulled from within schema references
  • the calculation linkbase validation engine must give precedence to linkbase information pulled from the XBRL instance over the information pulled from within schema references when there is a conflict between the two linkbases

This will be the next bit of work for Gepsio.

For those interested in the details of the test, here are the relevant files. It begins with the XBRL instance itself:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2008 XBRL International. All Rights Reserved. -->
<xbrl 
xmlns="http://www.xbrl.org/2003/instance" 
xmlns:t="http://xbrl.org/conformance/example" 
xmlns:link="http://www.xbrl.org/2003/linkbase" 
xmlns:xlink="http://www.w3.org/1999/xlink" 
>
  
  <link:schemaRef 
    xlink:type="simple" 
    xlink:href="331-equivalentRelationships-01.xsd"/>

 <link:linkbaseRef 
    xlink:type="simple"
    xlink:arcrole="http://www.w3.org/1999/xlink/properties/linkbase"
    xlink:href="331-equivalentRelationships-02-calculation.xml" />

  <context id="c-V01">
    <entity>
      <identifier scheme="http://xbrl.org/entity/identification/scheme">01</identifier>
    </entity>
    <period>
      <instant>2007-12-31</instant>
    </period>
  </context>  

  <unit id="pure">
    <measure>pure</measure>
  </unit>

  <t:P1 contextRef="c-V01" unitRef="pure" decimals="0">111</t:P1>
  <t:P2 contextRef="c-V01" unitRef="pure" decimals="0">111</t:P2>
  <t:P3 contextRef="c-V01" unitRef="pure" decimals="0">999</t:P3>


</xbrl>

The referenced schema is as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2008 XBRL International. All Rights Reserved. -->
<schema
  xmlns="http://www.w3.org/2001/XMLSchema"
  xmlns:xbrli="http://www.xbrl.org/2003/instance"
  xmlns:link="http://www.xbrl.org/2003/linkbase"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:t="http://xbrl.org/conformance/example"
  targetNamespace="http://xbrl.org/conformance/example"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified">
  <annotation>
    <appinfo>
      <link:linkbaseRef xlink:type="simple"
        xlink:role="http://www.xbrl.org/2003/role/calculationLinkbaseRef"
        xlink:arcrole="http://www.w3.org/1999/xlink/properties/linkbase"
        xlink:href="331-equivalentRelationships-01-calculation.xml"
        xlink:title="Calculation Links, all" />
    </appinfo>
  </annotation>
  <import
    namespace="http://www.xbrl.org/2003/instance"
    schemaLocation="http://www.xbrl.org/2003/xbrl-instance-2003-12-31.xsd" />
  <element
    id="t_P1"
    name="P1"
    type="xbrli:decimalItemType"
    substitutionGroup="xbrli:item"
    xbrli:periodType="instant"
    nillable="true" />
  <element
    id="t_P2"
    name="P2"
    type="xbrli:decimalItemType"
    substitutionGroup="xbrli:item"
    xbrli:periodType="instant"
    nillable="true" />
  <element
    id="t_P3"
    name="P3"
    type="xbrli:decimalItemType"
    substitutionGroup="xbrli:item"
    xbrli:periodType="instant"
    nillable="true" />
  <attribute
    name="strAttr"
    type="string" />
  <attribute
    name="decAttr"
    type="decimal" />
  <attribute
    name="dblAttr"
    type="double" />
  <attribute
    name="boolAttr"
    type="boolean" />
  <attribute
    name="defaultAttr"
    type="string"
    default="pqr" />
  <attribute
    name="fixedAttr"
    type="string"
    fixed="xyz" />
</schema>

The calculation linkbase referenced by the schema is as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2008 XBRL International. All Rights Reserved. -->
<linkbase
  xmlns="http://www.xbrl.org/2003/linkbase"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:t="http://xbrl.org/conformance/example"
  xsi:schemaLocation="
    http://www.xbrl.org/2003/linkbase 
      http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd
    http://xbrl.org/conformance/example
      331-equivalentRelationships-01.xsd
    ">
  <calculationLink xlink:type="extended"
    xlink:role="http://www.xbrl.org/2003/role/link">
    <loc xlink:type="locator"
      xlink:label="t_P1"
      xlink:href="331-equivalentRelationships-01.xsd#t_P1" />
    <loc xlink:type="locator"
      xlink:label="t_P2"
      xlink:href="331-equivalentRelationships-01.xsd#t_P2" />
    <loc xlink:type="locator"
      xlink:label="t_P3"
      xlink:href="331-equivalentRelationships-01.xsd#t_P3" />
    <calculationArc xlink:type="arc"
      xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item"
      xlink:from="t_P1" xlink:to="t_P2"
      order="1"
      weight="1"
      use="optional" />
    <calculationArc xlink:type="arc"
      xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item"
      xlink:from="t_P1" xlink:to="t_P3"
      order="1"
      weight="1"
      use="optional" 
      t:strAttr="abc"
      t:decAttr="1.23"
      t:dblAttr="4.56"
      t:boolAttr="true"
      />
  </calculationLink>
</linkbase>

The calculation linkbase referenced in the XBRL instance, which contains the conflicting calculation arc, is as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2008 XBRL International. All Rights Reserved. -->
<linkbase
  xmlns="http://www.xbrl.org/2003/linkbase"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:t="http://xbrl.org/conformance/example"
  xsi:schemaLocation="
    http://www.xbrl.org/2003/linkbase 
      http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd
    http://xbrl.org/conformance/example
      331-equivalentRelationships-01.xsd
    ">
  <calculationLink xlink:type="extended"
    xlink:role="http://www.xbrl.org/2003/role/link">
    <loc xlink:type="locator"
      xlink:label="t_P1"
      xlink:href="331-equivalentRelationships-01.xsd#t_P1" />
    <loc xlink:type="locator"
      xlink:label="t_P3"
      xlink:href="331-equivalentRelationships-01.xsd#t_P3" />
    <calculationArc xlink:type="arc"
      xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item"
      xlink:from="t_P1" xlink:to="t_P3"
      order="1"
      weight="1"
      priority="1"
      use="prohibited"
      t:strAttr="abc"
      t:decAttr="1.23"
      t:dblAttr="4.56"
      t:boolAttr="true"
      />
  </calculationLink>
</linkbase>

Inferring Linkbase Roles

Today, Gepsio uses the role attribute of a linkbaseRef node to determine the type of linkbase reference being referenced. Take, for example, the following linkbase reference, found in the 331-equivalentRelationships-01.xsd file in the XBRL-CONF-2014-12-10 conformance suite:

      <link:linkbaseRef xlink:type="simple"
        xlink:role="http://www.xbrl.org/2003/role/calculationLinkbaseRef"
        xlink:arcrole="http://www.w3.org/1999/xlink/properties/linkbase"
        xlink:href="331-equivalentRelationships-01-calculation.xml"
        xlink:title="Calculation Links, all" />

The value of the role attribute is http://www.xbrl.org/2003/role/calculationLinkbaseRef, which informs Gepsio that the linkbase reference is a calculation linkbase reference. Gepsio responds to that hint by creating a CalculationLinkbaseDocument object and populating it with the data in the reference.

In Gepsio version 2.1.0.15 (which, as of this writing, is the most recent version on NuGet), if the value of a role attribute of a linkbase reference is not one of the known URIs, or it does not have a value, Gepsio ignores the reference and doesn’t load anything. This, however, causes problems with some conformance suite tests that do not specify the role attribute. Take, for example, the following linkbase reference, found in the 331-equivalentRelationships-instance-02.xml file in the XBRL-CONF-2014-12-10 conformance suite:

 <link:linkbaseRef 
    xlink:type="simple"
    xlink:arcrole="http://www.w3.org/1999/xlink/properties/linkbase"
    xlink:href="331-equivalentRelationships-02-calculation.xml" />

This linkbase reference doesn’t even specify a role attribute, which means that, as of today, Gepsio skips over it, since it doesn’t know what role the reference plays. This reference, however, is critical to the conditions of this particular test, so Gepsio will need to be able to handle this situation.

The next version of Gepsio, therefore, will add support for inferring the correct role for a linkbase reference when the role attribute is either missing or contains a URI that does not match any of the standard linkbase reference roles. Gepsio will load the reference and will examine the nodes to determine the correct role for the reference. It will then load the appropriate object model reference and make the object available to the loaded instance’s object model in the same way that it would if a role attribute were properly specified.

Async XBRL Loading Ready for Next Release

Gepsio’s develop branch on GitHub has just been updated with a bug fix that will allow XBRL to be asynchronously loaded. Some unit tests have also been added to ensure that the async load case will be tested from here on out.

This means that, starting with the next release of Gepsio, callers will have the choice of loading XBRL instances synchronously or asynchronously. The code for the synchronous case will be supported as it always has been:

public void LoadSyncExample()
{
    var xbrlDoc = new XbrlDocument();
    xbrlDoc.Load("DocumentUriGoesHere");
}

With the next release, the asynchronous case will be fully supported and will look quite familiar:

public async Task LoadAsyncExample()
{
    var xbrlDoc = new XbrlDocument();
    await xbrlDoc.LoadAsync("DocumentUriGoesHere");
}

This has been a long time coming. Hopefully, people will be able to make use of additional scenarios, such as in user interfaces, where asynchronous loading of XBRL may be more beneficial to the overall user experience.

New LINQ-to-XML Implementation Paving Way for Async Loading of XBRL

Gepsio’s develop branch on GitHub has just been updated with a new XML implementation, based on the System.Xml.Linq namespace (also known as "LINQ-to-XML"), that will pave the way for Gepsio’s support of asynchronously loading XBRL documents.

The main driver behind the XML service layer switch is that System.Xml does not support the asynchronous loading of XML documents, although System.Xml.Linq does. If Gepsio is to have any hope of supporting the asynchronous loading of XBRL documents, then its XML service layer will need to support asynchronous loading as well.

The develop branch up on GitHub has both an initial implementation of System.Xml.Linq in place as well as new XbrlDocument signatures for asynchronous loading of XBRL documents. The async signatures have not yet been tested. That’s next up on the roadmap.

.NET Runtime Support

Gepsio’s switch from System.Xml to System.Xml.Linq required a few changes in versioning support. Specifically, the next release of Gepsio will support .NET Standard 2.1, rather than .NET Standard 2.0, due to the fact that XDocument.LoadAsync() is not available in any version of .NET Standard other than 2.1. The unit tests and samples that ship with Gepsio will be updated to use .NET Core 3.0 to match Gepsio’s support of .NET Standard 2.1.

And, now, the not-so-good news: Microsoft has ended their support of the original .NET Framework with .NET Standard 2.1. This means that, once the next release of Gepsio is packaged up and released as a NuGet package, it will no longer support .NET Framework clients. Clients must be either upgraded to .NET Core or remain on version 2.1.0.14 of Gepsio, which will be the last to support the .NET Framework. It is recommended that clients upgrade to .NET Core 3.0.

Developer guidance for using Gepsio is, therefore, as follows:

  • Upgrade projects to .NET Core 3.0 to continue to use versions of Gepsio beyond version 2.1.0.14.
  • If projects cannot be upgraded to .NET Core and must remain on the original .NET Framework, continue to use Gepsio 2.1.0.14.

XML Service Layer Implementation Notes

As it turns out, adding new XML implementations to Gepsio is fairly straightforward, thanks to Gepsio’s deign philosophy of accessing all XML services through an interface. Think of Gepsio as two layers: a lower XML service layer and a higher-level XBRL service layer. Callers interact with Gepsio through its XBRL service layer. When the XBRL service layer needs XML services, the XBRL service layer calls the XML service layer. Gepsio defines interfaces for all XML services with interfaces like IDocument for working with XML documents and INode when working with XML nodes and elements. As a result, Gepsio’s XBRL service layer never calls any XML services directly and instead makes calls through these interfaces pulled from a rudimentary interface implementation container that Gepsio uses. In previous versions of Gepsio, these XML service layer interfaces were implemented using the classes in the System.Xml namespace. In this new version, another implementation of the same interfaces using the classes in the System.Xml.Linq namespace were put in place, and Gepsio’s XBRL service layer was none the wiser.

Gepsio 2.1.0.14 Released

A NuGet package for Gepsio 2.1.0.14 is now available here. Release notes for this version are available here. This release includes support for reference linkbases and automatic support for several new industry standard taxonomies, including schemas from IFRS and US-GAAP.

The last three releases have been published on a monthly basis. Version 2.1.0.12 was released at the beginning of June, version 2.1.0.13 was released at the beginning of July, and this new version at the beginning of August. This cadence brings smaller changes with each release but puts changes in the hands of users more frequently.

Enjoy!

Adding Local Search Support For Schemas With Invalid URLs

The discussion threads on a previous post, as well as the discussion attached to a GitHub issue, speak to the fact that Gepsio cannot find facts for XBRL instances that use the Dutch taxonomy. There are a couple of issues here, so this post will discuss the issue as well as an idea that will allow Gepsio to mitigate one of the issues.

A Gepsio user recently wrote to the project and said that they were in possession of an XBRL instance that was successfully parsed by Gepsio but was devoid of facts. The XBRL instance started out as follows:

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns="http://www.w3.org/1999/xhtml" xmlns:dst="http://xbrl.dcca.dk/dst" xmlns:cmn="http://xbrl.dcca.dk/cmn" xmlns:sob="http://xbrl.dcca.dk/sob" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:iso4217="http://www.xbrl.org/2003/iso4217" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ref="http://www.xbrl.org/2006/ref" xmlns:xh11d="http://www.w3.org/1999/xhtml/datatypes/" xmlns:arr="http://xbrl.dcca.dk/arr" xmlns:ixt="http://www.xbrl.org/inlineXBRL/transformation/2010-04-20" xmlns:lnk="http://www.xbrl.org/2003/linkbase" xmlns:xbrldt="http://xbrl.org/2005/xbrldt" xmlns:basis="http://xbrl.dcca.dk/Regnskab%202.0%20Basis" xmlns:ifrs="http://xbrl.iasb.org/taxonomy/2009-04-01/ifrs" xmlns:ix="http://www.xbrl.org/2008/inlineXBRL" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mrv="http://xbrl.dcca.dk/mrv" xmlns:xl="http://www.xbrl.org/2003/XLink" xmlns:fsa="http://xbrl.dcca.dk/fsa" xmlns:xbrldi="http://xbrl.org/2006/xbrldi" xmlns:gsd="http://xbrl.dcca.dk/gsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink">
   <lnk:schemaRef xlink:href="http://archprod.service.eogs.dk/taxonomy/20171001/entryDanishGAAPBalanceSheetAccountFormIncomeStatementByNatureIncludingManagementsReviewStatisticsAndTax20171001.xsd" xlink:type="simple"/>

There is an issue right away, because that schema reference specifies an invalid URL. There is no document, XML schema or otherwise, at the address of http://archprod.service.eogs.dk/taxonomy/20171001. What happens here is that Gepsio loads the document, finds the schema reference, and attempts to load the schema. Since the schema load fails, it logs a validation error and continues on as best it can. Since no schemas are loaded, no element definitions are loaded, and Gepsio can find no facts.

The first question is, “Why does this document reference a taxonomy with an invalid URL?” The answer that came back was this:

But the issue is that there will never be a hosted taxonomy in denmark, since they have chosen to not take the responsibility thereof.

OK, then. Apparently, the URLs for Dutch taxonomies are placeholders, and they are meant to be available locally, in the same location as the XBRL instance.

Gepsio is being modified to assist with this issue. If Gepsio attempts to resolve a schema reference, and gets the equivalent of an HTTP 404 back from the request to retrieve the schema, then Gepsio will look for the schema in the same folder as the XBRL instance which contains the schema reference.