public void PartialDocument_PartialSerializedDocumentCreated() { Phase lMockPhase1 = new Phase(); lMockPhase1.ID = "error"; SchematronDocument lDocument = new SchematronDocument(); lDocument.Phases.Add(lMockPhase1); SchematronDocumentSerializer lBuilder = new SchematronDocumentSerializer(); string lSerializedModel = lBuilder.SerializeDocument(lDocument); Assert.IsFalse(string.IsNullOrEmpty(lSerializedModel), "A valid partial document was not created"); XmlDocument lSerializedDocument = new XmlDocument(); lSerializedDocument.LoadXml(lSerializedModel); XmlNamespaceManager lManager = new XmlNamespaceManager(lSerializedDocument.NameTable); lManager.AddNamespace("sch", "http://purl.oclc.org/dsdl/schematron"); XmlNode lPhaseNode = lSerializedDocument.SelectSingleNode(string.Format("/sch:schema/sch:phase[@id='{0}']", lMockPhase1.ID), lManager); Assert.IsNotNull(lPhaseNode, "Phase node was not located in the document"); XmlNode lActiveNode = lPhaseNode.FirstChild; Assert.IsNull(lActiveNode, "Active node was not created properly on Phase node"); }
public Rule FindRule(SchematronDocument a, string id) { foreach (Pattern p in a.Patterns) { foreach (Rule r in p.Rules) { if (r.ID == id) return r; } } throw new Exception(String.Format("'{0}' is not a rule.", id)); }
internal virtual string SerializeSchematronDocument(SchematronDocument doc, Dictionary <string, string> namespaces) { var ser = new SchematronDocumentSerializer(); // Add the namespaces to the serializer foreach (string cPrefix in namespaces.Keys) { ser.AddNamespace(cPrefix, namespaces[cPrefix]); } var output = ser.SerializeDocument(doc); return(output); }
public string SerializeDocument(SchematronDocument aDocument) { this.CreateHeaderAndRoot(); // Phases must be placed at the top of the document this.RegisterPhases(aDocument.Phases); // Patterns must be placed after all of the phases foreach (Phase lCurrentPhase in aDocument.Phases) { this.RegisterPatterns(lCurrentPhase.ActivePatterns); } return(this.CreateXmlString()); }
public void ReadingISO() { SchematronDocument doc = new SchematronDocument(); doc.Load("Schematron/Samples/AllISO.sch"); Assertion a = doc.Patterns["testing"].Rules["foo"].Assertions[0]; Assert.AreEqual("diag-1", a.Diagnostics); Assert.AreEqual("flag", a.Flag); Assert.AreEqual("fpi", a.Fpi); Assert.AreEqual("icon", a.Icon); Assert.AreEqual("foo-rule", a.ID); Assert.AreEqual("foo must be bar", a.Message.ToString()); Assert.AreEqual("role", a.Role); Assert.AreEqual("see", a.See); Assert.AreEqual("subject", a.Subject); Assert.AreEqual(". = 'bar'", a.Test); }
public void MinimalIsValid() { SchematronDocument full = SchematronReader.ReadSchematron("Schematron/Samples/All.sch"); SchematronDocument minimal = new Compiler().Compile(full); StringBuilder schematron = new StringBuilder(); minimal.Save(schematron); XmlDocument minimalDocument = new XmlDocument(); minimalDocument.LoadXml(schematron.ToString()); SchematronValidator validator = new SchematronValidator(Schematron.Default.IsoSchematronSchema); validator.ValidationPhase = "minimal"; validator.Validate(minimalDocument); SchematronDocument minimal2 = new SchematronDocument(); minimal2.Load(schematron); }
public void EmptyDocument_NoException() { SchematronDocument lDocument = new SchematronDocument(); SchematronDocumentSerializer lBuilder = new SchematronDocumentSerializer(); string lSerializedModel = lBuilder.SerializeDocument(lDocument); Assert.IsFalse(string.IsNullOrEmpty(lSerializedModel), "A valid but empty document (root element only) was not created"); XmlDocument lSerializedDocument = new XmlDocument(); lSerializedDocument.LoadXml(lSerializedModel); XmlNamespaceManager lManager = new XmlNamespaceManager(lSerializedDocument.NameTable); lManager.AddNamespace("sch", "http://www.ascc.net/xml/schematron"); XmlNode lPhaseNode = lSerializedDocument.SelectSingleNode("/schema/sch:phase", lManager); Assert.IsNull(lPhaseNode, "Phase node was not located in the document"); }
/// <summary> /// Generates a schematron xml (string) for the given IG in the database. /// </summary> /// <returns>Returns a string representing the generated schematron document (XML).</returns> public string Generate() { if (ig == null) { return(null); //thow an exception? } // Clear the cloned constraints whenever we run generate so that we don't get duplicate exceptions this.clonedConstraints.Clear(); var errorPhase = new Phase() { ID = "errors" }; var warningPhase = new Phase() { ID = "warnings" }; var schematronDocument = new SchematronDocument(); if (this.includeCustom) { IEnumerable <ImplementationGuideSchematronPattern> customErrorPatterns = ig.SchematronPatterns.Where(y => y.Phase == "errors"); IEnumerable <ImplementationGuideSchematronPattern> customWarningPatterns = ig.SchematronPatterns.Where(y => y.Phase == "warnings"); AddCustomPatterns(errorPhase, customErrorPatterns); AddCustomPatterns(warningPhase, customWarningPatterns); } // TRIF-909: Remove closed template rules from Trifolia Schematron generation //AddDocumentLevelTemplateConstraints(this.ig, errorPhase); foreach (var template in templates) { try { AddTemplate(template, errorPhase, warningPhase); if (!template.IsOpen) { AddClosedTemplateConstraints(template, errorPhase); } } catch (Exception ex) { Log.For(this).Error("Error generating schematron for template {0} ({1})", ex, template.Name, template.Oid); throw new Exception( string.Format( "Unknown error occurred while generating schematron at {0}. Please notify a system administrator of this error.", DateTime.Now.ToShortTimeString()), ex); } } schematronDocument.Phases.Add(errorPhase); schematronDocument.Phases.Add(warningPhase); // Prepare a list of namespaces to add to the schematron document var namespacesList = (from t in templates join tt in this.rep.TemplateTypes on t.TemplateTypeId equals tt.Id join igt in this.rep.ImplementationGuideTypes on tt.ImplementationGuideTypeId equals igt.Id select new { Prefix = igt.SchemaPrefix, URI = igt.SchemaURI }).Distinct(); Dictionary <string, string> namespaces = new Dictionary <string, string>(); foreach (var cNamespaceItem in namespacesList) { namespaces.Add(cNamespaceItem.Prefix, cNamespaceItem.URI); } return(SerializeSchematronDocument(schematronDocument, namespaces)); }
public void BuildAdvanceDirectiveObservationDocument_1stLevelOnly() { var sectionCount = 1; var phase = new Phase(); phase.ID = "error"; var document = new SchematronDocument(); document.Phases.Add(phase); var doc = new DocumentTemplate("cda"); doc.AddElement(new DocumentTemplateElement("observation")); doc.ChildElements[0].AddAttribute(new DocumentTemplateElementAttribute("classCode", "OBS")); doc.ChildElements[0].AddAttribute(new DocumentTemplateElementAttribute("moodCode", "EVN")); doc.AddElement(new DocumentTemplateElement("templateId")); doc.ChildElements[1].AddAttribute(new DocumentTemplateElementAttribute("root", "2.16.840.1.113883.10.20.22.4.48")); doc.AddElement(new DocumentTemplateElement("id")); doc.AddElement(new DocumentTemplateElement("code")); doc.ChildElements[doc.ChildElements.Count - 1].AddAttribute(new DocumentTemplateElementAttribute("xsi-type", "CE", "2.16.840.1.113883.1.11.20.2")); doc.AddElement(new DocumentTemplateElement("statusCode")); doc.ChildElements[doc.ChildElements.Count - 1].AddAttribute(new DocumentTemplateElementAttribute("code", "completed", "2.16.840.1.113883.5.14")); var participantElement = new DocumentTemplateElement("participant"); doc.ChildElements[0].AddElement(participantElement); participantElement.AddAttribute(new DocumentTemplateElementAttribute("typeCode", "VRF")); var templateIdElement = new DocumentTemplateElement("templateId"); templateIdElement.AddAttribute(new DocumentTemplateElementAttribute("root", "2.16.840.1.113883.10.20.1.58")); participantElement.AddElement(templateIdElement); var timeElement = new DocumentTemplateElement("time"); timeElement.AddAttribute(new DocumentTemplateElementAttribute("xsi:type", "TS")); participantElement.AddElement(timeElement); var participantRoleElement = new DocumentTemplateElement("participantRole"); participantElement.AddElement(participantRoleElement); var contextBuilder = new ContextBuilder(doc.ChildElements[0], "cda"); var rule = new Rule(); rule.Context = contextBuilder.GetFullyQualifiedContextString(); var assertionBuilder = new AssertionLineBuilder(doc.ChildElements[0].Attributes[0], templateIdentifierXpath, templateVersionIdentifierXpath); //"OBS" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..1 @classCode='OBS' Observation (CodeSystem: HL7ActClass 2.16.840.1.113883.5.6) (CONF:8648).", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..1")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); assertionBuilder = new AssertionLineBuilder(doc.ChildElements[0].Attributes[1], templateIdentifierXpath, templateVersionIdentifierXpath); //"EVN" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..1 @moodCode='EVN' Event (CodeSystem: ActMood 2.16.840.1.113883.5.1001) (CONF:8649).", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..1")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); var pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); rule = new Rule(); contextBuilder = new ContextBuilder(doc.ChildElements[1], "cda"); rule.Context = contextBuilder.GetFullyQualifiedContextString(); assertionBuilder = new AssertionLineBuilder(doc.ChildElements[1], templateIdentifierXpath, templateVersionIdentifierXpath); //"templateId[@rootCode]" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..1 @root='2.16.840.1.113883.10.20.22.4.48' (CONF:10485).", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..1")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); sectionCount++; pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); rule = new Rule(); contextBuilder = new ContextBuilder(doc.ChildElements[2], "cda"); rule.Context = contextBuilder.GetFullyQualifiedContextString(); assertionBuilder = new AssertionLineBuilder(doc.ChildElements[2], templateIdentifierXpath, templateVersionIdentifierXpath); //"1..* id" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..* id (CONF:8654)", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..*")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); sectionCount++; pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); rule = new Rule(); contextBuilder = new ContextBuilder(doc.ChildElements[3], "cda"); rule.Context = contextBuilder.GetFullyQualifiedContextString(); assertionBuilder = new AssertionLineBuilder(doc.ChildElements[3], templateIdentifierXpath, templateVersionIdentifierXpath); //"1..1 code @xsi:type='CE' valueset = 2.16.840.1.113883.1.11.20.2" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..1 code with @xsi:type='CE', where the @code SHOULD be selected from ValueSet AdvanceDirectiveTypeCode 2.16.840.1.113883.1.11.20.2 STATIC 2006-10-17 (CONF:8651).", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..1")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); sectionCount++; pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); rule = new Rule(); contextBuilder = new ContextBuilder(doc.ChildElements[3], "cda"); rule.Context = contextBuilder.GetFullyQualifiedContextString(); assertionBuilder = new AssertionLineBuilder(doc.ChildElements[3], templateIdentifierXpath, templateVersionIdentifierXpath); //"1..1 statusCode @code='completed' valueset = 2.16.840.1.113883.1.11.20.2" rule.Assertions.Add(new Assertion() { AssertionMessage = "SHALL contain 1..1 code with @xsi:type='CE', where the @code SHOULD be selected from ValueSet AdvanceDirectiveTypeCode 2.16.840.1.113883.1.11.20.2 STATIC 2006-10-17 (CONF:8651).", Test = assertionBuilder.WithCardinality(CardinalityParser.Parse("1..1")).WithinContext(contextBuilder.GetRelativeContextString()).ConformsTo(Conformance.SHALL).ToString() }); sectionCount++; pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); rule = new Rule(); contextBuilder = new ContextBuilder(doc.ChildElements[1].Attributes[0], "cda"); rule.Context = contextBuilder.GetFullyQualifiedContextString(); var childtemplateIdElementAssertionBuilder = new AssertionLineBuilder(templateIdElement.Attributes[0], templateIdentifierXpath, templateVersionIdentifierXpath) //templateId/@root .WithCardinality(CardinalityParser.Parse("1..1")) .ConformsTo(Conformance.SHALL) .WithinContext("cda:"); var childParticipantElementAssertionBuilder = new AssertionLineBuilder(participantRoleElement, templateIdentifierXpath, templateVersionIdentifierXpath) .WithCardinality(CardinalityParser.Parse("1..*")) .ConformsTo(Conformance.SHALL) .WithinContext("cda:"); var childTimeElementAssertionBuilder = new AssertionLineBuilder(timeElement, templateIdentifierXpath, templateVersionIdentifierXpath) .WithCardinality(CardinalityParser.Parse("0..1")) .ConformsTo(Conformance.SHOULD) .WithinContext("cda:"); assertionBuilder = new AssertionLineBuilder(participantElement, templateIdentifierXpath, templateVersionIdentifierXpath); //participant rule.Assertions.Add(new Assertion() { AssertionMessage = "should contain 1..* participant (CONF:8662), participant should contain 0..1 time (CONF:8665), the data type of Observation/participant/time in a verification SHALL be TS (time stamp) (CONF:8666), participant shall contain 1..1 participantRole (CONF:8825), participant shall contain 1..1 @typeCode=VRF 'Verifier' (CodeSystem: 2.16.840.1.113883.5.90) (CONF:8663), participant shall contain 1..1 templateId (CONF:8664), templateId shall contain 1..1 @root=2.16.840.1.113883.10.20.1.58 (CONF:10486)", Test = assertionBuilder .WithCardinality(CardinalityParser.Parse("1..*")) .WithinContext("cda:") .ConformsTo(Conformance.SHALL) .WithChildElementBuilder(childTimeElementAssertionBuilder) .WithChildElementBuilder(childParticipantElementAssertionBuilder) .WithChildElementBuilder(childtemplateIdElementAssertionBuilder) .ToString() }); sectionCount++; pattern = new Pattern(); pattern.ID = sectionCount.ToString(); pattern.Name = string.Format("pattern-{0}-errors", pattern.ID); pattern.Rules.Add(rule); phase.ActivePatterns.Add(pattern); var builder = new SchematronDocumentSerializer(); string serializedModel = builder.SerializeDocument(document); Assert.IsFalse(string.IsNullOrEmpty(serializedModel), "No string returned from serialize document"); string[] lModelLines = serializedModel.Split('\n'); Assert.IsNotNull(lModelLines, "The generated string was not split on lines"); Assert.IsTrue(lModelLines.Length > 1, "The generated string was not split on lines"); }
public void ValidSchematronDocument_1Rule_1Assertion_ValidSchematronDocumentEmitted() { Assertion lMockAssertion = new Assertion(); lMockAssertion.AssertionMessage = "This test fails"; lMockAssertion.Test = "count(@code) > 1"; Rule lRule = new Rule(); lRule.Assertions.Add(lMockAssertion); lRule.Context = "cda:code"; Pattern lPattern = new Pattern(); lPattern.ID = "pattern1"; lPattern.Name = "mock-pattern"; lPattern.Rules.Add(lRule); Phase lMockPhase1 = new Phase(); lMockPhase1.ID = "error"; lMockPhase1.ActivePatterns.Add(lPattern); SchematronDocument lDocument = new SchematronDocument(); lDocument.Phases.Add(lMockPhase1); SchematronDocumentSerializer lBuilder = new SchematronDocumentSerializer(); string lSerializedModel = lBuilder.SerializeDocument(lDocument); Assert.IsFalse(string.IsNullOrEmpty(lSerializedModel), "A valid Schematron document was not created!"); XmlDocument lSerializedDocument = new XmlDocument(); lSerializedDocument.LoadXml(lSerializedModel); XmlNamespaceManager lManager = new XmlNamespaceManager(lSerializedDocument.NameTable); lManager.AddNamespace("sch", "http://purl.oclc.org/dsdl/schematron"); XmlNode lPhaseNode = lSerializedDocument.SelectSingleNode(string.Format("/sch:schema/sch:phase[@id='{0}']", lMockPhase1.ID), lManager); Assert.IsNotNull(lPhaseNode, "Phase node was not located in the document"); XmlNode lActiveNode = lPhaseNode.FirstChild; Assert.IsNotNull(lActiveNode, "Active node was not created properly on Phase node"); Assert.IsNotNull(lActiveNode.Attributes, "Active node attributes were not created properly"); var lExistingAttributes = from XmlAttribute a in lActiveNode.Attributes where a.Name.Equals("pattern", StringComparison.InvariantCultureIgnoreCase) select a; Assert.IsNotNull(lExistingAttributes, "Active node did not contain an attribute named 'pattern'"); Assert.IsTrue(lExistingAttributes.Any(), "Active node did not contain an attribute named 'pattern'"); Assert.AreEqual("pattern1", lActiveNode.Attributes["pattern"].Value, "Pattern attribute on Active was invalid"); XmlNode lPatternNode = lSerializedDocument.SelectSingleNode(string.Format("/sch:schema/sch:pattern[@id='{0}']", lPattern.ID), lManager); Assert.IsNotNull(lPatternNode, "The desired pattern node was not found"); XmlNode lRuleNode = lSerializedDocument.SelectSingleNode( string.Format("/sch:schema/sch:pattern[@id='{0}']/sch:rule[@context='{1}']", lPattern.ID, lRule.Context), lManager); Assert.IsNotNull(lRuleNode, "The rule node did not exist in the pattern node"); }
/// <summary> /// <see cref="SchemaValidator"/> static constructor with an enumerated schematron content for NHS messages) /// </summary> /// <param name="schematronDocument">Enumerated schematron content, the resources is contained wihtin Messaging.Core assembly</param> /// <returns></returns> public static SchematronValidator Create(SchematronDocument schematronDocument) => schematronDocument switch {