diff --git a/JeffFerguson.Gepsio.Test/IssueTests/SingleMethodIssueTests.cs b/JeffFerguson.Gepsio.Test/IssueTests/SingleMethodIssueTests.cs index be4f28e..dd62f04 100644 --- a/JeffFerguson.Gepsio.Test/IssueTests/SingleMethodIssueTests.cs +++ b/JeffFerguson.Gepsio.Test/IssueTests/SingleMethodIssueTests.cs @@ -1,13 +1,7 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; -using System.Xml; - -using JeffFerguson.Gepsio.IoC; -using JeffFerguson.Gepsio.Xml.Implementation.SystemXml; - using Microsoft.VisualStudio.TestTools.UnitTesting; namespace JeffFerguson.Gepsio.Test.IssueTests @@ -79,9 +73,9 @@ public void VerifyFixForIssue9() { var xbrlDoc = new XbrlDocument(); xbrlDoc.Load("https://www.sec.gov/Archives/edgar/data/1688568/000168856818000036/csc-20170331.xml"); - foreach(var validationError in xbrlDoc.ValidationErrors) + foreach (var validationError in xbrlDoc.ValidationErrors) { - if(validationError.Message.Contains("http://xbrl.sec.gov/dei/2014-01-31") == true) + if (validationError.Message.Contains("http://xbrl.sec.gov/dei/2014-01-31") == true) { Assert.Fail(); } @@ -126,54 +120,54 @@ public void VerifyFixForIssue11() } } - /// - /// Ensure that decimal number parsing is culture independant. - /// For example french uses , (comma) as decimal separator. - /// - [TestMethod] - public void VerifyFixForIssue16() - { - try - { - CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo( "fr" ); - var xbrlDoc = new XbrlDocument( ); - xbrlDoc.Load( "https://www.sec.gov/Archives/edgar/data/1688568/000168856818000036/csc-20170331.xml" ); - } - catch(FormatException) - { - Assert.Fail( "Decimal number format should be culture independant." ); - } - } + /// + /// Ensure that decimal number parsing is culture independant. + /// For example french uses , (comma) as decimal separator. + /// + [TestMethod] + public void VerifyFixForIssue16() + { + try + { + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fr"); + var xbrlDoc = new XbrlDocument(); + xbrlDoc.Load("https://www.sec.gov/Archives/edgar/data/1688568/000168856818000036/csc-20170331.xml"); + } + catch (FormatException) + { + Assert.Fail("Decimal number format should be culture independant."); + } + } - /// - /// No Support for xsd:import in Schema Handling. - /// As a consequence in ESRD taxonomy, label linkbases are not discovered. - /// - [TestMethod] - public void VerifyFixForIssue50() - { - var xbrlDoc = new XbrlDocument( ); - xbrlDoc.Load( @"..\..\..\IssueTests\50\efrag-2026-12-31-en.xbrl" ); - var xbrlSchema = xbrlDoc.XbrlFragments[0].Schemas[0]; + /// + /// No Support for xsd:import in Schema Handling. + /// As a consequence in ESRD taxonomy, label linkbases are not discovered. + /// + [TestMethod] + public void VerifyFixForIssue50() + { + var xbrlDoc = new XbrlDocument(); + xbrlDoc.Load(@"..\..\..\IssueTests\50\efrag-2026-12-31-en.xbrl"); + var xbrlSchema = xbrlDoc.XbrlFragments[0].Schemas[0]; - Assert.IsTrue( xbrlSchema.DefinitionLinkbases.Any() ); //definition linkbases are in main schema - Assert.IsTrue( xbrlSchema.LabelLinkbases.Any() ); //label linkbases are in imported schema - } + Assert.IsTrue(xbrlSchema.DefinitionLinkbases.Any()); //definition linkbases are in main schema + Assert.IsTrue(xbrlSchema.LabelLinkbases.Any()); //label linkbases are in imported schema + } - /// - /// Error parsing PresentationArc Order value when culture is french. - /// - [TestMethod] - public void VerifyFixForIssue52() - { - CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo( "fr" ); - var xbrlDoc = new XbrlDocument( ); - xbrlDoc.Load( @"..\..\..\IssueTests\52\efrag-2026-12-31-en.xbrl" ); - var nodes = xbrlDoc.XbrlFragments[0].GetPresentableFactTree( ).TopLevelNodes; + /// + /// Error parsing PresentationArc Order value when culture is french. + /// + [TestMethod] + public void VerifyFixForIssue52() + { + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fr"); + var xbrlDoc = new XbrlDocument(); + xbrlDoc.Load(@"..\..\..\IssueTests\52\efrag-2026-12-31-en.xbrl"); + var nodes = xbrlDoc.XbrlFragments[0].GetPresentableFactTree().TopLevelNodes; - Assert.AreEqual( nodes[0].ChildNodes[3].PresentationLinkbaseLocator.HrefResourceId, "esrs_UndertakingIsNotRequiredToDrawupFinancialStatements" ); - Assert.AreEqual( nodes[0].ChildNodes[4].PresentationLinkbaseLocator.HrefResourceId, "esrs_DisclosureOfExtentToWhichSustainabilityStatementCoversUpstreamAndDownstreamValueChainExplanatory" ); - } + Assert.AreEqual(nodes[0].ChildNodes[3].PresentationLinkbaseLocator.HrefResourceId, "esrs_UndertakingIsNotRequiredToDrawupFinancialStatements"); + Assert.AreEqual(nodes[0].ChildNodes[4].PresentationLinkbaseLocator.HrefResourceId, "esrs_DisclosureOfExtentToWhichSustainabilityStatementCoversUpstreamAndDownstreamValueChainExplanatory"); + } /// /// Ensure that the taxonomy at http://xbrl.fasb.org/us-gaap/2018/elts/us-gaap-2018-01-31.xsd @@ -216,5 +210,22 @@ public async Task VerifyFixForIssue22Async() Assert.Fail(); } } + + /// + /// Verify that GetHashCode() can be called on schema elements that lack defined ID attributes. + /// + /// + /// The hash code returned is not important to the test. The test is simply in place so that the + /// GetHashCode() method can be called without a NullReferenceException being thrown. + /// + [TestMethod] + public void VerifyFixForIssue57() + { + var xbrlDoc = new XbrlDocument(); + xbrlDoc.Load("http://xbrlsite.com/US-GAAP/BasicExample/2010-09-30/abc-20101231.xml"); + var firstFragment = xbrlDoc.XbrlFragments[0]; + var elementWithoutDefinedId = firstFragment.Schemas.GetElement("explicitMember"); + var hashCode = elementWithoutDefinedId.GetHashCode(); + } } } diff --git a/JeffFerguson.Gepsio/Xsd/Element.cs b/JeffFerguson.Gepsio/Xsd/Element.cs index 9324a38..3ebd3ad 100644 --- a/JeffFerguson.Gepsio/Xsd/Element.cs +++ b/JeffFerguson.Gepsio/Xsd/Element.cs @@ -110,9 +110,9 @@ internal Element(XbrlSchema Schema, ISchemaElement SchemaElement) { this.Schema = Schema; thisSchemaElement = SchemaElement; - this.Id = SchemaElement.Id; - this.Name = SchemaElement.Name; - this.Default = string.IsNullOrEmpty(SchemaElement.Default) == false ? SchemaElement.Default : string.Empty; + this.Id = string.IsNullOrEmpty(SchemaElement.Id) ? string.Empty : SchemaElement.Id; + this.Name = string.IsNullOrEmpty(SchemaElement.Name) ? string.Empty : SchemaElement.Name; + this.Default = string.IsNullOrEmpty(SchemaElement.Default) ? string.Empty : SchemaElement.Default; this.IsAbstract = SchemaElement.IsAbstract; this.TypeName = SchemaElement.SchemaTypeName; SetSubstitutionGroup(SchemaElement.SubstitutionGroup); @@ -145,7 +145,7 @@ public override bool Equals(object obj) /// public override int GetHashCode() { - return this.Id.GetHashCode(); + return this.Name.GetHashCode(); } //------------------------------------------------------------------------------------ diff --git a/release-notes.md b/release-notes.md index 1017d11..7dfe696 100644 --- a/release-notes.md +++ b/release-notes.md @@ -13,12 +13,11 @@ The [Wiki](https://github.com/JeffFerguson/gepsio/wiki) area of [the Github repo Thank you for your contributions! # Design - - No changes from the previous release. # Bug Fixes -- No changes from the previous release. +- Fixed a bug which caused calls to `GetHashCode()` on schema `Element` objects without explicitly defined `ID` attributes to throw a `NullReferenceException`. This fixes [Issue 57](https://github.com/JeffFerguson/gepsio/issues/57). # Breaking Changes