Tuesday, June 19, 2012

Unsupported Path Bug Fixed in Linkbase Document Class

Codeplex (and Gepsio) user matthewschrager recently submitted a patch for a rather old issue that caused paths of the form "file:///C:/blah/blah/http://blah/blah.org" to be created in the LinkbaseDocument class’ GetFullLinkbasePath() method when filings that reference remote documents are stored locally. This caused a NotSupportedException to be thrown.

I have just applied this patch and have checked in a fix for the issue. The fix will be available in the next release (currently planned for Jul 2012). If you want to grab the code ahead of time, feel free to grab the latest source code here.

Many thanks to matthewschrager for sending in a patch!

Monday, June 18, 2012

Null Reference Bug Fixed in QualifiedName Class

Codeplex (and Gepsio) user jwokelly recently filed a bug noting that the Gepsio Nov 2011 CTP was failing to parse the XBRL documents created by Amazon to report their financial information for Q1 2012. More specifically, Gepsio was throwing a NullReferenceException while attempting to perform equality comparisons in the qualified name code.

I have just fixed this bug and have checked in a fix. The fix will be available in the next release (currently planned for Jul 2012). If you want to grab the code ahead of time, feel free to grab the latest source code here.

Many thanks to jwokelly for reporting a bug and for sending along the offending documents in a ZIP file. Gepsio now includes a unit test that parses these documents and ensures that no exceptions are thrown.

Sunday, June 17, 2012

Full Documentation Available for the Nov 2011 CTP

The first release of help file-style documentation for Gepsio is now available for the Nov 2011 CTP! To grab your copy, go to the Nov 2011 CTP Release page here and download the JeffFerguson.Gepsio.chm file.

If you download the file directly, and save it to a location such as your Desktop, you may get an “Navigation to the webpage was canceled” message when you open it:

image

To fix this, close the CHM file.Then find the downloaded CHM file, right click it, and select “Properties” from the context menu. You will see the file’s Properties dialog:

image

If you see the message at the bottom that reads “This file came from another computer and might be blocked to help protect this computer”, click the “Unblock” button. Click the “OK” button to close the Properties dialog, and reopen the CHM file.

Voila!

image

This online documentation is generated automatically from comments I embed in the source code. The nice part about that is that, as I update the source code comments and produce new builds, the online documentation will be updated and synchronized with the latest information available in the Gepsio object model.

Thursday, June 14, 2012

Gepsio Reviewed by HereBeDragon

I found a very nice review of Gepsio today on a blog at herebedragon.blogspot.com. Here’s what the author had to say:

My first stop was Codeplex, where I searched for the term 'XBRL' and found 3 projects. That's too few. Of these, one particularly caught my eye (in fact I have followed this project for a few months) and that is 'Gepsio'.

Gepsio is a .NET based document object model for XBRL that can load and validate XBRL documents. It's a 'strict' processor for XBRL that throws exceptions when the loaded document is not valid. Perhaps it's possible to make changes to and save XBRL files using Gepsio as well, but frankly I could not look into it in depth because of the exceptions and because I was short of time.

I did give the source code of the XBRL Reader part of Gepsio a good look though. I was impressed to see sustained work, focus on meeting XBRL conformance requirements and a clean, well organized codebase. Gepsio is a good option to evaluate if you are looking for open source XBRL software.

The Gepsio XBRL code is licensed under Microsoft Public License (Ms-PL), which allows you to use the code in a commercial application.

Find the author’s review of Gepsio, and many other open source XBRL tools, through this link.

Thanks to HereBeDragon for the review!

Monday, June 11, 2012

Gepsio on Facebook

I have just created a page for Gepsio on Facebook. “Like” Gepsio at http://www.facebook.com/gepsio to get information on releases, blog posts, documentation, samples and questions and answers. Looking forward to seeing you there!

Saturday, June 9, 2012

Documentation Work in Progress

I am currently working on providing some online help for Gepsio:

image

I am currently adding XML comments to all of the public classes, properties and methods so that I can use Sandcastle to generate CHM-style documentation. The XML comments should also aid in providing documentation to Visual Studio’s Intellisense infrastructure.

I realize that Gepsio’s growing array of public classes and properties can be daunting and I hope that this documentation will go a long away towards making its public interface understandable.

Saturday, March 24, 2012

Using Gepsio From C#

A developer new to Gepsio asked for a C#-based sample of using Gepsio. I have built a simple C# console app using Visual Studio 2010 and the Gepsio Nov 2011 CTP. I’ll show the code first, and then I will discuss some key points after the code is shown:

using JeffFerguson.Gepsio;
using System;

namespace GepsioConsole
{
class Program
{
/// <summary>
/// The magic begins here.
/// </summary>
/// <param name="args">
/// A collection of program arguments. One argument should be supplied: the address of the XBRL document
/// to load.
/// </param>
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("usage: GepsioConsole [XBRL document]");
return;
}
ProcessXbrlWithGepsio(args[0]);
}

/// <summary>
/// Process a named XBRL document.
/// </summary>
/// <param name="xbrlFile">
/// The address of the XBRL document to process.
/// </param>
private static void ProcessXbrlWithGepsio(string xbrlFile)
{
try
{
var xbrlDoc = new XbrlDocument();
xbrlDoc.Load(xbrlFile);
foreach (var currentFragment in xbrlDoc.XbrlFragments)
{
DisplayFragmentStatistics(currentFragment);
WriteFactValue(currentFragment, "EntityRegistrantName");
WriteFactValue(currentFragment, "DocumentPeriodEndDate");
}
}
catch (XbrlException xbrle)
{
Console.WriteLine("ERROR: {0}", xbrle.Message);
}
}

/// <summary>
/// Display statistics relating to the loaded document fragment.
/// </summary>
/// <param name="currentFragment">
/// The XBRL fragment whose statistics should be published.
/// </param>
private static void DisplayFragmentStatistics(XbrlFragment currentFragment)
{
var factsCollection = currentFragment.Facts;
Console.WriteLine("Number of facts...: {0}", factsCollection.Count);
var unitsCollection = currentFragment.Units;
Console.WriteLine("Number of units...: {0}", unitsCollection.Count);
var contextsCollection = currentFragment.Contexts;
Console.WriteLine("Number of contexts: {0}", contextsCollection.Count);
}

/// <summary>
/// Display the value of a fact pulled from an XBRL fragment.
/// </summary>
/// <param name="currentFragment">
/// The fragment containing the fact to be found.
/// </param>
/// <param name="factName">
/// The name of the fact to be found.
/// </param>
private static void WriteFactValue(XbrlFragment currentFragment, string factName)
{
foreach (var currentFact in currentFragment.Facts)
{
if (currentFact.Name.Equals(factName) == true)
{
var currentFactAsItem = currentFact as Item;
Console.WriteLine("{0}: {1}", factName, currentFactAsItem.Value);
return;
}
}
}
}
}



I wanted to offer a few notes regarding this code:



  • This is a console application, and is intended to be run with a command line argument specifying the address of the XBRL document to be loaded, as in GepsioConsole http://www.sec.gov/Archives/edgar/data/21344/000104746911006790/ko-20110701.xml. Gepsio can work with documents stored on the Web, so HTTP-based document addresses are valid.

  • From Gepsio’s point of view, an XBRL document is a collection of fragments. The fragments idea was originally designed to support the notion of Inline XBRL, where a document may consist of multiple XBRL fragments. For standard XBRL documents, however, the entire document is an XBRL document, which makes up one “fragment”. This explains the “for each fragment in document” code in the ProcessCodeWithGepsio() method.

  • The WriteFactValue() method looks for a fact in the fragment’s collection of facts. Remember that, from an XBRL point of view, a fact is a type of item. In XBRL parlance, items can be facts, which have a single value, or tuples, which can have more than one value. Gepsio models this fact by defining a base class called Item and then deriving both Fact and Tuple from Item. This explains the cast back to Item in the code for WriteFactValue(). The cast may look a bit strange … perhaps I’ll revisit this in a later CTP.

As I developed this sample, I noticed that Gepsio performs as intended but, for larger documents, its performance can be improved. I’ll be addressing this shortly. Look for a future blog post where I discuss performance, where it could be improved, and how the improvements will be implemented. I will be using the code in this blog post as the showcase for the performance improvements, so you will be seeing this code again.