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;
2using System.Collections.Generic;
3using System.Xml;
14
16{
23 {
27 public const string Namespace = "http://www.w3.org/2005/sparql-results#";
28
32 public const string LocalName = "sparql";
33
34 private readonly Dictionary<string, ISemanticLiteral> dataTypes = new Dictionary<string, ISemanticLiteral>();
35 private readonly Uri baseUri;
36
42 public SparqlResultSet(XmlDocument Xml)
43 : this(Xml, null)
44 {
45 }
46
52 public SparqlResultSet(string Xml)
53 : this(Xml, null)
54 {
55 }
56
63 public SparqlResultSet(string Xml, Uri BaseUri)
64 : this(RdfDocument.ToXml(Xml), BaseUri)
65 {
66 }
67
74 public SparqlResultSet(XmlDocument Xml, Uri BaseUri)
75 {
76 if (Xml is null ||
77 Xml.DocumentElement is null ||
78 Xml.DocumentElement.LocalName != LocalName ||
79 Xml.DocumentElement.NamespaceURI != Namespace)
80 {
81 throw new ArgumentException("Invalid SPARQL Result XML document.", nameof(Xml));
82 }
83
84 this.baseUri = BaseUri;
85 this.BooleanResult = null;
86
87 List<string> Variables = new List<string>();
88 List<Uri> Links = new List<Uri>();
89 List<ISparqlResultRecord> Records = new List<ISparqlResultRecord>();
90
91 foreach (XmlNode N in Xml.DocumentElement.ChildNodes)
92 {
93 if (!(N is XmlElement E) || E.NamespaceURI != Namespace)
94 continue;
95
96 switch (E.LocalName)
97 {
98 case "head":
99 foreach (XmlNode N2 in E.ChildNodes)
100 {
101 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
102 continue;
103
104 switch (E2.LocalName)
105 {
106 case "variable":
107 string Name = XML.Attribute(E2, "name");
108 if (!string.IsNullOrEmpty(Name))
109 Variables.Add(Name);
110 break;
111
112 case "link":
113 string HRef = XML.Attribute(E2, "href");
114 if (string.IsNullOrEmpty(HRef))
115 break;
116
117 if (this.baseUri is null)
118 {
119 if (Uri.TryCreate(HRef, UriKind.RelativeOrAbsolute, out Uri Link))
120 Links.Add(Link);
121 }
122 else
123 {
124 if (Uri.TryCreate(this.baseUri, HRef, out Uri Link))
125 Links.Add(Link);
126 }
127 break;
128 }
129 }
130 break;
131
132 case "boolean":
133 if (CommonTypes.TryParse(E.InnerText, out bool b))
134 this.BooleanResult = b;
135 break;
136
137 case "results":
138 foreach (XmlNode N2 in E.ChildNodes)
139 {
140 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
141 continue;
142
143 switch (E2.LocalName)
144 {
145 case "result":
146 Dictionary<string, ISparqlResultItem> Record = new Dictionary<string, ISparqlResultItem>();
147 int Index = 0;
148
149 foreach (XmlNode N3 in E2.ChildNodes)
150 {
151 if (!(N3 is XmlElement E3) || E3.NamespaceURI != Namespace)
152 continue;
153
154 switch (E3.LocalName)
155 {
156 case "binding":
157 string Name = XML.Attribute(E3, "name");
158 ISemanticElement Value = this.ParseXmlValue(E3);
159 Record[Name] = new SparqlResultItem(Name, Value, Index++);
160 break;
161 }
162 }
163
164 Records.Add(new SparqlPatternResultRecord(Record));
165 break;
166 }
167 }
168 break;
169 }
170 }
171
172 this.Variables = Variables.ToArray();
173 this.Links = Links.ToArray();
174 this.Records = Records.ToArray();
175 }
176
183 public SparqlResultSet(Dictionary<string, object> Obj, Uri BaseUri)
184 {
185 if (Obj is null)
186 throw new ArgumentException("Invalid SPARQL Result JSON document.", nameof(Obj));
187
188 this.baseUri = BaseUri;
189 this.BooleanResult = null;
190
191 List<string> Variables = new List<string>();
192 List<Uri> Links = new List<Uri>();
193 List<ISparqlResultRecord> Records = new List<ISparqlResultRecord>();
194
195 foreach (KeyValuePair<string, object> P in Obj)
196 {
197 switch (P.Key)
198 {
199 case "head":
200 if (!(P.Value is Dictionary<string, object> Head))
201 break;
202
203 foreach (KeyValuePair<string, object> P2 in Head)
204 {
205 switch (P2.Key)
206 {
207 case "vars":
208 if (P2.Value is Array VariableArray)
209 {
210 foreach (object Item in VariableArray)
211 {
212 if (Item is string Name)
213 Variables.Add(Name);
214 }
215 }
216 break;
217
218 case "link":
219 if (P2.Value is Array LinkArray)
220 {
221 foreach (object Item in LinkArray)
222 {
223 if (Item is string HRef &&
224 !string.IsNullOrEmpty(HRef))
225 {
226 if (this.baseUri is null)
227 {
228 if (Uri.TryCreate(HRef, UriKind.RelativeOrAbsolute, out Uri Link))
229 Links.Add(Link);
230 }
231 else
232 {
233 if (Uri.TryCreate(this.baseUri, HRef, out Uri Link))
234 Links.Add(Link);
235 }
236 }
237 }
238 }
239 break;
240 }
241 }
242 break;
243
244 case "boolean":
245 if (P.Value is bool b)
246 this.BooleanResult = b;
247 break;
248
249 case "results":
250 if (!(P.Value is Dictionary<string, object> Results))
251 break;
252
253 foreach (KeyValuePair<string, object> P2 in Results)
254 {
255 if (P2.Key != "bindings")
256 continue;
257
258 if (!(P2.Value is Array Bindings))
259 continue;
260
261 foreach (object BindingObj in Bindings)
262 {
263 if (!(BindingObj is Dictionary<string, object> Binding))
264 continue;
265
266 Dictionary<string, ISparqlResultItem> Record = new Dictionary<string, ISparqlResultItem>();
267 int Index = 0;
268
269 foreach (KeyValuePair<string, object> P3 in Binding)
270 {
271 ISemanticElement Value = this.ParseJsonValue(P3.Value);
272 Record[P3.Key] = new SparqlResultItem(P3.Key, Value, Index++);
273 }
274
275 Records.Add(new SparqlPatternResultRecord(Record));
276 }
277 }
278 break;
279 }
280 }
281
282 this.Variables = Variables.ToArray();
283 this.Links = Links.ToArray();
284 this.Records = Records.ToArray();
285 }
286
287 private ISemanticElement ParseXmlValue(XmlElement Xml)
288 {
289 foreach (XmlNode N in Xml.ChildNodes)
290 {
291 if (!(N is XmlElement E) || E.NamespaceURI != Namespace)
292 continue;
293
294 switch (E.LocalName)
295 {
296 case "uri":
297 if (this.baseUri is null)
298 {
299 if (Uri.TryCreate(E.InnerText, UriKind.RelativeOrAbsolute, out Uri UriValue))
300 return new UriNode(UriValue, E.InnerText);
301 else
302 return new StringLiteral(E.InnerText);
303 }
304 else
305 {
306 if (Uri.TryCreate(this.baseUri, E.InnerText, out Uri UriValue))
307 return new UriNode(UriValue, E.InnerText);
308 else
309 return new StringLiteral(E.InnerText);
310 }
311
312 case "bnode":
313 return new BlankNode(E.InnerText);
314
315 case "literal":
316 string s = E.InnerText;
317 string DataType = null;
318 string Language = null;
319
320 foreach (XmlAttribute Attr in E.Attributes)
321 {
322 switch (Attr.Name)
323 {
324 case "xml:lang":
325 Language = Attr.Value;
326 break;
327
328 case "datatype":
329 DataType = Attr.Value;
330 break;
331 }
332 }
333
334 if (!string.IsNullOrEmpty(DataType))
335 {
336 if (!this.dataTypes.TryGetValue(DataType, out ISemanticLiteral LiteralType))
337 {
338 LiteralType = Types.FindBest<ISemanticLiteral, string>(DataType)
339 ?? new CustomLiteral(string.Empty, DataType);
340
341 this.dataTypes[DataType] = LiteralType;
342 }
343
344 return LiteralType.Parse(s, DataType, Language);
345 }
346 else if (!string.IsNullOrEmpty(Language))
347 return new StringLiteral(s, Language);
348 else
349 return new StringLiteral(s);
350
351 case "triple":
352 ISemanticElement Subject = null;
353 ISemanticElement Predicate = null;
354 ISemanticElement Object = null;
355
356 foreach (XmlNode N2 in E.ChildNodes)
357 {
358 if (!(N2 is XmlElement E2) || E2.NamespaceURI != Namespace)
359 continue;
360
361 switch (E2.LocalName)
362 {
363 case "subject":
364 Subject = this.ParseXmlValue(E2);
365 break;
366
367 case "predicate":
368 Predicate = this.ParseXmlValue(E2);
369 break;
370
371 case "object":
372 Object = this.ParseXmlValue(E2);
373 break;
374 }
375 }
376
377 return new SemanticTriple(Subject, Predicate, Object);
378
379 default:
380 continue;
381 }
382 }
383
384 return null;
385 }
386
387 private ISemanticElement ParseJsonValue(object Obj)
388 {
389 if (!(Obj is Dictionary<string, object> Object) ||
390 !(Object.TryGetValue("type", out object TypeObject)) ||
391 !(TypeObject is string Type))
392 {
393 return null;
394 }
395
396 switch (Type)
397 {
398 case "uri":
399 if (!(Object.TryGetValue("value", out object ValueObject)) ||
400 !(ValueObject is string Value))
401 {
402 return null;
403 }
404
405 if (this.baseUri is null)
406 {
407 if (Uri.TryCreate(Value, UriKind.RelativeOrAbsolute, out Uri UriValue))
408 return new UriNode(UriValue, Value);
409 else
410 return new StringLiteral(Value);
411 }
412 else
413 {
414 if (Uri.TryCreate(this.baseUri, Value, out Uri UriValue))
415 return new UriNode(UriValue, Value);
416 else
417 return new StringLiteral(Value);
418 }
419
420 case "bnode":
421 if (!(Object.TryGetValue("value", out ValueObject)) ||
422 (Value = ValueObject as string) is null)
423 {
424 return null;
425 }
426
427 return new BlankNode(Value);
428
429 case "literal":
430 if (!(Object.TryGetValue("value", out ValueObject)) ||
431 (Value = ValueObject as string) is null)
432 {
433 return null;
434 }
435
436 if (!Object.TryGetValue("datatype", out object DataTypeObject) ||
437 !(DataTypeObject is string DataType))
438 {
439 DataType = null;
440 }
441
442 if (!Object.TryGetValue("xml:lang", out object LanguageObject) ||
443 !(LanguageObject is string Language))
444 {
445 Language = null;
446 }
447
448 if (!string.IsNullOrEmpty(DataType))
449 {
450 if (!this.dataTypes.TryGetValue(DataType, out ISemanticLiteral LiteralType))
451 {
452 LiteralType = Types.FindBest<ISemanticLiteral, string>(DataType)
453 ?? new CustomLiteral(string.Empty, DataType);
454
455 this.dataTypes[DataType] = LiteralType;
456 }
457
458 return LiteralType.Parse(Value, DataType, Language);
459 }
460 else if (!string.IsNullOrEmpty(Language))
461 return new StringLiteral(Value, Language);
462 else
463 return new StringLiteral(Value);
464
465 case "triple":
466 if (!(Object.TryGetValue("value", out ValueObject)) ||
467 !(ValueObject is Dictionary<string,object> Triple))
468 {
469 return null;
470 }
471
472 ISemanticElement TripleSubject = null;
473 ISemanticElement TriplePredicate = null;
474 ISemanticElement TripleObject = null;
475
476 foreach (KeyValuePair<string, object> P in Triple)
477 {
478 switch (P.Key)
479 {
480 case "subject":
481 TripleSubject = this.ParseJsonValue(P.Value);
482 break;
483
484 case "predicate":
485 TriplePredicate = this.ParseJsonValue(P.Value);
486 break;
487
488 case "object":
489 TripleObject = this.ParseJsonValue(P.Value);
490 break;
491 }
492 }
493
494 return new SemanticTriple(TripleSubject, TriplePredicate, TripleObject);
495
496 default:
497 return null;
498 }
499 }
500
505 public SparqlResultSet(bool Result)
506 {
507 this.Variables = null;
508 this.Links = null;
509 this.Records = null;
510 this.baseUri = null;
511 this.BooleanResult = Result;
512 }
513
521 {
522 this.Variables = Variables;
523 this.Links = Links;
524 this.Records = Records;
525 this.baseUri = null;
526 this.BooleanResult = null;
527 }
528
532 public bool? BooleanResult { get; }
533
537 public string[] Variables { get; }
538
542 public Uri[] Links { get; }
543
547 public ISparqlResultRecord[] Records { get; }
548
552 public bool Pretty { get; set; }
553
559 {
560 if (this.BooleanResult.HasValue)
561 return new BooleanMatrix(new bool[1, 1] { { this.BooleanResult.Value } });
562
563 int Columns = this.Variables.Length;
564 int Rows = this.Records.Length;
565 IElement[,] Elements = new IElement[Rows, Columns];
566 int x, y;
567
568 for (y = 0; y < Rows; y++)
569 {
570 ISparqlResultRecord Record = this.Records[y];
571
572 for (x = 0; x < Columns; x++)
573 Elements[y, x] = (IElement)Record[this.Variables[x]] ?? ObjectValue.Null;
574 }
575
576 return new ObjectMatrix(Elements)
577 {
578 ColumnNames = this.Variables
579 };
580 }
581
587 {
588 return new ObjectVector(((ObjectMatrix)this.ToMatrix()).VectorElements);
589 }
590
591 }
592}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:46
Represents a blank node
Definition: BlankNode.cs:7
Contains semantic information stored in an RDF document.
Definition: RdfDocument.cs:21
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/ ...
bool? BooleanResult
Any Boolean result returned.
bool Pretty
If pretty output is desired.
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.
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:19
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:914
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:14
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:86
Collection of variables.
Definition: Variables.cs:25
virtual Variable Add(string Name, object Value)
Adds a variable to the collection.
Definition: Variables.cs:122
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:20
Basic interface for matrices.
Definition: IMatrix.cs:9
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