XINCE is an expression syntax that allows the creation of XBRL reports using a XULE processor.

The XINCE language uses the XULE syntax to define facts in an XBRL instances either in a  JSON or XML format.

Creating Facts with XINCE

The XINCE syntax allows a user to define the data included in an XBRL instance. The XINCE syntax supports associating dimensions with a fact.  These include the period the concept, the entity the unit and any other taxonomy defined dimensions. XINCE can be used to create as many facts as required.  Every fact that is created must specify the instance document that it belongs too.

XINCE created facts can then be written to an instance or multiple instances.

Fact Generation Example

The following expression will take every monetary fact in an instance document, multiply the value by 10% and output the result as a new instance called myInstance.

output  createInstance
true
instance-name  "myInstance"
instance-taxonomy 'https://www.sec.gov/Archives/edgar/data/891166/000089116622000114/uve-20220930.xsd'
output  add_fact_values
{@concept.data-type = xbrli:monetaryItemType}
true
fact-value $rule-value * 1.1
fact-concept $rule-value.concept.to-xince
fact-unit $rule-value.unit.to-xince
fact-entity  $rule-value.entity.to-xince
fact-period  $rule-value.period.to-xince
fact-decimals  $rule-value.decimals
fact-dimensions  $rule-value.dimensions.to-xince

fact-instance "myInstance"

Create Instance from Excel

Xule includes a  function to read excel spreadsheets.  This function can be used to create a XBRL instance from a standardized Excel template. The following example demonstrates reading the Single Audit Reporting template spreadsheet and returning an XBRL instance.

This standard Excel Template is provided by the Federal Government to collect single Audit Information. We have included this example copy of this spreadsheet on github  sf-sac.xlsx. 

To create the instance document we use two taxonomies. The first is the single audit taxonomy which is included as part of the Government Reporting Taxonomy (GRIP). The entry point for this taxonomy is https://taxonomies.xbrl.us/grip/2022/singleaudit/singleaudit-all_2022.xsd. The second taxonomy is the DEI taxonomy published by the SEC. This taxonomy entry point is https://xbrl.sec.gov/dei/2022/dei-sub-2022.xsd.

Once we have the taxonomies we want to use we can create a blank instance document.

output createInstance
true
instance-name  'myInstance'
instance-taxonomy list('https://taxonomies.xbrl.us/grip/2022/singleaudit/singleaudit-all_2022.xsd', 'https://xbrl.sec.gov/dei/2022/dei-sub-2022.xsd').to-json

Get the Federal Awards Data

The excel spreadsheet includes a named range called FederalAwards in the tab Federal Awards. Xule has the ability to access a named range in an excel spreadsheet. We can return this named range using a function called excel-data(). This function takes the uri of the excel sheet, the named range, and a boolean if the range has a header.

To get the federal awards data into xule we can capture this data in a vaiable.  We will assign this data to a constant called $GET_DATA. The variable has a $ sign to indicate it is a variable.

constant $GET_DATA = excel-data(sf-sac.xlsx, 'FederalAwards',true)

The excel-data function includes the 3 arguments of excel spreadsheet location, the named range and if the data has a header, which in this case is true.

The image below shows the named range highlighted and the data that will be added to the instance document.

The excel data function will always return the data as a list of rows. In XULE this is represented using lists.  Each row represents a list of values. Each additional row is a component of an outer list.

This range has 22 columns.  Some have data, some do not. The Single Audit taxonomy defines each of these columns using a concept. The first step is to map each of these columns to the Single audit taxonomy.  This can be done in a number of ways. If the spreadsheet contains the elements the mapping is relatively easy. If not then we have to assign the XBRL concept to each column.  This spreadsheet range does not have the XBRL taxonomy elements, so we have to define a map.  We can do this in XULE by defining a dictionary.  Alternatively it could be done using an external mapping file.  For this example we will define the dictionary in the XULE expression as a constant called $ElementMapping.

constant $ElementMapping =
dict(
list(1,"\{https://taxonomies.xbrl.us/grip/2022/grants\}FederalProgramIdentifierAxis"),
list(2,"blank"),
list(3,"\{https://taxonomies.xbrl.us/grip/2022/grants\}FederalAwardingAgencyEnumerated"),
list(4,"\{https://taxonomies.xbrl.us/grip/2022/grants\}CFDANumber"),
list(5,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}AdditionalAwardIdentification"),
list(6,"\{https://taxonomies.xbrl.us/grip/2022/grants\}FederalProgramName"),
list(7,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}AmountExpended"),
list(8,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}GRMLegalEntityAuditClusterName"),
list(9,"blank"),
list(10,"blank"),
list(11,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}FederalLoanOrLoanGuarantee"),
list(12,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}OutstandingLoanBalance"),
list(13,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}DirectAward"),
list(14,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}PassThroughSourceEntityName"),
list(15,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}PassThroughSourceEntityIdentifier"),
list(16,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}AwardPassedThroughToSubrecipients"),
list(17,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}PassThroughAmount"),
list(18,"blank"),
list(19,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}MajorProgram"),
list(20,"blank"),
list(21,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}TypeofSingleAuditOpinion"),
list(22,"\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}GRMLegalEntityAuditFindingsTotalQuantity")
)

In addition to the elements we need to identify the units to use for each column. Units are only applied to numerical values. In this case only the columns 3,7,12,17 and 22 have columns. To perform this mapping we create another dictionary to map the columns to the respective unit. This constant is called $units.

constant $units = dict(
list(3,unit(xbrli:pure)),
list(7,unit(iso4217:USD)),
list(12,unit(iso4217:USD)),
list(17,unit(iso4217:USD)),
list(22,unit(xbrli:pure))
)

Next we need to determine the periods that will be used for the facts that we generate.  We need to determine the reporting period from the spreadsheet. The spreadsheet has a period start date and a period end date.  The period start date is on the excel tab ‘General Info’ in cell F9 and the period end date is on the excel sheet tab ‘General Info’ in cell F12. We can get this data using the excel data function. To make the function easier to read we will define a constant that represents the location of the excel file.

constant $FILING_EXCEL = 
'https://github.com/xbrlus/ACFR-Taxonomy/raw/main/SingleAudit/InstanceCreation/Excel/sf-sac.xlsx'

We can then use this variable in the excel-data function.

excel-data($FILING_EXCEL, 'General Info!F9',false, list('string'))

In this case we are pulling data from a single cell in the spreadsheet. To do this we can reference a tab and cell coordinate rather than a named range. Because this is a single cell there is no header, so the header flag is set as false. You will notice a 4th optional argument that allows the definition of the type. In this case we are going to set the type to a string. We will convert it to a date format later.

Because this date is also reported as a fact in the instance document we are going to put the value into a list, with the second component being the taxonomy element name of FiscalPeriodStartDate.

The following constant can then be defined.

constant $GET_FISCAL_PERIOD_START = list(sum(sum(excel-data($FILING_EXCEL, 'General Info!F9',false, list('string')))),'\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}FiscalPeriodStartDate')

This will return a value of list(‘7/1/2019′,’\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}FiscalPeriodStartDate’). Note how the sum function is used twice. This is done because the value returned for F9 by the excel-data function is list(list(‘7/1/2019’)). The sum functions flatten the two lists to return the string value ‘7/1/2019’.

We do the following to get the end date.

constant $GET_FISCAL_PERIOD_END = list(sum(sum(excel-data($FILING_EXCEL, 'General Info!F12',false, list('string')))),'\{https://taxonomies.xbrl.us/grip/2022/singleAudit\}FiscalPeriodEndDate')

Once we have defined the mapping we can retrieve the data from the spreadsheet to add to our blank instance document. To do this we loop through each row of the spreadsheet and create the facts for each column.

The for loop is defined to loop through each row returned for the $GET_DATA variable.

for $row in $GET_DATA

Next we need to work out the length of the row and loop through each item in the row. This is done as follows:

for $i in range($row.length)

The first column is a row identifier.  We do not need this so we skip it.

if $i == 1
skip

We then check if the column is a blank or if the value in the cell is equal to none.  This is done by looking up the column number in the $elementMapping dictionary and seeing if it has a value of ‘blank’. If it is the cell is skipped. If not we check if the cell has a value of ‘None’, if it does then the cell is skipped.

if $ElementMapping[$i] == "blank" or $row[$i] == 'None'
skip

If the cell is a value then we extract the data. First we get a dimension value for the fact based on the row number and assign to a variable called $member_value.

$member_value = $row[1];

Next we get the value of the cell and assign it to a variable called $sa_value.

$sa_value = $row[$i];

Next we determine if the value is nil, by checking if the cell has a value.

$is-nil = if $row[$i] == ''
 true 
else 
false

Next we get the concept name for the fact based on the Element Mapping dictionary.

$conceptName = $ElementMapping[$i];

Next we get the period associated with the fact.

$period = duration($GET_FISCAL_PERIOD_START[1] ,  $GET_FISCAL_PERIOD_END[1])

Note that the duration function is used to get the period start and period end lists with a string value as the first value of the list. The duration function takes two string values. This is why the excel-data function was used to return string values above.

Finally we get the unit value, by looking up the unit dictionary based on the column we are processing.

$unit_value = if exists($units[$i]) $units[$i] else none ;

Finally we want the rule to fire so we enter a value to return. This can be anything, so we just used true.

The last step is to add all the values we have created to the instance document. This is done using the output attributes discussed above.

Firstly we define the instance to add the values to.

fact-instance $InstanceName

Secondly we add the fact value

fact-value $sa_value

Next we add the concept name to the fact value

fact-concept $conceptName.to-xince

Next we add the dimension for each row.

fact-dimensions dict(list("\{https://taxonomies.xbrl.us/grip/2022/grants\}FederalProgramIdentifierAxis", $member_value)).to-xince

Next we add the entity. This is hard coded but this could be passed as a parameter or read from the spreadsheet.

fact-entity entity('http://some/schema', 'CompanyA').to-xince

Next we add the period of the fact.

fact-period $period.to-xince

Finally we add the units and if the value is nil.

fact-unit $unit_value.to-xince
fact-is-nil  $is-nil

The final output is as follows:

output  federalAwards
for $row in $GET_DATA
for $i in range($row.length)
if $i == 1
skip
else
if $ElementMapping[$i] == "blank" or $row[$i] == 'None'
skip
else
$member_value = $row[1];
$sa_value = $row[$i];
$is-nil = if $row[$i] == '' true else false
$conceptName = $ElementMapping[$i];
$period = duration($GET_FISCAL_PERIOD_START[1] , $GET_FISCAL_PERIOD_END[1])
$unit_value = if exists($units[$i]) $units[$i] else none ;
true
fact-instance $InstanceName
fact-value $sa_value
fact-concept $conceptName.to-xince
fact-dimensions
dict(list("\{https://taxonomies.xbrl.us/grip/2022/grants\}FederalProgramIdentifierAxis", $member_value)).to-xince
fact-entity entity('http://some/schema', 'CompanyA').to-xince
fact-period $period.to-xince
fact-unit $unit_value.to-xince
fact-is-nil $is-nil

Comment