Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XmlSchemaValidationService.cs
1using System.Xml;
2using System.Xml.Schema;
5
7{
11 [Singleton]
13 {
14 private sealed class SchemaEntry
15 {
16 public string Path = string.Empty;
17 public XmlSchema? Schema;
18 public bool LoadAttempted;
19 }
20
21 private readonly Dictionary<string, SchemaEntry> schemas = new(StringComparer.OrdinalIgnoreCase);
22 private readonly object gate = new();
23
24 public void RegisterSchema(string Key, string RelativePath)
25 {
26 if (string.IsNullOrWhiteSpace(Key)) throw new ArgumentNullException(nameof(Key));
27 if (string.IsNullOrWhiteSpace(RelativePath)) throw new ArgumentNullException(nameof(RelativePath));
28
29 lock (this.gate)
30 {
31 if (!this.schemas.TryGetValue(Key, out SchemaEntry? Entry))
32 {
33 Entry = new SchemaEntry();
34 this.schemas[Key] = Entry;
35 }
36 Entry.Path = RelativePath;
37 Entry.LoadAttempted = false; // allow re-registration override
38 Entry.Schema = null;
39 }
40 ServiceRef.LogService.LogDebug("XmlSchemaRegistered", new KeyValuePair<string, object?>("Key", Key), new KeyValuePair<string, object?>("Path", RelativePath));
41 }
42
43 public bool IsRegistered(string Key)
44 {
45 lock (this.gate) return this.schemas.ContainsKey(Key);
46 }
47
48 public async Task<bool> ValidateAsync(string Key, string Xml, CancellationToken CancellationToken = default)
49 {
50 if (Xml is null) throw new ArgumentNullException(nameof(Xml));
51 XmlSchema? Schema = await this.GetOrLoadAsync(Key, CancellationToken).ConfigureAwait(false);
52 if (Schema is null)
53 {
54 // Non-fatal: Schema missing or failed to load; treat as valid to allow fallback logic in caller.
55 return true;
56 }
57 try
58 {
59 XmlDocument Doc = new() { XmlResolver = null };
60 using StringReader StringReader = new(Xml);
61 using XmlReader Reader = XmlReader.Create(StringReader, new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, XmlResolver = null });
62 Doc.Load(Reader);
63 XSL.Validate(Key, Doc, Schema);
64 return true;
65 }
66 catch (XmlSchemaException Ex)
67 {
68 ServiceRef.LogService.LogWarning("XmlValidationFailed",
69 new KeyValuePair<string, object?>("Key", Key),
70 new KeyValuePair<string, object?>("Line", Ex.LineNumber),
71 new KeyValuePair<string, object?>("Pos", Ex.LinePosition),
72 new KeyValuePair<string, object?>("Message", Ex.Message));
73 return false;
74 }
75 catch (Exception Ex)
76 {
77 ServiceRef.LogService.LogException(Ex,
78 new KeyValuePair<string, object?>("Operation", "XmlValidationUnexpected"),
79 new KeyValuePair<string, object?>("Key", Key));
80 return false;
81 }
82 }
83
84 private async Task<XmlSchema?> GetOrLoadAsync(string Key, CancellationToken CancellationToken)
85 {
86 SchemaEntry? Entry;
87 lock (this.gate)
88 {
89 if (!this.schemas.TryGetValue(Key, out Entry))
90 {
91 ServiceRef.LogService.LogWarning("XmlSchemaKeyNotRegistered", new KeyValuePair<string, object?>("Key", Key));
92 return null;
93 }
94 if (Entry.Schema is not null)
95 return Entry.Schema;
96 if (Entry.LoadAttempted)
97 return Entry.Schema; // failed earlier
98 Entry.LoadAttempted = true;
99 }
100 try
101 {
102 using Stream Stream = await FileSystem.OpenAppPackageFileAsync(Entry.Path).ConfigureAwait(false);
103 using Stream Clone = new MemoryStream();
104 await Stream.CopyToAsync(Clone, CancellationToken).ConfigureAwait(false);
105 Clone.Position = 0;
106 XmlSchema Schema = XSL.LoadSchema(Clone, Entry.Path);
107 lock (this.gate) Entry.Schema = Schema;
108 ServiceRef.LogService.LogDebug("XmlSchemaLoaded",
109 new KeyValuePair<string, object?>("Key", Key));
110 return Schema;
111 }
112 catch (Exception Ex)
113 {
114 ServiceRef.LogService.LogException(Ex,
115 new KeyValuePair<string, object?>("Operation", "XmlSchemaLoad"),
116 new KeyValuePair<string, object?>("Key", Key));
117 return null;
118 }
119 }
120 }
121}
Base class that references services in the app.
Definition: ServiceRef.cs:43
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
Default implementation of IXmlSchemaValidationService.
bool IsRegistered(string Key)
Checks if a schema Key has been registered.
void RegisterSchema(string Key, string RelativePath)
Registers a schema under a logical Key. The schema file must exist in the application package (Raw re...
async Task< bool > ValidateAsync(string Key, string Xml, CancellationToken CancellationToken=default)
Validates an XML string against the schema identified by Key. Returns true if valid or schema missing...
Static class managing loading of XSL resources stored as embedded resources or in content files.
Definition: XSL.cs:16
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
Definition: XSL.cs:24
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Definition: XSL.cs:134
Contract for validating XML instances against pre-registered XML Schemas (XSD). Schemas are lazily lo...