2using System.Xml.Schema;
14 private sealed
class SchemaEntry
16 public string Path =
string.Empty;
17 public XmlSchema? Schema;
18 public bool LoadAttempted;
21 private readonly Dictionary<string, SchemaEntry> schemas =
new(StringComparer.OrdinalIgnoreCase);
22 private readonly
object gate =
new();
26 if (
string.IsNullOrWhiteSpace(Key))
throw new ArgumentNullException(nameof(Key));
27 if (
string.IsNullOrWhiteSpace(RelativePath))
throw new ArgumentNullException(nameof(RelativePath));
31 if (!this.schemas.TryGetValue(Key, out SchemaEntry? Entry))
33 Entry =
new SchemaEntry();
34 this.schemas[Key] = Entry;
36 Entry.Path = RelativePath;
37 Entry.LoadAttempted =
false;
40 ServiceRef.
LogService.LogDebug(
"XmlSchemaRegistered",
new KeyValuePair<string, object?>(
"Key", Key),
new KeyValuePair<string, object?>(
"Path", RelativePath));
45 lock (this.gate)
return this.schemas.ContainsKey(Key);
48 public async Task<bool>
ValidateAsync(
string Key,
string Xml, CancellationToken CancellationToken =
default)
50 if (Xml is
null)
throw new ArgumentNullException(nameof(Xml));
51 XmlSchema? Schema = await this.GetOrLoadAsync(Key, CancellationToken).ConfigureAwait(
false);
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 });
66 catch (XmlSchemaException Ex)
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));
78 new KeyValuePair<string, object?>(
"Operation",
"XmlValidationUnexpected"),
79 new KeyValuePair<string, object?>(
"Key", Key));
84 private async Task<XmlSchema?> GetOrLoadAsync(
string Key, CancellationToken CancellationToken)
89 if (!this.schemas.TryGetValue(Key, out Entry))
91 ServiceRef.
LogService.LogWarning(
"XmlSchemaKeyNotRegistered",
new KeyValuePair<string, object?>(
"Key", Key));
94 if (Entry.Schema is not
null)
96 if (Entry.LoadAttempted)
98 Entry.LoadAttempted =
true;
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);
107 lock (this.gate) Entry.Schema = Schema;
108 ServiceRef.LogService.LogDebug(
"XmlSchemaLoaded",
109 new KeyValuePair<string, object?>(
"Key", Key));
114 ServiceRef.LogService.LogException(Ex,
115 new KeyValuePair<string, object?>(
"Operation",
"XmlSchemaLoad"),
116 new KeyValuePair<string, object?>(
"Key", Key));
Base class that references services in the app.
static ILogService LogService
Log service.
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.
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Contract for validating XML instances against pre-registered XML Schemas (XSD). Schemas are lazily lo...