Procházet zdrojové kódy

2003-06-04 Atsushi Enomoto <[email protected]>

	* (temporarily) added XSD2Class.cs.

svn path=/trunk/mcs/; revision=15089
Atsushi Eno před 22 roky
rodič
revize
72d640f0cb
2 změnil soubory, kde provedl 360 přidání a 0 odebrání
  1. 4 0
      mcs/tools/mono-xsd/ChangeLog
  2. 356 0
      mcs/tools/mono-xsd/XSD2Class.cs

+ 4 - 0
mcs/tools/mono-xsd/ChangeLog

@@ -1,3 +1,7 @@
+2003-06-04  Atsushi Enomoto <[email protected]>
+
+	* (temporarily) added XSD2Class.cs.
+
 2003-03-25  Duncan Mak  <[email protected]>
 
 	* MonoXSD.cs: Added support for two command line arguments:

+ 356 - 0
mcs/tools/mono-xsd/XSD2Class.cs

@@ -0,0 +1,356 @@
+//
+// XSD2Class - xml schema based class generator
+//
+// Author
+//	Atsushi Enomoto ([email protected])
+//
+// (C)2003 Atsushi Enomoto
+//
+// TODO:
+//	* Currently it is developed with MS.NET and Microsoft.CSharp namespace.
+//	* Handling members of choice fields are incomplete. No enum members are
+//	  collected and registered as the member.
+//	* Members should be checked their names, and should be supplied
+//	  XmlAttributeAttribute or XmlElementAttribute when their names already
+//	  exists.
+//
+//	* It is desirable to have an alternative generator that generates
+//	  property members instead of simple fields, which checks their values 
+//	  in relation to their facets.
+//
+
+using System;
+using System.CodeDom;
+using System.Collections;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.Serialization;
+using Microsoft.CSharp;
+
+namespace Mono.Xml.Schema
+{
+	public class Driver
+	{
+		public static void Main (string [] args)
+		{
+			if (args.Length < 1) {
+				Console.WriteLine ("usage: xsd2class [filename]");
+				return;
+			}
+			XmlTextReader xtr = new XmlTextReader (args [0]);
+//			xtr.XmlResolver = null;
+			XmlSchema xs = XmlSchema.Read (xtr, null);
+			xs.Compile (null);
+			XmlSchemas schemas = new XmlSchemas ();
+			schemas.Add (xs);
+			new XSD2Class (schemas).Generate ();
+		}
+	}
+
+	public class XSD2Class
+	{
+		XmlSchemas schemas;
+		CodeCompileUnit codeCompileUnit;
+		CodeNamespace codeNamespace;
+		CodeTypeDeclaration currentType;
+		Hashtable codeTypes = new Hashtable ();
+
+		public XSD2Class (XmlSchemas schemas)
+			: this (schemas, new CodeNamespace ())
+		{
+		}
+
+		public XSD2Class (XmlSchemas schemas, CodeNamespace codeNamespace)
+			: this (schemas, codeNamespace, new CodeCompileUnit ())
+		{
+		}
+
+		public XSD2Class (XmlSchemas schemas,
+			CodeNamespace codeNamespace,
+			CodeCompileUnit codeCompileUnit)
+		{
+			this.schemas = schemas;
+			this.codeCompileUnit = codeCompileUnit;
+			this.codeNamespace = codeNamespace;
+			codeCompileUnit.Namespaces.Add (codeNamespace);
+		}
+
+		public void Generate ()
+		{
+			foreach (XmlSchema schema in schemas)
+				GenerateSchemaTypes (schema);
+			new CSharpCodeProvider ().CreateGenerator ().GenerateCodeFromCompileUnit (codeCompileUnit, Console.Out, null);
+		}
+
+		public void GenerateSchemaTypes (XmlSchema schema)
+		{
+			foreach (XmlSchemaObject sob in schema.Items) {
+				XmlSchemaElement element = sob as XmlSchemaElement;
+				if (element == null)
+					continue;
+				XmlSchemaComplexType xsType =
+					FindComplexType (element.SchemaTypeName);
+				if (xsType != null)
+					GenerateComplexTypeCode (xsType);
+			}
+		}
+		
+		public XmlTypeMapping ImportTypeMapping (XmlQualifiedName qname)
+		{
+			XmlSchemaComplexType xsType = FindComplexType (qname);
+			if (xsType == null)
+				throw new InvalidOperationException ("Type " + qname + " not found.");
+
+			GenerateComplexTypeCode (xsType);
+			return null;
+		}
+
+		private XmlSchemaComplexType FindComplexType (XmlQualifiedName qname)
+		{
+			foreach (XmlSchema schema in schemas) {
+				foreach (XmlQualifiedName name in schema.SchemaTypes.Names) {
+					XmlSchemaType xsType = schema.SchemaTypes [name] as XmlSchemaType;
+					if (xsType is XmlSchemaSimpleType)
+						continue;
+					if (xsType.QualifiedName == qname)
+							return xsType as XmlSchemaComplexType;
+				}
+			}
+			return null;
+		}
+
+		private XmlSchemaGroup FindGroup (XmlQualifiedName qname)
+		{
+			foreach (XmlSchema schema in schemas) {
+				foreach (XmlQualifiedName name in schema.Groups.Names) {
+					XmlSchemaGroup group = schema.Groups [name] as XmlSchemaGroup;
+					if (group.Name == qname.Name)
+						return group;
+				}
+			}
+			return null;
+		}
+
+		private void GenerateComplexTypeCode (XmlSchemaComplexType xsType)
+		{
+			string typeName = xsType.QualifiedName.Name;
+			if (codeTypes.Contains (typeName))
+				return;
+Console.Out.WriteLine ("type " + typeName);
+
+			currentType = new CodeTypeDeclaration (typeName);
+			codeTypes.Add (xsType.QualifiedName.Name, currentType);
+			// anyAttribute
+			if (xsType.AnyAttribute != null) {
+				CodeMemberField cmf = new CodeMemberField (typeof (XmlAttribute), "AnyAttr");
+				cmf.Attributes = MemberAttributes.Public;
+				currentType.Members.Add (cmf);
+			}
+
+			// attributes
+			foreach (XmlSchemaAttribute schemaAtt in xsType.Attributes)
+				GenerateAttributeField (schemaAtt);
+
+			// elements
+			if (xsType.Particle != null) {
+				// particle
+				GenerateParticleField (xsType.Particle);
+			} else if (xsType.ContentModel != null) {
+				// content model
+				throw new NotImplementedException ();
+			}
+			codeNamespace.Types.Add (currentType);
+		}
+
+		private void GenerateAttributeField (XmlSchemaAttribute schemaAtt)
+		{
+			XmlSchemaDatatype primitive = schemaAtt.AttributeType 
+				as XmlSchemaDatatype;
+			XmlSchemaSimpleType simple = schemaAtt.AttributeType 
+				as XmlSchemaSimpleType;
+			while (primitive == null) {
+				simple = simple.BaseSchemaType 
+					as XmlSchemaSimpleType;
+				primitive = simple.BaseSchemaType 
+					as XmlSchemaDatatype;
+			}
+
+			CodeMemberField cmf = new CodeMemberField (primitive.ValueType, schemaAtt.QualifiedName.Name);
+			cmf.Attributes = MemberAttributes.Public;
+			cmf.CustomAttributes.Add (new CodeAttributeDeclaration (typeof (XmlAttributeAttribute).FullName));
+			currentType.Members.Add (cmf);
+		}
+
+		private void GenerateElementField (XmlSchemaElement schemaElem)
+		{
+			CodeMemberField cmf;
+
+			XmlSchemaDatatype dt = 
+				schemaElem.ElementType as XmlSchemaDatatype;
+			XmlSchemaSimpleType st = 
+				schemaElem.ElementType as XmlSchemaSimpleType;
+			if (st != null)
+				dt = st.Datatype;
+			if (dt != null) {
+				// simple type member.
+				cmf = new CodeMemberField (dt.ValueType,
+					schemaElem.QualifiedName.Name);
+				cmf.Attributes = MemberAttributes.Public;
+				currentType.Members.Add (cmf);
+			} else {
+				// complex type member.
+				XmlSchemaComplexType ct = schemaElem.ElementType
+					as XmlSchemaComplexType;
+
+				CodeTypeDeclaration ctd = currentType;
+				GenerateComplexTypeCode (ct);
+				currentType = ctd;
+				cmf = new CodeMemberField (new CodeTypeReference (ct.QualifiedName.Name), schemaElem.QualifiedName.Name);
+				cmf.Attributes = MemberAttributes.Public;
+				currentType.Members.Add (cmf);
+			}
+		}
+
+		private void GenerateParticleField (XmlSchemaParticle particle)
+		{
+			if (particle is XmlSchemaAny)
+				GenerateParticleAnyField (particle 
+					as XmlSchemaAny);
+			else if (particle is XmlSchemaElement)
+				GenerateElementField (particle 
+					as XmlSchemaElement);
+			else if (particle is XmlSchemaAll)
+				GenerateParticleAllField (particle 
+					as XmlSchemaAll);
+			else if (particle is XmlSchemaChoice)
+				GenerateParticleChoiceField (particle 
+					as XmlSchemaChoice);
+			else if (particle is XmlSchemaSequence)
+				GenerateParticleSequenceField (particle 
+					as XmlSchemaSequence);
+			else if (particle is XmlSchemaGroupRef) {
+				XmlSchemaGroupRef gRef = particle 
+					as XmlSchemaGroupRef;
+				GenerateGroupField (FindGroup (gRef.RefName));
+			}
+		}
+
+		private void GenerateParticleAnyField (XmlSchemaAny xsany)
+		{
+			CodeMemberField cmf = new CodeMemberField (
+				typeof (XmlElement), "Any");
+			cmf.Attributes = MemberAttributes.Public;
+			currentType.Members.Add (cmf);
+		}
+
+		private void GenerateParticleAllField (XmlSchemaAll xsall)
+		{
+			foreach (XmlSchemaParticle cp in xsall.Items)
+				GenerateParticleField (cp);
+		}
+
+		private void GenerateParticleSequenceField (XmlSchemaSequence sequence)
+		{
+			foreach (XmlSchemaParticle cp in sequence.Items)
+				GenerateParticleField (cp);
+		}
+
+		private bool CodeTypeContains (string name)
+		{
+			for (int i=0; i<codeNamespace.Types.Count; i++)
+				if (codeNamespace.Types [i].Name == name)
+					return true;
+			return false;
+		}
+
+		private bool CodeMemberContains (string name)
+		{
+			for (int i=0; i<currentType.Members.Count; i++)
+				if (currentType.Members [i].Name == name)
+					return true;
+			return false;
+		}
+
+		private void GenerateParticleChoiceField (XmlSchemaChoice choice)
+		{
+			// TODO: first, check all choice alternatives that
+			// they might be common typed elements. In such case,
+			// no enum fields and types should be created.
+
+			// generate choice identifier enum type
+			int i = 1;
+			string itemName = "Item";
+			if (CodeMemberContains (itemName)) {
+				while (CodeMemberContains (itemName + i))
+					i++;
+				itemName = itemName + i;
+			}
+			i = 1;
+			string enumFieldName = "ItemElementType";
+			if (CodeMemberContains (enumFieldName)) {
+				while (CodeMemberContains (enumFieldName  + i))
+					i++;
+				enumFieldName = enumFieldName + i;
+			}
+			i = 1;
+			string typeName = "ItemChoiceType";
+			if (CodeTypeContains (typeName)) {
+				while (CodeTypeContains (typeName + i))
+					i++;
+				typeName = typeName + i;
+			}
+
+			// enum type generation
+			CodeTypeDeclaration enumType = 
+				new CodeTypeDeclaration (typeName);
+			enumType.IsEnum = true;
+			CodeAttributeDeclaration enumXmlType = 
+				new CodeAttributeDeclaration (
+					typeof (XmlTypeAttribute).FullName);
+			// [XmlType (IncludeInSchema=false)]
+			enumXmlType.Arguments.Add (
+				new CodeAttributeArgument ("IncludeInSchema",
+					new CodePrimitiveExpression (false)));
+			enumType.CustomAttributes.Add (enumXmlType);
+			// TODO: how to add enum members?
+
+			// add item field
+			CodeMemberField cmf = new CodeMemberField (
+				typeof (object), itemName);
+			cmf.Attributes = MemberAttributes.Public;
+			CodeAttributeDeclaration choiceIdent =
+				new CodeAttributeDeclaration (
+				typeof (XmlChoiceIdentifierAttribute).FullName);
+			choiceIdent.Arguments.Add (new CodeAttributeArgument (
+				"MemberName",
+				new CodePrimitiveExpression (enumFieldName)));
+			cmf.CustomAttributes.Add (choiceIdent);
+			currentType.Members.Add (cmf);
+
+			// add enum field
+			codeNamespace.Types.Add (enumType);
+
+			CodeMemberField cid = new CodeMemberField (
+				new CodeTypeReference (typeName), enumFieldName);
+			currentType.Members.Add (cid);
+
+		}
+
+		private void GenerateGroupField (XmlSchemaGroup group)
+		{
+			GenerateParticleField (group.Particle);
+		}
+
+/*
+		private CodeAttributeDeclaration CreateXmlAttribute (Type attrType, string name)
+		{
+			CodeAttributeDeclaration xmlAtt = new CodeAttributeDeclaration (attrType.FullName);
+			if (name != null)
+				xmlAtt.Arguments.Add (new CodeAttributeArgument ("Name", new CodePrimitiveExpression (name)));
+
+			return xmlAtt;
+		}
+*/
+	}
+}