Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
SparqlResultSet.cs
1using System;
3using System.Xml;
15
17{
24 {
28 public const string Namespace = "http://www.w3.org/2005/sparql-results#";
29
33 public const string LocalName = "sparql";
34
35 private readonly Dictionary<string, ISemanticLiteral> dataTypes = new Dictionary<string, ISemanticLiteral>();
36 private readonly Uri baseUri;
37 private Dictionary<string, string> shortBlankNodeLabels = null;
38 private Dictionary<string, string> shortUris = null;
39 private Dictionary<string, SemanticLiteral> literals = null;
40
46 public SparqlResultSet(XmlDocument Xml)
47 : this(Xml, null)
48 {
49 }
50
56 public SparqlResultSet(string Xml)
57 : this(Xml, null)
58 {
59 }
60
67 public SparqlResultSet(string Xml, Uri BaseUri)
68 : this(RdfDocument.ToXml(Xml), BaseUri)
69 {
70 }
71
78 public SparqlResultSet(XmlDocument Xml, Uri BaseUri)
79 {
80 if (Xml is null ||
81 Xml.DocumentElement is null ||
82 Xml.DocumentElement.LocalName != LocalName ||
83 Xml.DocumentElement.NamespaceURI != Namespace)
84 {
85 throw new ArgumentException("Invalid SPARQL Result XML document.", nameof(Xml));
86 }
87
88 this.baseUri = BaseUri;
89 this.BooleanResult = null;
90
94
95 foreach (XmlNode N in Xml.DocumentElement.ChildNodes)
96 {
97 if (!(N is XmlElement E) || E.NamespaceURI != Namespace)
98 continue;
99
100 switch (E.LocalName)
101 {
102 case "head":
103 foreach (XmlNode N2 in E.ChildNodes)
104 {
105 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
106 continue;
107
108 switch (E2.LocalName)
109 {
110 case "variable":
111 string Name = XML.Attribute(E2, "name");
112 if (!string.IsNullOrEmpty(Name))
113 Variables.Add(Name);
114 break;
115
116 case "link":
117 string HRef = XML.Attribute(E2, "href");
118 if (string.IsNullOrEmpty(HRef))
119 break;
120
121 if (this.baseUri is null)
122 {
123 if (Uri.TryCreate(HRef, UriKind.RelativeOrAbsolute, out Uri Link))
124 Links.Add(Link);
125 }
126 else
127 {
128 if (Uri.TryCreate(this.baseUri, HRef, out Uri Link))
129 Links.Add(Link);
130 }
131 break;
132 }
133 }
134 break;
135
136 case "boolean":
137 if (CommonTypes.TryParse(E.InnerText, out bool b))
138 this.BooleanResult = b;
139 break;
140
141 case "results":
142 foreach (XmlNode N2 in E.ChildNodes)
143 {
144 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
145 continue;
146
147 switch (E2.LocalName)
148 {
149 case "result":
150 Dictionary<string, ISparqlResultItem> Record = new Dictionary<string, ISparqlResultItem>();
151 int Index = 0;
152
153 foreach (XmlNode N3 in E2.ChildNodes)
154 {
155 if (!(N3 is XmlElement E3) || E3.NamespaceURI != Namespace)
156 continue;
157
158 switch (E3.LocalName)
159 {
160 case "binding":
161 string Name = XML.Attribute(E3, "name");
162 ISemanticElement Value = this.ParseXmlValue(E3);
163 Record[Name] = new SparqlResultItem(Name, Value, Index++);
164 break;
165 }
166 }
167
168 Records.Add(new SparqlPatternResultRecord(Record));
169 break;
170 }
171 }
172 break;
173 }
174 }
175
176 this.Variables = Variables.ToArray();
177 this.Links = Links.ToArray();
178 this.Records = Records.ToArray();
179 }
180
187 public SparqlResultSet(Dictionary<string, object> Obj, Uri BaseUri)
188 {
189 if (Obj is null)
190 throw new ArgumentException("Invalid SPARQL Result JSON document.", nameof(Obj));
191
192 this.baseUri = BaseUri;
193 this.BooleanResult = null;
194
198
199 foreach (KeyValuePair<string, object> P in Obj)
200 {
201 switch (P.Key)
202 {
203 case "head":
204 if (!(P.Value is Dictionary<string, object> Head))
205 break;
206
207 foreach (KeyValuePair<string, object> P2 in Head)
208 {
209 switch (P2.Key)
210 {
211 case "vars":
212 if (P2.Value is Array VariableArray)
213 {
214 foreach (object Item in VariableArray)
215 {
216 if (Item is string Name)
217 Variables.Add(Name);
218 }
219 }
220 break;
221
222 case "link":
223 if (P2.Value is Array LinkArray)
224 {
225 foreach (object Item in LinkArray)
226 {
227 if (Item is string HRef &&
228 !string.IsNullOrEmpty(HRef))
229 {
230 if (this.baseUri is null)
231 {
232 if (Uri.TryCreate(HRef, UriKind.RelativeOrAbsolute, out Uri Link))
233 Links.Add(Link);
234 }
235 else
236 {
237 if (Uri.TryCreate(this.baseUri, HRef, out Uri Link))
238 Links.Add(Link);
239 }
240 }
241 }
242 }
243 break;
244 }
245 }
246 break;
247
248 case "boolean":
249 if (P.Value is bool b)
250 this.BooleanResult = b;
251 break;
252
253 case "results":
254 if (!(P.Value is Dictionary<string, object> Results))
255 break;
256
257 foreach (KeyValuePair<string, object> P2 in Results)
258 {
259 if (P2.Key != "bindings")
260 continue;
261
262 if (!(P2.Value is Array Bindings))
263 continue;
264
265 foreach (object BindingObj in Bindings)
266 {
267 if (!(BindingObj is Dictionary<string, object> Binding))
268 continue;
269
270 Dictionary<string, ISparqlResultItem> Record = new Dictionary<string, ISparqlResultItem>();
271 int Index = 0;
272
273 foreach (KeyValuePair<string, object> P3 in Binding)
274 {
275 ISemanticElement Value = this.ParseJsonValue(P3.Value);
276 Record[P3.Key] = new SparqlResultItem(P3.Key, Value, Index++);
277 }
278
279 Records.Add(new SparqlPatternResultRecord(Record));
280 }
281 }
282 break;
283 }
284 }
285
286 this.Variables = Variables.ToArray();
287 this.Links = Links.ToArray();
288 this.Records = Records.ToArray();
289 }
290
291 private ISemanticElement ParseXmlValue(XmlElement Xml)
292 {
293 foreach (XmlNode N in Xml.ChildNodes)
294 {
295 if (!(N is XmlElement E) || E.NamespaceURI != Namespace)
296 continue;
297
298 switch (E.LocalName)
299 {
300 case "uri":
301 if (this.baseUri is null)
302 {
303 if (Uri.TryCreate(E.InnerText, UriKind.RelativeOrAbsolute, out Uri UriValue))
304 return new UriNode(UriValue, E.InnerText);
305 else
306 return new StringLiteral(E.InnerText);
307 }
308 else
309 {
310 if (Uri.TryCreate(this.baseUri, E.InnerText, out Uri UriValue))
311 return new UriNode(UriValue, E.InnerText);
312 else
313 return new StringLiteral(E.InnerText);
314 }
315
316 case "bnode":
317 return new BlankNode(E.InnerText);
318
319 case "literal":
320 string s = E.InnerText;
321 string DataType = null;
322 string Language = null;
323
324 foreach (XmlAttribute Attr in E.Attributes)
325 {
326 switch (Attr.Name)
327 {
328 case "xml:lang":
329 Language = Attr.Value;
330 break;
331
332 case "datatype":
333 DataType = Attr.Value;
334 break;
335 }
336 }
337
338 if (!string.IsNullOrEmpty(DataType))
339 {
340 if (!this.dataTypes.TryGetValue(DataType, out ISemanticLiteral LiteralType))
341 {
342 LiteralType = Types.FindBest<ISemanticLiteral, string>(DataType)
343 ?? new CustomLiteral(string.Empty, DataType);
344
345 this.dataTypes[DataType] = LiteralType;
346 }
347
348 return LiteralType.Parse(s, DataType, Language);
349 }
350 else if (!string.IsNullOrEmpty(Language))
351 return new StringLiteral(s, Language);
352 else
353 return new StringLiteral(s);
354
355 case "triple":
356 ISemanticElement Subject = null;
357 ISemanticElement Predicate = null;
358 ISemanticElement Object = null;
359
360 foreach (XmlNode N2 in E.ChildNodes)
361 {
362 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
363 continue;
364
365 switch (E2.LocalName)
366 {
367 case "subject":
368 Subject = this.ParseXmlValue(E2);
369 break;
370
371 case "predicate":
372 Predicate = this.ParseXmlValue(E2);
373 break;
374
375 case "object":
376 Object = this.ParseXmlValue(E2);
377 break;
378 }
379 }
380
381 return new SemanticTriple(Subject, Predicate, Object);
382
383 default:
384 continue;
385 }
386 }
387
388 return null;
389 }
390
391 private ISemanticElement ParseJsonValue(object Obj)
392 {
393 if (!(Obj is Dictionary<string, object> Object) ||
394 !(Object.TryGetValue("type", out object TypeObject)) ||
395 !(TypeObject is string Type))
396 {
397 return null;
398 }
399
400 switch (Type)
401 {
402 case "uri":
403 if (!(Object.TryGetValue("value", out object ValueObject)) ||
404 !(ValueObject is string Value))
405 {
406 return null;
407 }
408
409 if (this.baseUri is null)
410 {
411 if (Uri.TryCreate(Value, UriKind.RelativeOrAbsolute, out Uri UriValue))
412 return new UriNode(UriValue, Value);
413 else
414 return new StringLiteral(Value);
415 }
416 else
417 {
418 if (Uri.TryCreate(this.baseUri, Value, out Uri UriValue))
419 return new UriNode(UriValue, Value);
420 else
421 return new StringLiteral(Value);
422 }
423
424 case "bnode":
425 if (!(Object.TryGetValue("value", out ValueObject)) ||
426 (Value = ValueObject as string) is null)
427 {
428 return null;
429 }
430
431 return new BlankNode(Value);
432
433 case "literal":
434 if (!(Object.TryGetValue("value", out ValueObject)) ||
435 (Value = ValueObject as string) is null)
436 {
437 return null;
438 }
439
440 if (!Object.TryGetValue("datatype", out object DataTypeObject) ||
441 !(DataTypeObject is string DataType))
442 {
443 DataType = null;
444 }
445
446 if (!Object.TryGetValue("xml:lang", out object LanguageObject) ||
447 !(LanguageObject is string Language))
448 {
449 Language = null;
450 }
451
452 if (!string.IsNullOrEmpty(DataType))
453 {
454 if (!this.dataTypes.TryGetValue(DataType, out ISemanticLiteral LiteralType))
455 {
456 LiteralType = Types.FindBest<ISemanticLiteral, string>(DataType)
457 ?? new CustomLiteral(string.Empty, DataType);
458
459 this.dataTypes[DataType] = LiteralType;
460 }
461
462 return LiteralType.Parse(Value, DataType, Language);
463 }
464 else if (!string.IsNullOrEmpty(Language))
465 return new StringLiteral(Value, Language);
466 else
467 return new StringLiteral(Value);
468
469 case "triple":
470 if (!(Object.TryGetValue("value", out ValueObject)) ||
471 !(ValueObject is Dictionary<string, object> Triple))
472 {
473 return null;
474 }
475
476 ISemanticElement TripleSubject = null;
477 ISemanticElement TriplePredicate = null;
478 ISemanticElement TripleObject = null;
479
480 foreach (KeyValuePair<string, object> P in Triple)
481 {
482 switch (P.Key)
483 {
484 case "subject":
485 TripleSubject = this.ParseJsonValue(P.Value);
486 break;
487
488 case "predicate":
489 TriplePredicate = this.ParseJsonValue(P.Value);
490 break;
491
492 case "object":
493 TripleObject = this.ParseJsonValue(P.Value);
494 break;
495 }
496 }
497
498 return new SemanticTriple(TripleSubject, TriplePredicate, TripleObject);
499
500 default:
501 return null;
502 }
503 }
504
509 public SparqlResultSet(bool Result)
510 {
511 this.Variables = null;
512 this.Links = null;
513 this.Records = null;
514 this.baseUri = null;
515 this.BooleanResult = Result;
516 }
517
525 {
526 this.Variables = Variables;
527 this.Links = Links;
528 this.Records = Records;
529 this.baseUri = null;
530 this.BooleanResult = null;
531 }
532
536 public bool? BooleanResult { get; }
537
541 public string[] Variables { get; }
542
546 public Uri[] Links { get; }
547
551 public ISparqlResultRecord[] Records { get; }
552
556 public bool Pretty { get; set; }
557
563 {
564 return this.ToMatrix(true);
565 }
566
572 public IMatrix ToMatrix(bool ShortLinks)
573 {
574 if (this.BooleanResult.HasValue)
575 return new BooleanMatrix(new bool[1, 1] { { this.BooleanResult.Value } });
576
577 int Columns = this.Variables.Length;
578 int Rows = this.Records.Length;
579 IElement[,] Elements = new IElement[Rows, Columns];
580 int x, y;
581
582 for (y = 0; y < Rows; y++)
583 {
584 ISparqlResultRecord Record = this.Records[y];
585
586 for (x = 0; x < Columns; x++)
587 {
588 IElement Element = (IElement)Record[this.Variables[x]] ?? ObjectValue.Null;
589
590 if (ShortLinks)
591 {
593 Element = new StringValue(this.GetShortBlankNodeLabel(BlankNode));
594 else if (Element is UriNode UriNode)
595 Element = new StringValue(this.GetShortUri(UriNode));
596 }
597
598 Elements[y, x] = Element;
599 }
600 }
601
602 return new ObjectMatrix(Elements)
603 {
604 ColumnNames = this.Variables
605 };
606 }
607
613 {
614 return new ObjectVector(((ObjectMatrix)this.ToMatrix(true)).VectorElements);
615 }
616
623 {
624 string s = Node.NodeId;
625
626 if (this.shortBlankNodeLabels is null)
627 this.shortBlankNodeLabels = new Dictionary<string, string>();
628
629 if (!this.shortBlankNodeLabels.TryGetValue(s, out string Short))
630 {
631 Short = "_:bn" + (this.shortBlankNodeLabels.Count + 1).ToString();
632 this.shortBlankNodeLabels[s] = Short;
633 }
634
635 return Short;
636 }
637
643 public string GetShortUri(UriNode Node)
644 {
645 return this.GetShortUri(Node.Uri.AbsoluteUri);
646 }
647
653 public string GetShortUri(string Uri)
654 {
655 if (this.shortUris is null)
656 this.shortUris = new Dictionary<string, string>();
657
658 if (!this.shortUris.TryGetValue(Uri, out string Short))
659 {
660 IOntology Ontology = Types.FindBest<IOntology, string>(Uri);
661 if (Ontology is null)
662 this.shortUris[Uri] = Short = Uri;
663 else
664 {
665 Short = Ontology.OntologyPrefix + ":" +
666 Uri.Substring(Ontology.OntologyNamespace.Length);
667
668 this.shortUris[Uri] = Short;
669 }
670 }
671
672 return Short;
673 }
674
680 public string GetLiteralLabel(SemanticLiteral Literal)
681 {
682 if (this.literals is null)
683 this.literals = new Dictionary<string, SemanticLiteral>();
684
685 int i = this.literals.Count + 1;
686 string Label = "L" + i.ToString();
687
688 this.literals[Label] = Literal;
689
690 return Label;
691 }
692 }
693}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:48
Represents a blank node
Definition: BlankNode.cs:7
string NodeId
Blank node Node ID.
Definition: BlankNode.cs:33
Abstract base class for semantic literal values.
Contains semantic information stored in an RDF document.
Definition: RdfDocument.cs:23
Contains a record from the results of a SPARQL query.
Contains an item in a record from the results of a SPARQL query.
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/ ...
IMatrix ToMatrix(bool ShortLinks)
Converts the object to a matrix.
string GetShortBlankNodeLabel(BlankNode Node)
Gets a short blank node label for the given blank node.
bool? BooleanResult
Any Boolean result returned.
string GetShortUri(UriNode Node)
Gets a short URI label for the given uri node.
bool Pretty
If pretty output is desired.
string GetShortUri(string Uri)
Gets a short URI label for the given uri node.
string[] Variables
Names of variables in result set.
ISparqlResultRecord[] Records
Records in result set.
SparqlResultSet(string Xml, Uri BaseUri)
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/
SparqlResultSet(bool Result)
Contains the results of a SPARQL query.
IMatrix ToMatrix()
Converts the object to a matrix.
IElement ToVector()
Converts the object to a vector.
string GetLiteralLabel(SemanticLiteral Literal)
Gets a label unique for a literal.
SparqlResultSet(string[] Variables, Uri[] Links, ISparqlResultRecord[] Records)
Contains the results of a SPARQL query.
SparqlResultSet(XmlDocument Xml)
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/
Uri[] Links
Links to additional metadata about result set.
SparqlResultSet(string Xml)
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/
SparqlResultSet(XmlDocument Xml, Uri BaseUri)
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/
SparqlResultSet(Dictionary< string, object > Obj, Uri BaseUri)
Contains the results of a SPARQL query. https://www.w3.org/TR/sparql12-results-json/
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:1062
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
Base class for all types of elements.
Definition: Element.cs:14
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:88
Collection of variables.
Definition: Variables.cs:25
virtual Variable Add(string Name, object Value)
Adds a variable to the collection.
Definition: Variables.cs:126
Interface for semantic ontologies.
Definition: IOntology.cs:9
string OntologyNamespace
Ontology namespace.
Definition: IOntology.cs:13
Interface for semantic nodes.
Interface for semantic literals.
Interface for result records of a SPARQL query.
Basic interface for all types of elements.
Definition: IElement.cs:21
Basic interface for matrices.
Definition: IMatrix.cs:7
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
Interface for objects that can be converted into matrices.
Definition: IToVector.cs:9
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.