diff --git a/RDFSharp.Test/Model/Validation/RDFValidationEngineTest.cs b/RDFSharp.Test/Model/Validation/RDFValidationEngineTest.cs index 3c222515..cb7a3bd3 100644 --- a/RDFSharp.Test/Model/Validation/RDFValidationEngineTest.cs +++ b/RDFSharp.Test/Model/Validation/RDFValidationEngineTest.cs @@ -482,7 +482,87 @@ public void ShouldWorkWithRDFXMLDeserializationOfID() - + +"; + MemoryStream dataStream = new MemoryStream(); + using (StreamWriter dataStreamWriter = new StreamWriter(dataStream)) + dataStreamWriter.WriteLine(graphData); + RDFGraph dataGraph = RDFXml.Deserialize(new MemoryStream(dataStream.ToArray()), null); + + //Validate + RDFValidationReport validationReport = shapesGraph.Validate(dataGraph); + + Assert.IsFalse(validationReport.Conforms); + Assert.IsTrue(validationReport.ResultsCount == 1); + Assert.IsTrue(validationReport.Results[0].Severity == RDFValidationEnums.RDFShapeSeverity.Violation); + Assert.IsTrue(validationReport.Results[0].ResultMessages.Count == 1); + Assert.IsTrue(validationReport.Results[0].ResultMessages[0].Equals(new RDFPlainLiteral("Cardinality violation. Lower bound shall be 1. exns:Parent.Child-cardinality"))); + Assert.IsTrue(validationReport.Results[0].FocusNode.Equals(new RDFResource("http://test.com/#parent1"))); + Assert.IsNull(validationReport.Results[0].ResultValue); + Assert.IsTrue(validationReport.Results[0].ResultPath.Equals(new RDFResource("http://ex.com/ns#Child.Parent"))); + Assert.IsTrue(validationReport.Results[0].SourceConstraintComponent.Equals(RDFVocabulary.SHACL.MIN_COUNT_CONSTRAINT_COMPONENT)); + Assert.IsTrue(validationReport.Results[0].SourceShape.Equals(new RDFResource("http://ex.com/ns#Parent.Child-cardinality"))); + } + [TestMethod] + public void ShouldWorkWithRDFXMLDeserializationOfID2() + { + //ShapesGraph + string shapesData = +@" +@prefix rdf: . +@prefix sh: . +@prefix exns: . + +exns:Parent rdf:type sh:NodeShape ; + sh:property exns:Parent.Child-cardinality ; + sh:targetClass exns:Parent . + +exns:Child rdf:type sh:NodeShape ; + sh:property exns:Child.Parent-cardinality ; + sh:targetClass exns:Child . + +exns:Parent.Child-cardinality + rdf:type sh:PropertyShape ; + sh:description ""This constraint validates the cardinality of the association at the inverse direction."" ; + sh:group exns:CardinalityGroup ; + sh:message ""Cardinality violation. Lower bound shall be 1. exns:Parent.Child-cardinality"" ; + sh:minCount 1 ; + sh:name ""Parent.Child-cardinality"" ; + sh:order 0 ; + sh:path [ sh:inversePath exns:Child.Parent ] ; + sh:severity sh:Violation . + +exns:Child.Parent-cardinality + rdf:type sh:PropertyShape ; + sh:description ""This constraint validates the cardinality of the association at the inverse direction."" ; + sh:group exns:CardinalityGroup ; + sh:message ""Cardinality violation. A child should have at least one parent. exns:Parent.Child-cardinality"" ; + sh:minCount 1 ; + sh:name ""Parent.Child-cardinality"" ; + sh:order 0 ; + sh:path exns:Child.Parent ; + sh:severity sh:Violation ."; + MemoryStream shapeStream = new MemoryStream(); + using (StreamWriter shapeStreamWriter = new StreamWriter(shapeStream)) + shapeStreamWriter.WriteLine(shapesData); + RDFGraph shapesGraphObject = RDFTurtle.Deserialize(new MemoryStream(shapeStream.ToArray()), null); + RDFShapesGraph shapesGraph = RDFShapesGraph.FromRDFGraph(shapesGraphObject); + + //DataGraph + string graphData = +@" + + + + + + + + "; MemoryStream dataStream = new MemoryStream(); using (StreamWriter dataStreamWriter = new StreamWriter(dataStream)) diff --git a/RDFSharp.Test/RDFSharp.Test.csproj b/RDFSharp.Test/RDFSharp.Test.csproj index bd12614d..37abf597 100644 --- a/RDFSharp.Test/RDFSharp.Test.csproj +++ b/RDFSharp.Test/RDFSharp.Test.csproj @@ -3,7 +3,7 @@ RDFSharp.Test RDFSharp.Test $(Version) - 3.6.0 + 3.6.1 Marco De Salvo Marco De Salvo net6.0 diff --git a/RDFSharp/Model/Serializers/RDFXml.cs b/RDFSharp/Model/Serializers/RDFXml.cs index 4ef5d00c..39c7ae34 100644 --- a/RDFSharp/Model/Serializers/RDFXml.cs +++ b/RDFSharp/Model/Serializers/RDFXml.cs @@ -821,26 +821,29 @@ private static string ResolveRelativeNode(XmlAttribute attr, Uri xmlBase) if (attr != null && xmlBase != null) { string attrValue = attr.Value; + string xmlBaseString = xmlBase.ToString(); //Adjust corner case for clashes on namespace ending characters ("#", "/") - if (xmlBase.ToString().EndsWith("#") && attrValue.StartsWith("#")) - attrValue = string.Join(string.Empty, attrValue.SkipWhile(c => c == '#')); - if (xmlBase.ToString().EndsWith("/") && attrValue.StartsWith("/")) - attrValue = string.Join(string.Empty, attrValue.SkipWhile(c => c == '/')); + if (xmlBaseString.EndsWith("#") && attrValue.StartsWith("#")) + attrValue = attrValue.TrimStart('#'); + if (xmlBaseString.EndsWith("/") && attrValue.StartsWith("/")) + attrValue = attrValue.TrimStart('/'); //"rdf:ID" relative Uri: must be resolved against the xmlBase namespace if (attr.LocalName.Equals("rdf:ID", StringComparison.OrdinalIgnoreCase) - || attr.LocalName.Equals("ID", StringComparison.OrdinalIgnoreCase)) + || attr.LocalName.Equals("ID", StringComparison.OrdinalIgnoreCase)) { //This kind of syntax requires the attribute value to start with "#" if (!attrValue.StartsWith("#")) attrValue = string.Concat("#", attrValue); - attrValue = RDFModelUtilities.GetUriFromString(string.Concat(xmlBase, attrValue)).ToString(); + if (xmlBaseString.EndsWith("#")) + xmlBaseString = xmlBaseString.TrimEnd('#'); + attrValue = RDFModelUtilities.GetUriFromString(string.Concat(xmlBaseString, attrValue)).ToString(); } //"rdf:nodeID" relative Uri: must be resolved against the "bnode:" prefix else if (attr.LocalName.Equals("rdf:nodeID", StringComparison.OrdinalIgnoreCase) - || attr.LocalName.Equals("nodeID", StringComparison.OrdinalIgnoreCase)) + || attr.LocalName.Equals("nodeID", StringComparison.OrdinalIgnoreCase)) { if (!attrValue.StartsWith("bnode:")) attrValue = string.Concat("bnode:", attrValue); @@ -848,7 +851,7 @@ private static string ResolveRelativeNode(XmlAttribute attr, Uri xmlBase) //"rdf:about" or "rdf:resource" relative Uri: must be resolved against the xmlBase namespace else if (RDFModelUtilities.GetUriFromString(attrValue) == null) - attrValue = RDFModelUtilities.GetUriFromString(string.Concat(xmlBase, attrValue)).ToString(); + attrValue = RDFModelUtilities.GetUriFromString(string.Concat(xmlBaseString, attrValue)).ToString(); return attrValue; } diff --git a/RDFSharp/RDFSharp.csproj b/RDFSharp/RDFSharp.csproj index e78f9508..1641631e 100644 --- a/RDFSharp/RDFSharp.csproj +++ b/RDFSharp/RDFSharp.csproj @@ -3,7 +3,7 @@ RDFSharp RDFSharp $(Version) - 3.6.0 + 3.6.1 Marco De Salvo Marco De Salvo Lightweight and friendly .NET library for realizing Semantic Web applications