//------------------------------------------------------------------------------- //------------------------------------------------------------------------------- internal XbrlSchema(XbrlFragment ContainingXbrlFragment, string SchemaFilename, string BaseDirectory) { this.Fragment = ContainingXbrlFragment; this.SchemaReferencePath = GetFullSchemaPath(SchemaFilename, BaseDirectory); this.LoadPath = this.SchemaReferencePath; try { if (ReadAndCompile(this.SchemaReferencePath) == false) { return; } } catch (FileNotFoundException fnfEx) { StringBuilder MessageBuilder = new StringBuilder(); string StringFormat = AssemblyResources.GetName("FileNotFoundDuringSchemaCreation"); MessageBuilder.AppendFormat(StringFormat, this.SchemaReferencePath); this.Fragment.AddValidationError(new SchemaValidationError(this, MessageBuilder.ToString(), fnfEx)); return; } catch (WebException webEx) { // Check to see if we got an HTTP 404 back from an attempt to open a schema up from a // URL. If we did, check to see if the schema is available locally. Some taxonomies are // specified through URLs that don't actually exist in a physical form but just appear // as placeholders. The Dutch taxonomies are an example of this. An XBRL instance might // have a schema reference of "http://archprod.service.eogs.dk/taxonomy/20171001/ // entryDanishGAAPBalanceSheetAccountFormIncomeStatementByNatureIncludingManagements // ReviewStatisticsAndTax20171001.xsd", for example, but there might not be a schema // at that location. It is assumed, in these cases, that the schema is available with // the XBRL instance itself. Check for a locally-stored schema. var localSchemaAvailable = false; var schemaLocalPath = string.Empty; var webResponse = webEx.Response as HttpWebResponse; if (webResponse == null || webResponse.StatusCode == HttpStatusCode.NotFound) { schemaLocalPath = BuildSchemaPathLocalToFragment(ContainingXbrlFragment, SchemaFilename); try { localSchemaAvailable = ReadAndCompile(schemaLocalPath); } catch (FileNotFoundException) { localSchemaAvailable = false; } } if (localSchemaAvailable == false) { StringBuilder MessageBuilder = new StringBuilder(); string StringFormat = AssemblyResources.GetName("WebExceptionThrownDuringSchemaCreation"); MessageBuilder.AppendFormat(StringFormat, this.SchemaReferencePath); this.Fragment.AddValidationError(new SchemaValidationError(this, MessageBuilder.ToString(), webEx)); return; } this.LoadPath = schemaLocalPath; } thisSchemaDocument = Container.Resolve <IDocument>(); this.thisLinkbaseDocuments = new LinkbaseDocumentCollection(); this.RoleTypes = new List <RoleType>(); thisSchemaDocument.Load(this.LoadPath); this.NamespaceManager = Container.Resolve <INamespaceManager>(); this.NamespaceManager.Document = thisSchemaDocument; this.NamespaceManager.AddNamespace("schema", XbrlSchema.XmlSchemaNamespaceUri); ReadSchemaNode(); ReadSimpleTypes(); ReadComplexTypes(); ReadElements(); LookForAnnotations(); }
/// <summary> /// Validates a given summation concept. /// </summary> /// <param name="CurrentCalculationLink"> /// The calculation link that defines the given summation concept. /// </param> /// <param name="CurrentSummationConcept"> /// The summation concept to be validated. /// </param> /// <param name="FactList"> /// The collection of items that should be searched when looking for summation or contributing items. /// </param> private void ValidateSummationConcept(CalculationLink CurrentCalculationLink, SummationConcept CurrentSummationConcept, FactCollection FactList) { Element SummationConceptElement = LocateElement(CurrentSummationConcept.SummationConceptLocator); Item SummationConceptItem = LocateItem(SummationConceptElement, FactList); // If the summation concept item doesn't exist, then there is no calculation // to perform. if (SummationConceptItem == null) { return; } // If the summation concept item has a "nil" value, then there is no calculation // to perform. if (SummationConceptItem.NilSpecified == true) { return; } double SummationConceptRoundedValue = SummationConceptItem.RoundedValue; double ContributingConceptRoundedValueTotal = 0; var ContributingConceptItemsFound = false; foreach (Locator CurrentLocator in CurrentSummationConcept.ContributingConceptLocators) { // Some decisions need to be made before the code can actually add the value of the // contributing concept to the total that the code is keeping. var IncludeContributingConceptItemInCalculation = true; // Find the calculation arc for the given calculation link. CalculationArc ContributingConceptCalculationArc = CurrentCalculationLink.GetCalculationArc(CurrentLocator); if (ContributingConceptCalculationArc == null) { IncludeContributingConceptItemInCalculation = false; } // Find the elemement for the given locator. Element ContributingConceptElement = LocateElement(CurrentLocator); if (ContributingConceptElement == null) { IncludeContributingConceptItemInCalculation = false; } // Find all items for the given element. If there is more than one, and at least // one of them is not p-equals with at least one of the other ones, then // the entire calculation validation is forfeit, according to test 397.12 in // the XBRL-CONF-CR3-2007-03-05 conformance suite. var AllMatchingItems = LocateItems(ContributingConceptElement, FactList); if (AllItemsNotPEquals(AllMatchingItems) == false) { return; } // Find the item for the given element. if (AllMatchingItems.Count == 0) { IncludeContributingConceptItemInCalculation = false; } else { foreach (var ContributingConceptItem in AllMatchingItems) { // Ensure that the contributing concept item is context-equals // with the summation item. if (IncludeContributingConceptItemInCalculation == true) { if (SummationConceptItem.ContextEquals(ContributingConceptItem) == false) { IncludeContributingConceptItemInCalculation = false; } } // Ensure that the contributing concept item is unit-equals // with the summation item. if (IncludeContributingConceptItemInCalculation == true) { if (SummationConceptItem.UnitEquals(ContributingConceptItem) == false) { IncludeContributingConceptItemInCalculation = false; } } // Ensure that the contributing concept item does not have a nil value. if (IncludeContributingConceptItemInCalculation == true) { if (ContributingConceptItem.NilSpecified == true) { IncludeContributingConceptItemInCalculation = false; } } // If the code is still interested in including the contributing concept item // in the calculation, then get its rounded value and add it to the total. if (IncludeContributingConceptItemInCalculation == true) { ContributingConceptItemsFound = true; double ContributingConceptRoundedValue = ContributingConceptItem.RoundedValue; if (ContributingConceptCalculationArc.Weight != (decimal)(1.0)) { ContributingConceptRoundedValue = ContributingConceptRoundedValue * (double)(ContributingConceptCalculationArc.Weight); } ContributingConceptRoundedValueTotal += ContributingConceptRoundedValue; } } } } if (ContributingConceptItemsFound == true) { ContributingConceptRoundedValueTotal = SummationConceptItem.Round(ContributingConceptRoundedValueTotal); if (SummationConceptRoundedValue != ContributingConceptRoundedValueTotal) { StringBuilder MessageBuilder = new StringBuilder(); string StringFormat = AssemblyResources.GetName("SummationConceptError"); MessageBuilder.AppendFormat(StringFormat, SummationConceptItem.Name, SummationConceptRoundedValue, ContributingConceptRoundedValueTotal); ValidatedFragment.AddValidationError(new SummationConceptValidationError(CurrentSummationConcept, MessageBuilder.ToString())); return; } } }