#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Xml.XPath;
namespace XsdGenerator
{
///
/// Processes WXS files and builds code for them.
///
public sealed class Processor
{
public const string ExtensionNamespace = "http://weblogs.asp.net/cazzu";
private static XPathExpression Extensions;
static Processor()
{
XPathNavigator nav = new XmlDocument().CreateNavigator();
// Select all extension types.
Extensions = nav.Compile( "/xs:schema/xs:annotation/xs:appinfo/kzu:Code/kzu:Extension/@Type" );
// Create and set namespace resolution context.
XmlNamespaceManager nsmgr = new XmlNamespaceManager( nav.NameTable );
nsmgr.AddNamespace( "xs", XmlSchema.Namespace );
nsmgr.AddNamespace( "kzu", ExtensionNamespace );
Extensions.SetContext( nsmgr );
}
private Processor() {}
///
/// Processes the schema.
///
/// The full path to the WXS file to process.
/// The namespace to put generated classes in.
/// The CodeDom tree generated from the schema.
public static CodeNamespace Process( string xsdFile, string targetNamespace )
{
// Load the XmlSchema and its collection.
XmlSchema xsd;
using ( FileStream fs = new FileStream( xsdFile, FileMode.Open ) )
{
xsd = XmlSchema.Read( fs, null );
xsd.Compile( null );
}
XmlSchemas schemas = new XmlSchemas();
schemas.Add( xsd );
// Create the importer for these schemas.
XmlSchemaImporter importer = new XmlSchemaImporter( schemas );
// System.CodeDom namespace for the XmlCodeExporter to put classes in.
CodeNamespace ns = new CodeNamespace( targetNamespace );
XmlCodeExporter exporter = new XmlCodeExporter( ns );
// Iterate schema top-level elements and export code for each.
foreach ( XmlSchemaElement element in xsd.Elements.Values )
{
// Import the mapping first.
XmlTypeMapping mapping = importer.ImportTypeMapping(
element.QualifiedName );
// Export the code finally.
exporter.ExportTypeMapping( mapping );
}
new XsdGenerator.Extensions.ArraysToCollectionsExtension().Process( ns, xsd );
new XsdGenerator.Extensions.FieldsToPropertiesExtension().Process( ns, xsd );
#region Execute extensions
XPathNavigator nav;
using ( FileStream fs = new FileStream( xsdFile, FileMode.Open ) )
{
nav = new XPathDocument( fs ).CreateNavigator();
}
XPathNodeIterator it = nav.Select( Extensions );
while ( it.MoveNext() )
{
Type t = Type.GetType( it.Current.Value, true );
// Is the type an ICodeExtension?
Type iface = t.GetInterface( typeof( ICodeExtension ).Name );
if (iface == null)
throw new ArgumentException( "Invalid extension type '" + it.Current.Value + "'." );
ICodeExtension ext = ( ICodeExtension ) Activator.CreateInstance( t );
// Run it!
ext.Process( ns, xsd );
}
#endregion Execute extensions
return ns;
}
}
}