Herramienta de preprocesador para esquemas XML
El elemento include de W3C XSD proporciona compatibilidad con la modularidad de esquemas en la que un esquema XML se puede dividir en más de un archivo físico. Actualmente, SQL Server no admite este elemento. El servidor rechazará los esquemas XML que incluyan este elemento.
Para solucionar este problema, los esquemas XML que incluyen la directiva <xsd:include> se pueden procesar previamente para copiar y combinar el contenido de todos los esquemas incluidos en un solo esquema para cargarlo en el servidor. Se puede utilizar el código C# siguiente para el preprocesamiento. Los comentarios de la primera parte del código proporcionan información acerca de su utilización.
// XSD Schema Include Normalizer
// To compile:
// csc filename.cs
//
// How to use:
//
// Arguments: [-q] input.xsd [output.xsd]
//
// input.xsd - file to normalize
// output.xsd - file to output, default is console
// -q - quiet
//
// Example:
//
// filename.exe schema.xsd
//
using System;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using System.Collections;
public class XsdSchemaNormalizer
{
private static bool NormalizeXmlSchema( String url, TextWriter writer )
{
try {
XmlTextReader txtRead = new XmlTextReader( url );
XmlSchema sch = XmlSchema.Read( txtRead, null );
// Compiling Schema
sch.Compile(null);
XmlSchema outSch =
XmlSchemaIncludeNormalizer.BuildIncludeFreeXmlSchema( sch);
outSch.Write( writer );
} catch ( Exception e ) {
Console.WriteLine(e.ToString());
return false;
}
return true;
}
public static void usage()
{
Console.WriteLine("Arguments: [-q] [-v] input.xsd [output.xsd]\n");
Console.WriteLine("input.xsd - file to normalize");
Console.WriteLine("output.xsd - file to output, default is console");
Console.WriteLine("-q - quiet");
}
public static void Main(String []args)
{
if( args.GetLength(0) < 1 ) {
usage();
return;
}
int argi = 0;
bool quiet = false;
if( args[argi] == "-q" ) {
quiet = true;
argi++;
}
if( argi == args.GetLength(0) )
{
usage();
return;
}
String url = args[argi];
if( !quiet )
Console.WriteLine("Loading Schema: " + url);
if( argi < ( args.GetLength(0) - 1 ) )
{
if( !quiet )
Console.WriteLine("Outputing to file: " + args[argi+1]);
StreamWriter output =
new StreamWriter( new FileStream(args[argi+1], FileMode.Create ));
NormalizeXmlSchema( url, output);
}
else
{
NormalizeXmlSchema( url, Console.Out);
}
}
}
// A class to remove all <include> from a Xml Schema
//
public class XmlSchemaIncludeNormalizer
{
// Takes as input a XmlSchema which has includes in it
// and the schema location uri of that XmlSchema
//
// Returns a "preprocessed" form of XmlSchema without any
// includes. It still retains imports though. Also, it does
// not propagate unhandled attributes
//
// It can throw any exception
public static XmlSchema BuildIncludeFreeXmlSchema( XmlSchema inSch )
{
XmlSchema outSch = new XmlSchema();
AddSchema( outSch, inSch );
return outSch;
}
// Adds everything in the second schema minus includes to
// the first schema
//
private static void AddSchema( XmlSchema outSch, XmlSchema add)
{
outSch.AttributeFormDefault = add.AttributeFormDefault;
outSch.BlockDefault = add.BlockDefault;
outSch.ElementFormDefault = add.ElementFormDefault;
outSch.FinalDefault = add.FinalDefault;
outSch.Id = add.Id;
outSch.TargetNamespace = add.TargetNamespace;
outSch.Version = add.Version;
AddTableToSchema( outSch, add.AttributeGroups );
AddTableToSchema( outSch, add.Attributes );
AddTableToSchema( outSch, add.Elements );
AddTableToSchema( outSch, add.Groups );
AddTableToSchema( outSch, add.Notations );
AddTableToSchema( outSch, add.SchemaTypes );
// Handle includes as a special case
for( int i = 0; i < add.Includes.Count; i++ )
{
if( ! ( add.Includes[i] is XmlSchemaInclude) )
outSch.Includes.Add( add.Includes[i] );
}
}
// Adds all items in the XmlSchemaObjectTable to the specified XmlSchema
//
private static void AddTableToSchema( XmlSchema outSch,
XmlSchemaObjectTable table )
{
IDictionaryEnumerator e = table.GetEnumerator();
while( e.MoveNext() )
{
outSch.Items.Add( (XmlSchemaObject)e.Value );
}
}
}
Probar la herramienta de preprocesador
Puede utilizar los esquemas XSD siguientes para probar la herramienta de preprocesador:
books_common.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="bookstore-schema"
elementFormDefault="qualified" >
<xsd:element name="publisher" type="xsd:string"/>
</xsd:schema>
books.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="bookstore-schema"
elementFormDefault="qualified"
targetNamespace="bookstore-schema">
<xsd:include id="books_common" schemaLocation="books_common.xsd"/>
<xsd:element name="bookstore" type="xsd:string" />
</xsd:schema>