|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.w3.org.Item2001.XMLSchema;
using System.IO;
namespace Coding.Bruce.Language.Converter.Ska
{
class XmlSchemaLoader
{
public delegate string IncludedFileResolver(string path, Uri includeUriName);
/// <summary>
/// default (simple) loader, will use local file paths only, does not resolve
/// web references, etc.
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
public static schema Load(IEnumerable<string> files)
{
return Load(files, FindRelativePath);
}
/// <summary>
/// Load a schema using the include file resolver, so you can find any resource
/// </summary>
/// <param name="files"></param>
/// <param name="resolver"></param>
/// <returns></returns>
public static schema Load(IEnumerable<string> files, IncludedFileResolver resolver)
{
schema mtr = new schema();
foreach(var fil in files)
{
var sch = schema.Load(fil);
Merge(mtr, sch);
// Combine import & include
var incs = sch.import.Select(q => q.schemaLocation).ToList();
incs.AddRange(sch.include.Select(s=>s.schemaLocation));
var resolved = incs.Select(inc => resolver(fil, inc))
.Where(q=>null!=q);
if (resolved.Count() > 0)
Merge(mtr, Load(resolved));
}
return mtr;
}
/// <summary>
/// This is a local resource resolver. It works for files on disk relative to the source
/// </summary>
/// <param name="path"></param>
/// <param name="inc"></param>
/// <returns></returns>
private static string FindRelativePath(string path, Uri inc)
{
var incFile = inc.OriginalString;
if (File.Exists(incFile))
return incFile;
if (!Directory.Exists(path))
path = Path.GetDirectoryName(path);
incFile = Path.Combine(path, incFile);
return File.Exists(incFile) ? incFile : null;
}
/// <summary>
/// combines multiple schemas into one large schema object
/// </summary>
/// <param name="mstr"></param>
/// <param name="src"></param>
private static void Merge(schema mstr, schema src)
{
mstr.element = MergeList<element>(mstr.element, src.element);
mstr.attribute = MergeList<attribute>(mstr.attribute, src.attribute);
mstr.complexType = MergeList<complexType>(mstr.complexType, src.complexType);
mstr.simpleType = MergeList<simpleType>(mstr.simpleType, src.simpleType);
mstr.include = MergeList<include>(mstr.include, src.include);
mstr.import = MergeList<import>(mstr.import, src.import);
}
/// <summary>
/// Generic list of stuff merge mechanism. Simple ref copy if null, otherwise append
/// ignores duplicate.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dest"></param>
/// <param name="src"></param>
/// <returns></returns>
private static IList<T> MergeList<T>(IList<T> dest, IList<T> src)
{
if (null == dest)
return src;
if (null != src && src.Count() > 0)
src.Where(q=>!dest.Contains(q)).ToList().ForEach(s => dest.Add(s));
return dest;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
My professional career began as a developer fixing bugs on Microsoft Word97 and I've been fixing bad habits ever since. Now I do R&D work writing v1 line of business applications mostly in C#/.Net.
I've been an avid pilot/instructor for 13+ years, I've built two airplanes and mostly fly gliders now for fun. I commute in an all-electric 1986 BMW 325 conversion.
I'd like to get back to my academic roots of programming 3D analysis applications to organize complex systems.