Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C#

An XML Schema Definition (XSD) Editor

Rate me:
Please Sign up or sign in to vote.
4.89/5 (90 votes)
14 Oct 20035 min read 406.7K   11.1K   189  
An editor capable of producing common XSD documents
/*
 * XML Schema Editor
 * This code may be freely modified and distributed.
 * 
 * History:
 * 
 * Version 1.0
 *	First release, Marc Clifton
*/
/*
 * Version 1.0
 * 
 * Quirks:
 *	1. Clicking on node A while in the middle of editing node B results in the name being changed for node A (mouse down event handler sets the current node!)
 *	2. After editing the schema in the text edit box, you MUST compile otherwise changes will be lost!
 *	3. If the tree node doesn't match the schema object, there are blank lines in the XSD file which are causing synchronization problems.  Select "Schema/Compile" from menu.
 * 
 * Bugs:
 *   1. Editing the name of a complex type adds a "name" to the CT, not the parent element
 * 
 * Features:
 *	dynamically adjusts for global and local types
 *	dynamically creates complex types from elements
 *	selecting a tree node highlights the corresponding XML text
 *	compiler error window
 *	xml can be edited directly instead of using the tree
 *	creates and manages global types list as types are added and removed
 *	keyboard shortcuts:
 *		F2-edit node label
 *		Ctrl-A : add to schema at current node
 *		Ctrl-T : go to top of schema
 *		Ctrl-P : got to parent of current node
 * 
 * Notes:
 * 
 * Need to do:
 * 
 * Missing features:
 *	Auto-scroll edit box to show selected node
 *	Remember selected node when compiling schema
 *	Implement XmlSchemaElement minOccurs and maxOccurs with GUI to enter values
 *	Implement XmlSchemaAttribute fixed and use with GUI to enter values
 *	Implement XmlSchemaGroup
 *	...others?
 * 
 */

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;

namespace xmlSchemaEditor
{
	public class SchemaEditor : System.Windows.Forms.Form
	{
		#region data
		private System.Windows.Forms.TreeView tvSchema;
		private System.Windows.Forms.ContextMenu tvcmSchema;
		private System.Windows.Forms.MenuItem mnuAddElement;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.TextBox edSchema;
		private System.Windows.Forms.MenuItem mnuAddSimpleType;
		private System.Windows.Forms.MenuItem mnuAddComplexType;
		private System.Windows.Forms.MainMenu mainMenu;
		private System.Windows.Forms.MenuItem mnuFile;
		private System.Windows.Forms.MenuItem mnuNew;
		private System.Windows.Forms.MenuItem mnuOpen;
		private System.Windows.Forms.MenuItem mnuSave;
		private System.Windows.Forms.MenuItem mnuSaveAs;
		private System.Windows.Forms.MenuItem mnuExit;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem mnuAbout;
		private System.Windows.Forms.OpenFileDialog openSchemaDialog;
		private System.Windows.Forms.ImageList tvImageList;
		private System.Windows.Forms.MenuItem mnuAddAnnotation;
		private System.Windows.Forms.MenuItem mnuAddAttribute;
		private System.Windows.Forms.TextBox edSchemaErrors;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem mnuCompile;
		private System.Windows.Forms.GroupBox gbSelectType;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem mnuRemoveNode;
		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.ComboBox cbGlobalTypes;
		private System.Windows.Forms.ComboBox cbSimpleTypes;
		private XmlSchema schema;
		private System.Windows.Forms.MenuItem mnuFacetEnumeration;
		private System.Windows.Forms.MenuItem mnuFacetMaxExclusive;
		private System.Windows.Forms.MenuItem mnuFacetMaxInclusive;
		private System.Windows.Forms.MenuItem mnuFacetMinExclusive;
		private System.Windows.Forms.MenuItem mnuFacetMinInclusive;
		private System.Windows.Forms.MenuItem mnuFacetNumeric;
		private System.Windows.Forms.MenuItem mnuFacetPattern;
		private System.Windows.Forms.MenuItem mnuFacetWhiteSpace;
		private System.Windows.Forms.MenuItem mnuFacetFractionDigits;
		private System.Windows.Forms.MenuItem mnuFacetLength;
		private System.Windows.Forms.MenuItem mnuFacetMaxLength;
		private System.Windows.Forms.MenuItem mnuFacetMinLength;
		private System.Windows.Forms.MenuItem mnuFacetTotalDigits;
		private System.Windows.Forms.MenuItem mnuAddDocumentation;
		private System.Windows.Forms.MenuItem mnuAddAppInfo;
		private string prevLabel;
		private System.Windows.Forms.SaveFileDialog saveAsSchemaDialog;
		private string fileName=null;
		enum TreeViewImages {Schema, Element, SimpleType, ComplexType, Annotation, Documentation, AppInfo, Attribute, Facet};
		#endregion

		#region GlobalElementType
		public class GlobalElementType
		{
			public GlobalElementType(string name, XmlSchemaObject type)
			{
				this.name=name;
				this.type=type;
			}

			public override string ToString()
			{
				return name;
			}

			public string Get()
			{
				return name;
			}

			public void Set(string name)
			{
				this.name=name;
			}

			public string name;
			public XmlSchemaObject type;
		}
		#endregion

		#region SchemaEditor Class
		public SchemaEditor()
		{
			InitializeComponent();
			CreateRootNode();
			tvSchema.LabelEdit=true;
			tvSchema.KeyUp+=new KeyEventHandler(EventTreeViewKeyUp);
			tvSchema.BeforeLabelEdit+=new NodeLabelEditEventHandler(PreEventLabelChanged);
			tvSchema.AfterLabelEdit+=new NodeLabelEditEventHandler(EventLabelChanged);
			tvSchema.MouseDown+=new MouseEventHandler(EventMouseDown);
			edSchema.LostFocus+=new EventHandler(EventSchemaTextBoxLostFocus);
			schema=new XmlSchema();
			CompileSchema();
		}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		static void Main() 
		{
			Application.Run(new SchemaEditor());
		}

		#endregion

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(SchemaEditor));
			this.tvSchema = new System.Windows.Forms.TreeView();
			this.tvcmSchema = new System.Windows.Forms.ContextMenu();
			this.mnuAddElement = new System.Windows.Forms.MenuItem();
			this.mnuAddSimpleType = new System.Windows.Forms.MenuItem();
			this.mnuAddComplexType = new System.Windows.Forms.MenuItem();
			this.mnuAddAttribute = new System.Windows.Forms.MenuItem();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.mnuAddAnnotation = new System.Windows.Forms.MenuItem();
			this.mnuAddDocumentation = new System.Windows.Forms.MenuItem();
			this.mnuAddAppInfo = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem7 = new System.Windows.Forms.MenuItem();
			this.mnuFacetEnumeration = new System.Windows.Forms.MenuItem();
			this.mnuFacetMaxExclusive = new System.Windows.Forms.MenuItem();
			this.mnuFacetMaxInclusive = new System.Windows.Forms.MenuItem();
			this.mnuFacetMinExclusive = new System.Windows.Forms.MenuItem();
			this.mnuFacetMinInclusive = new System.Windows.Forms.MenuItem();
			this.mnuFacetNumeric = new System.Windows.Forms.MenuItem();
			this.mnuFacetFractionDigits = new System.Windows.Forms.MenuItem();
			this.mnuFacetLength = new System.Windows.Forms.MenuItem();
			this.mnuFacetMaxLength = new System.Windows.Forms.MenuItem();
			this.mnuFacetMinLength = new System.Windows.Forms.MenuItem();
			this.mnuFacetTotalDigits = new System.Windows.Forms.MenuItem();
			this.mnuFacetPattern = new System.Windows.Forms.MenuItem();
			this.mnuFacetWhiteSpace = new System.Windows.Forms.MenuItem();
			this.menuItem6 = new System.Windows.Forms.MenuItem();
			this.mnuRemoveNode = new System.Windows.Forms.MenuItem();
			this.tvImageList = new System.Windows.Forms.ImageList(this.components);
			this.edSchema = new System.Windows.Forms.TextBox();
			this.mainMenu = new System.Windows.Forms.MainMenu();
			this.mnuFile = new System.Windows.Forms.MenuItem();
			this.mnuNew = new System.Windows.Forms.MenuItem();
			this.mnuOpen = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.mnuSave = new System.Windows.Forms.MenuItem();
			this.mnuSaveAs = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.mnuExit = new System.Windows.Forms.MenuItem();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.mnuCompile = new System.Windows.Forms.MenuItem();
			this.mnuAbout = new System.Windows.Forms.MenuItem();
			this.openSchemaDialog = new System.Windows.Forms.OpenFileDialog();
			this.edSchemaErrors = new System.Windows.Forms.TextBox();
			this.gbSelectType = new System.Windows.Forms.GroupBox();
			this.cbGlobalTypes = new System.Windows.Forms.ComboBox();
			this.cbSimpleTypes = new System.Windows.Forms.ComboBox();
			this.label2 = new System.Windows.Forms.Label();
			this.label1 = new System.Windows.Forms.Label();
			this.saveAsSchemaDialog = new System.Windows.Forms.SaveFileDialog();
			this.gbSelectType.SuspendLayout();
			this.SuspendLayout();
			// 
			// tvSchema
			// 
			this.tvSchema.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left);
			this.tvSchema.ContextMenu = this.tvcmSchema;
			this.tvSchema.FullRowSelect = true;
			this.tvSchema.HideSelection = false;
			this.tvSchema.ImageList = this.tvImageList;
			this.tvSchema.Location = new System.Drawing.Point(8, 8);
			this.tvSchema.Name = "tvSchema";
			this.tvSchema.Size = new System.Drawing.Size(280, 432);
			this.tvSchema.TabIndex = 0;
			this.tvSchema.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.tvSchema_AfterSelect);
			// 
			// tvcmSchema
			// 
			this.tvcmSchema.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																		 this.mnuAddElement,
																		 this.mnuAddSimpleType,
																		 this.mnuAddComplexType,
																		 this.mnuAddAttribute,
																		 this.menuItem9,
																		 this.menuItem5,
																		 this.menuItem4,
																		 this.menuItem7,
																		 this.menuItem6,
																		 this.mnuRemoveNode});
			// 
			// mnuAddElement
			// 
			this.mnuAddElement.Index = 0;
			this.mnuAddElement.Text = "Element";
			this.mnuAddElement.Click += new System.EventHandler(this.mnuAddElement_Click);
			// 
			// mnuAddSimpleType
			// 
			this.mnuAddSimpleType.Index = 1;
			this.mnuAddSimpleType.Text = "Simple Type";
			this.mnuAddSimpleType.Click += new System.EventHandler(this.mnuAddSimpleType_Click);
			// 
			// mnuAddComplexType
			// 
			this.mnuAddComplexType.Index = 2;
			this.mnuAddComplexType.Text = "Complex Type";
			this.mnuAddComplexType.Click += new System.EventHandler(this.mnuAddComplexType_Click);
			// 
			// mnuAddAttribute
			// 
			this.mnuAddAttribute.Index = 3;
			this.mnuAddAttribute.Text = "Attribute";
			this.mnuAddAttribute.Click += new System.EventHandler(this.mnuAddAttribute_Click);
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 4;
			this.menuItem9.Text = "-";
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 5;
			this.menuItem5.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																		this.mnuAddAnnotation,
																		this.mnuAddDocumentation,
																		this.mnuAddAppInfo});
			this.menuItem5.Text = "Annotation";
			// 
			// mnuAddAnnotation
			// 
			this.mnuAddAnnotation.Index = 0;
			this.mnuAddAnnotation.Text = "Annotation";
			this.mnuAddAnnotation.Click += new System.EventHandler(this.mnuAddAnnotation_Click);
			// 
			// mnuAddDocumentation
			// 
			this.mnuAddDocumentation.Index = 1;
			this.mnuAddDocumentation.Text = "Documentation";
			this.mnuAddDocumentation.Click += new System.EventHandler(this.mnuAddDocumentation_Click);
			// 
			// mnuAddAppInfo
			// 
			this.mnuAddAppInfo.Index = 2;
			this.mnuAddAppInfo.Text = "App Info";
			this.mnuAddAppInfo.Click += new System.EventHandler(this.mnuAddAppInfo_Click);
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 6;
			this.menuItem4.Text = "-";
			// 
			// menuItem7
			// 
			this.menuItem7.Index = 7;
			this.menuItem7.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																		this.mnuFacetEnumeration,
																		this.mnuFacetMaxExclusive,
																		this.mnuFacetMaxInclusive,
																		this.mnuFacetMinExclusive,
																		this.mnuFacetMinInclusive,
																		this.mnuFacetNumeric,
																		this.mnuFacetPattern,
																		this.mnuFacetWhiteSpace});
			this.menuItem7.Text = "Facet";
			// 
			// mnuFacetEnumeration
			// 
			this.mnuFacetEnumeration.Index = 0;
			this.mnuFacetEnumeration.Text = "Enumeration";
			this.mnuFacetEnumeration.Click += new System.EventHandler(this.mnuFacetEnumeration_Click);
			// 
			// mnuFacetMaxExclusive
			// 
			this.mnuFacetMaxExclusive.Index = 1;
			this.mnuFacetMaxExclusive.Text = "Max Exclusive";
			this.mnuFacetMaxExclusive.Click += new System.EventHandler(this.mnuFacetMaxExclusive_Click);
			// 
			// mnuFacetMaxInclusive
			// 
			this.mnuFacetMaxInclusive.Index = 2;
			this.mnuFacetMaxInclusive.Text = "Max Inclusive";
			this.mnuFacetMaxInclusive.Click += new System.EventHandler(this.mnuFacetMaxInclusive_Click);
			// 
			// mnuFacetMinExclusive
			// 
			this.mnuFacetMinExclusive.Index = 3;
			this.mnuFacetMinExclusive.Text = "Min Exclusive";
			this.mnuFacetMinExclusive.Click += new System.EventHandler(this.mnuFacetMinExclusive_Click);
			// 
			// mnuFacetMinInclusive
			// 
			this.mnuFacetMinInclusive.Index = 4;
			this.mnuFacetMinInclusive.Text = "Min Inclusive";
			this.mnuFacetMinInclusive.Click += new System.EventHandler(this.mnuFacetMinInclusive_Click);
			// 
			// mnuFacetNumeric
			// 
			this.mnuFacetNumeric.Index = 5;
			this.mnuFacetNumeric.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																			 this.mnuFacetFractionDigits,
																			 this.mnuFacetLength,
																			 this.mnuFacetMaxLength,
																			 this.mnuFacetMinLength,
																			 this.mnuFacetTotalDigits});
			this.mnuFacetNumeric.Text = "Numeric";
			// 
			// mnuFacetFractionDigits
			// 
			this.mnuFacetFractionDigits.Index = 0;
			this.mnuFacetFractionDigits.Text = "Fraction Digits";
			this.mnuFacetFractionDigits.Click += new System.EventHandler(this.mnuFacetFractionDigits_Click);
			// 
			// mnuFacetLength
			// 
			this.mnuFacetLength.Index = 1;
			this.mnuFacetLength.Text = "Length";
			this.mnuFacetLength.Click += new System.EventHandler(this.mnuFacetLength_Click);
			// 
			// mnuFacetMaxLength
			// 
			this.mnuFacetMaxLength.Index = 2;
			this.mnuFacetMaxLength.Text = "Max Length";
			this.mnuFacetMaxLength.Click += new System.EventHandler(this.mnuFacetMaxLength_Click);
			// 
			// mnuFacetMinLength
			// 
			this.mnuFacetMinLength.Index = 3;
			this.mnuFacetMinLength.Text = "Min Length";
			this.mnuFacetMinLength.Click += new System.EventHandler(this.mnuFacetMinLength_Click);
			// 
			// mnuFacetTotalDigits
			// 
			this.mnuFacetTotalDigits.Index = 4;
			this.mnuFacetTotalDigits.Text = "Total Digits";
			this.mnuFacetTotalDigits.Click += new System.EventHandler(this.mnuFacetTotalDigits_Click);
			// 
			// mnuFacetPattern
			// 
			this.mnuFacetPattern.Index = 6;
			this.mnuFacetPattern.Text = "Pattern";
			this.mnuFacetPattern.Click += new System.EventHandler(this.mnuFacetPattern_Click);
			// 
			// mnuFacetWhiteSpace
			// 
			this.mnuFacetWhiteSpace.Index = 7;
			this.mnuFacetWhiteSpace.Text = "White Space";
			this.mnuFacetWhiteSpace.Click += new System.EventHandler(this.mnuFacetWhiteSpace_Click);
			// 
			// menuItem6
			// 
			this.menuItem6.Index = 8;
			this.menuItem6.Text = "-";
			// 
			// mnuRemoveNode
			// 
			this.mnuRemoveNode.Index = 9;
			this.mnuRemoveNode.Text = "Remove";
			this.mnuRemoveNode.Click += new System.EventHandler(this.mnuRemoveNode_Click);
			// 
			// tvImageList
			// 
			this.tvImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
			this.tvImageList.ImageSize = new System.Drawing.Size(16, 16);
			this.tvImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("tvImageList.ImageStream")));
			this.tvImageList.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// edSchema
			// 
			this.edSchema.AcceptsReturn = true;
			this.edSchema.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right);
			this.edSchema.HideSelection = false;
			this.edSchema.Location = new System.Drawing.Point(296, 8);
			this.edSchema.Multiline = true;
			this.edSchema.Name = "edSchema";
			this.edSchema.ScrollBars = System.Windows.Forms.ScrollBars.Both;
			this.edSchema.Size = new System.Drawing.Size(640, 432);
			this.edSchema.TabIndex = 1;
			this.edSchema.Text = "";
			this.edSchema.WordWrap = false;
			// 
			// mainMenu
			// 
			this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																	    this.mnuFile,
																	    this.menuItem1,
																	    this.mnuAbout});
			// 
			// mnuFile
			// 
			this.mnuFile.Index = 0;
			this.mnuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																	   this.mnuNew,
																	   this.mnuOpen,
																	   this.menuItem3,
																	   this.mnuSave,
																	   this.mnuSaveAs,
																	   this.menuItem2,
																	   this.mnuExit});
			this.mnuFile.Text = "&File";
			// 
			// mnuNew
			// 
			this.mnuNew.Index = 0;
			this.mnuNew.Text = "&New";
			this.mnuNew.Click += new System.EventHandler(this.mnuNew_Click);
			// 
			// mnuOpen
			// 
			this.mnuOpen.Index = 1;
			this.mnuOpen.Text = "&Open";
			this.mnuOpen.Click += new System.EventHandler(this.mnuOpen_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 2;
			this.menuItem3.Text = "-";
			// 
			// mnuSave
			// 
			this.mnuSave.Index = 3;
			this.mnuSave.Text = "&Save";
			this.mnuSave.Click += new System.EventHandler(this.mnuSave_Click);
			// 
			// mnuSaveAs
			// 
			this.mnuSaveAs.Index = 4;
			this.mnuSaveAs.Text = "Save &As";
			this.mnuSaveAs.Click += new System.EventHandler(this.mnuSaveAs_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 5;
			this.menuItem2.Text = "-";
			// 
			// mnuExit
			// 
			this.mnuExit.Index = 6;
			this.mnuExit.Text = "E&xit";
			this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 1;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																		this.mnuCompile});
			this.menuItem1.Text = "&Schema";
			// 
			// mnuCompile
			// 
			this.mnuCompile.Index = 0;
			this.mnuCompile.Text = "&Compile";
			this.mnuCompile.Click += new System.EventHandler(this.mnuCompile_Click);
			// 
			// mnuAbout
			// 
			this.mnuAbout.Index = 2;
			this.mnuAbout.Text = "&About";
			this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click);
			// 
			// edSchemaErrors
			// 
			this.edSchemaErrors.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right);
			this.edSchemaErrors.HideSelection = false;
			this.edSchemaErrors.Location = new System.Drawing.Point(296, 448);
			this.edSchemaErrors.Multiline = true;
			this.edSchemaErrors.Name = "edSchemaErrors";
			this.edSchemaErrors.ReadOnly = true;
			this.edSchemaErrors.ScrollBars = System.Windows.Forms.ScrollBars.Both;
			this.edSchemaErrors.Size = new System.Drawing.Size(640, 88);
			this.edSchemaErrors.TabIndex = 2;
			this.edSchemaErrors.Text = "";
			// 
			// gbSelectType
			// 
			this.gbSelectType.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
			this.gbSelectType.Controls.AddRange(new System.Windows.Forms.Control[] {
																		 this.cbGlobalTypes,
																		 this.cbSimpleTypes,
																		 this.label2,
																		 this.label1});
			this.gbSelectType.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.gbSelectType.Location = new System.Drawing.Point(8, 440);
			this.gbSelectType.Name = "gbSelectType";
			this.gbSelectType.Size = new System.Drawing.Size(280, 96);
			this.gbSelectType.TabIndex = 3;
			this.gbSelectType.TabStop = false;
			this.gbSelectType.Text = "Select Type";
			// 
			// cbGlobalTypes
			// 
			this.cbGlobalTypes.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.cbGlobalTypes.Location = new System.Drawing.Point(88, 56);
			this.cbGlobalTypes.Name = "cbGlobalTypes";
			this.cbGlobalTypes.Size = new System.Drawing.Size(168, 21);
			this.cbGlobalTypes.Sorted = true;
			this.cbGlobalTypes.TabIndex = 3;
			this.cbGlobalTypes.SelectedIndexChanged += new System.EventHandler(this.cbGlobalTypes_SelectedIndexChanged);
			// 
			// cbSimpleTypes
			// 
			this.cbSimpleTypes.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.cbSimpleTypes.Items.AddRange(new object[] {
													  "anyURI",
													  "base64Binary",
													  "boolean",
													  "byte",
													  "date",
													  "dateTime",
													  "decimal",
													  "double",
													  "duration",
													  "ENTITIY",
													  "float",
													  "gDay",
													  "gMonth",
													  "gMonthDay",
													  "gYear",
													  "gYearMonth",
													  "hexBinary",
													  "ID",
													  "IDREF",
													  "imteger",
													  "int",
													  "language",
													  "long",
													  "Name",
													  "NCName",
													  "negativeInteger",
													  "NMTOKEN",
													  "nonNegativeInteger",
													  "nonPositiveInteger",
													  "normalizedString",
													  "NOTATION",
													  "positiveInteger",
													  "QName",
													  "short",
													  "string",
													  "time",
													  "token",
													  "unsignedByte",
													  "unsignedInt",
													  "unsignedLong",
													  "unsignedShort"});
			this.cbSimpleTypes.Location = new System.Drawing.Point(88, 24);
			this.cbSimpleTypes.Name = "cbSimpleTypes";
			this.cbSimpleTypes.Size = new System.Drawing.Size(168, 21);
			this.cbSimpleTypes.Sorted = true;
			this.cbSimpleTypes.TabIndex = 2;
			this.cbSimpleTypes.SelectedIndexChanged += new System.EventHandler(this.cbSimpleTypes_SelectedIndexChanged);
			// 
			// label2
			// 
			this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label2.Location = new System.Drawing.Point(8, 58);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(80, 16);
			this.label2.TabIndex = 1;
			this.label2.Text = "Global Types:";
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label1.Location = new System.Drawing.Point(8, 26);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(80, 16);
			this.label1.TabIndex = 0;
			this.label1.Text = "Simple Types:";
			// 
			// saveAsSchemaDialog
			// 
			this.saveAsSchemaDialog.DefaultExt = "xsd";
			// 
			// SchemaEditor
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(944, 553);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
															   this.gbSelectType,
															   this.edSchemaErrors,
															   this.edSchema,
															   this.tvSchema});
			this.Menu = this.mainMenu;
			this.Name = "SchemaEditor";
			this.Text = "XML Schema Editor";
			this.gbSelectType.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion


		#region Menu Commands

		#region Add Facets
		// There are several types of facets that can be added to a simple type.
		// This code adds a facet and specifies a default value (completely arbitrary)

		private void mnuFacetEnumeration_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaEnumerationFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxExclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxExclusiveFacet(), "101", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxInclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxInclusiveFacet(), "100", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinExclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinExclusiveFacet(), "0", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinInclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinInclusiveFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetFractionDigits_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaFractionDigitsFacet(), "2", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaLengthFacet(), "16", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxLengthFacet(), "16", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinLengthFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetTotalDigits_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaTotalDigitsFacet(), "8", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}


		private void mnuFacetPattern_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaPatternFacet(), "[0-9]", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetWhiteSpace_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaWhiteSpaceFacet(), "collapse", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}
		#endregion

		#region Add Annotation, Documentation, and AppInfo
		// create an annotation for the schema or for an annotatable object
		private void mnuAddAnnotation_Click(object sender, System.EventArgs e)
		{
			XmlSchemaAnnotation annot=new XmlSchemaAnnotation();
			TreeNode newNode=CreateNode("--annotation--");

			// if adding at the schema root level...
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				AddToCollection(schema.Items, annot, newNode, TreeViewImages.Annotation);
			}
			else
			{
				// otherwise, get the object as an XmlSchemaAnnotated type
				XmlSchemaAnnotated obj=newNode.Parent.Tag as XmlSchemaAnnotated;
				if (obj != null)
				{
					// if it exists, add the annotation
					obj.Annotation=annot;
					newNode.Tag=annot;
					newNode.ImageIndex=(int)TreeViewImages.Annotation;
					newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
					CompileSchema();
				}
				else
				{
					// otherwise, tell the user annotation cannot be added to this type.
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot create an annotation for this item.");
				}
			}
		}

		private void mnuAddDocumentation_Click(object sender, System.EventArgs e)
		{
			bool success=false;
			XmlSchemaAnnotation annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
			// if the parent node is an annotation type...
			if (annot != null)
			{
				// ...then add the documentation type
				TreeNode newNode=CreateNode("--documentation--");
				XmlSchemaDocumentation doc=new XmlSchemaDocumentation();
				doc.Markup=TextToNodeArray("Documentation");
				annot.Items.Add(doc);
				newNode.Tag=doc;
				newNode.ImageIndex=(int)TreeViewImages.Annotation;
				newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
				CompileSchema();
				success=true;
			}
			if (!success)
			{
				// otherwise create the annotation type first
				mnuAddAnnotation_Click(sender, e);
				annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
				// if successful in adding the annotation type, add the documentation type now
				if (annot != null)
				{
					mnuAddDocumentation_Click(sender, e);
				}
			}
		}

		private void mnuAddAppInfo_Click(object sender, System.EventArgs e)
		{
			bool success=false;
			XmlSchemaAnnotation annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
			// if the parent node is an annotation type...
			if (annot != null)
			{
				// ...then add the AppInfo type
				TreeNode newNode=CreateNode("--app info--");
				XmlSchemaAppInfo doc=new XmlSchemaAppInfo();
				doc.Markup=TextToNodeArray("Application Information");
				annot.Items.Add(doc);
				newNode.Tag=doc;
				newNode.ImageIndex=(int)TreeViewImages.Annotation;
				newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
				CompileSchema();
				success=true;
			}
			if (!success)
			{
				// otherwise create the annotation type first
				mnuAddAnnotation_Click(sender, e);
				annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
				// if successful in creating the annotation type, add the AppInfo type now
				if (annot != null)
				{
					mnuAddAppInfo_Click(sender, e);
				}
			}
		}

		#endregion

		#region Add Attribute
		// Can only be added to schema root as a global or complex type.
		// For complex types, the attribute can reference a global type.
		// An optional type can be specified referring to a simple type.
		// If the type isn't used, the attribute must define a simple type.
		private void mnuAddAttribute_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("Attribute");
			XmlSchemaAttribute attrib=new XmlSchemaAttribute();
			attrib.Name="Attribute";
			attrib.SchemaTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  An global attribute cannot reference a global type
				AddToCollection(schema.Items, attrib, newNode, TreeViewImages.Attribute);
				cbGlobalTypes.Items.Add(new GlobalElementType(attrib.Name, attrib));
				cbGlobalTypes.Enabled=false;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// an attribute can only be added to a complex type
				XmlSchemaComplexType ct=newNode.Parent.Tag as XmlSchemaComplexType;
				if (ct != null)
				{
					// and can reference a global attribute, so enable the global combobox
					AddToCollection(ct.Attributes, attrib, newNode, TreeViewImages.Attribute);
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
				else
				{
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot create an attribute for this item.");
				}
			}
		}
		#endregion

		#region Add Element
		// An element can be added to the schema or to a complex type.
		// If adding to an element, convert the element to a complex type.
		// An element can be added to a global complex type or to a local complex type.
		private void mnuAddElement_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("Element");
			XmlSchemaElement element=new XmlSchemaElement();
			element.Name="Element";
			element.SchemaTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  A global element can reference another global type
				AddToCollection(schema.Items, element, newNode, TreeViewImages.Element);
				cbGlobalTypes.Items.Add(new GlobalElementType(element.Name, element));
				cbGlobalTypes.Enabled=true;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// otherwise, an element must be part of a complex type
				bool ret=AddToComplexType(newNode.Parent.Tag, element, newNode, TreeViewImages.Element);
				if (!ret)
				{
					// not successful
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add an element to this item.");
				}
				else
				{
					// successful
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
			}
		}
		#endregion

		#region Add Simple Type
		// A simple type can be added as a global type or as a local member of a complex type.
		// A simple type cannot contain elements or attributes.
		// Simple types are derived from basic types or other simple types.
		// The complex type can either be a global definition or a local complex type.
		// When adding to a complex type, the simple type must be wrapped in an element.
		private void mnuAddSimpleType_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("SimpleType");

			XmlSchemaSimpleType simpleType=new XmlSchemaSimpleType();
			simpleType.Name="SimpleType";
			XmlSchemaSimpleTypeRestriction restriction=new XmlSchemaSimpleTypeRestriction();
			restriction.BaseTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");
			simpleType.Content=restriction;

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  A global simple type cannot reference another global
				AddToCollection(schema.Items, simpleType, newNode, TreeViewImages.SimpleType);
				cbGlobalTypes.Items.Add(new GlobalElementType(simpleType.Name, simpleType));
				cbGlobalTypes.Enabled=false;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// if not a root node, then it must be created as an element of simple type...
				XmlSchemaElement el=new XmlSchemaElement();
				el.Name="SimpleType";
				el.SchemaType=simpleType;
				simpleType.Name=null;
				// ...as a subnode to a complex type
				bool ret=AddToComplexType(newNode.Parent.Tag, el, newNode, TreeViewImages.SimpleType);
				if (!ret)
				{
					// failure
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add a simple type to this item.");
				}
				else
				{
					// success.  Can reference a global simple type
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
			}
		}
		#endregion

		#region Add Complex Type
		// A complex type can be added as a global type to the schema or as a complex element.
		// If adding to an element, change the element to a complex type.
		// When adding to a complex type, the complex type must be wrapped in an element.
		private void mnuAddComplexType_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("ComplexType");

			XmlSchemaComplexType complexType=new XmlSchemaComplexType();
			XmlSchemaSequence sequence=new XmlSchemaSequence();
			complexType.Particle=sequence;
			complexType.Name="ComplexType";

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root.  A complex type has no type reference information.
				AddToCollection(schema.Items, complexType, newNode, TreeViewImages.ComplexType);
				cbGlobalTypes.Items.Add(new GlobalElementType(complexType.Name, complexType));
				cbSimpleTypes.SelectedItem=-1;
				cbGlobalTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=false;
				cbGlobalTypes.Enabled=false;
			}
			else
			{
				// if not at root, create an element of complex type...
				XmlSchemaElement el=new XmlSchemaElement();
				el.Name="ComplexType";
				el.SchemaType=complexType;
				complexType.Name=null;
				// ...that is added as a subnode to a complex type.
				bool ret=AddToComplexType(newNode.Parent.Tag, el, newNode, TreeViewImages.ComplexType);
				if (!ret)
				{
					// failure
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add a complex type to this item.");
				}
				else
				{
					// success.  No type is referenced.
					cbSimpleTypes.SelectedItem=-1;
					cbGlobalTypes.SelectedItem=-1;
					cbSimpleTypes.Enabled=false;
					cbGlobalTypes.Enabled=false;
				}
			}
		}
		#endregion

		#region New
		private void mnuNew_Click(object sender, System.EventArgs e)
		{
			CreateRootNode();		// create a new treeview root node
			schema=new XmlSchema();	// create a new schema
			CompileSchema();		// compile and show it
			fileName=null;			// no filename
		}
		#endregion

		#region Open
		// open an existing XSD file
		private void mnuOpen_Click(object sender, System.EventArgs e)
		{
			openSchemaDialog.DefaultExt="xsd";
			openSchemaDialog.CheckFileExists=true;
			openSchemaDialog.Filter="XSD Files (*.xsd)|*.xsd|All Files (*.*)|*.*";
			DialogResult res=openSchemaDialog.ShowDialog();
			if (res==DialogResult.OK)
			{
				try
				{
					StreamReader tr=new StreamReader(openSchemaDialog.FileName);
					schema=XmlSchema.Read(tr, new ValidationEventHandler(SchemaValidationHandler));
					tr.Close();
					CompileSchema();
					CreateRootNode();
					DecodeSchema(schema, tvSchema.Nodes[0]);
					tvSchema.ExpandAll();
					fileName=openSchemaDialog.FileName;
				}
				catch(Exception err)
				{
					edSchemaErrors.Text=err.ToString();
				}
			}
		}
		#endregion

		#region Save, Save As, Exit, About
		// save the current XSD
		private void mnuSave_Click(object sender, System.EventArgs e)
		{
			if (fileName==null)
			{
				mnuSaveAs_Click(sender, e);
			}
			else
			{
				CompileSchema();
				StreamWriter sw=new StreamWriter(fileName, false, System.Text.Encoding.UTF8);
				sw.Write(edSchema.Text);
				sw.Flush();
				sw.Close();
			}
		}

		// save the current XSD as...
		private void mnuSaveAs_Click(object sender, System.EventArgs e)
		{
			DialogResult res=saveAsSchemaDialog.ShowDialog();
			if (res==DialogResult.OK)
			{
				fileName=saveAsSchemaDialog.FileName;
				CompileSchema();
				StreamWriter sw=new StreamWriter(fileName, false, System.Text.Encoding.UTF8);
				sw.Write(edSchema.Text);
				sw.Flush();
				sw.Close();

			}
		}

		private void mnuExit_Click(object sender, System.EventArgs e)
		{
			Close();		// signal form to close
		}

		// info
		private void mnuAbout_Click(object sender, System.EventArgs e)
		{
			MessageBox.Show("XML Schema Editor\r\n\r\nversion 1.0\r\n\r\n(c)2003 Marc Clifton\r\n\r\nThis program may be freely distributed.");
		}
		#endregion

		#region Compile
		private void mnuCompile_Click(object sender, System.EventArgs e)
		{
			// 1. read the XSD from the edit box into a schema
			// 2. compile it
			// 3. create a new tree view
			// 4. decode the schema into the tree view
			// 5. show the tree
			try
			{
				StringReader sr=new StringReader(edSchema.Text);
				schema=XmlSchema.Read(sr, new ValidationEventHandler(SchemaValidationHandler));
				CompileSchema();
				CreateRootNode();
				DecodeSchema(schema, tvSchema.Nodes[0]);
				tvSchema.ExpandAll();
			}
			catch(Exception err)
			{
				edSchemaErrors.Text=err.ToString();
			}
		}
		#endregion

		#region Remove Node
		// The parent type determines from what list the selected item must be removed.
		// Use the image index in the tree view to figure out the parent type.
		private void mnuRemoveNode_Click(object sender, System.EventArgs e)
		{
			TreeNode tnParent=tvSchema.SelectedNode.Parent;
			XmlSchemaObject obj=tvSchema.SelectedNode.Tag as XmlSchemaObject;
			bool success=false;
			// if the node to remove has a parent and is of an XmlSchemaObject type...
			if ( (tnParent != null) && (obj != null) )
			{
				// look at the tree node image index to figure out what the parent is!
				switch ((TreeViewImages)tnParent.ImageIndex)
				{
					// if the parent is the schema root:
					case TreeViewImages.Schema:
					{
						// remove the object from the schema and from the global list
						schema.Items.Remove(obj);
						int idx=cbGlobalTypes.FindStringExact(tvSchema.SelectedNode.Text);
						if (idx != -1)
						{
							cbGlobalTypes.Items.RemoveAt(idx);
						}
						success=true;
						break;
					}

					// if the parent is an annotation type
					case TreeViewImages.Annotation:
					{
						XmlSchemaAnnotation annot=tnParent.Tag as XmlSchemaAnnotation;
						if (annot != null)
						{
							annot.Items.Remove(obj);
							success=true;
						}
						break;
					}

					// if the parent is a simple type
					case TreeViewImages.SimpleType:
					{
						// a simple type can have an annotation or a facet type as children
						XmlSchemaSimpleType st=tnParent.Tag as XmlSchemaSimpleType;
						if (obj is XmlSchemaAnnotation)
						{
							// remove from annotation list if it's an annotation type
							st.Annotation.Items.Remove(obj);
							success=true;
						}
						else if (obj is XmlSchemaFacet)
						{
							XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
							if (rest != null)
							{
								// remove from facet list if it's a facet type
								rest.Facets.Remove(obj);
								success=true;
							}
						}
						break;
					}

					// if the parent is a complex type...
					case TreeViewImages.ComplexType:
					{
						XmlSchemaComplexType ct=tnParent.Tag as XmlSchemaComplexType;
						if (ct != null)
						{
							// then we are removing an attribute
							if (obj is XmlSchemaAttribute)
							{
								ct.Attributes.Remove(obj);
								success=true;
							}
							// or an annotation
							else if (obj is XmlSchemaAnnotation)
							{
								ct.Annotation.Items.Remove(obj);
								success=true;
							}
							// or an element type
							else
							{
								XmlSchemaSequence seq=ct.Particle as XmlSchemaSequence;
								if (seq != null)
								{
									seq.Items.Remove(obj);
									success=true;
								}
							}
						}
						break;
					}
				}
			}
			// if successful, remove the node from the tree view
			if (success)
			{
				tnParent.Nodes.Remove(tvSchema.SelectedNode);
				CompileSchema();
			}
			else
			{
				MessageBox.Show("Unable to remove this node");
			}
		}
		#endregion

		#endregion

		#region Schema Validation Handler
		// report any errors to the schema error edit box
		private void SchemaValidationHandler(object sender, ValidationEventArgs args) 
		{
			Console.WriteLine(args.Message);
			edSchemaErrors.Text+=args.Message+"\r\n";
		}
		#endregion

		#region Events

		#region TreeView PreEventLabelChanged and EventLabelChanged
		// exclude certain tree nodes from being editable
		private void PreEventLabelChanged(object sender, NodeLabelEditEventArgs e)
		{
			prevLabel=tvSchema.SelectedNode.Text;
			if ( (e.Node.Tag is XmlSchemaFacet) ||
				(e.Node.Tag is XmlSchemaAnnotation) || 
				(e.Node.Tag is XmlSchemaDocumentation) ||
				(e.Node.Tag is XmlSchemaAppInfo) )
			{
				e.Node.EndEdit(false);
			}
		}

		private void EventLabelChanged(object sender, NodeLabelEditEventArgs e)
		{
			// if a node is selected...
			if (e.Node != null)
			{
				// and a label has been changed... (e.Label==null if ESC key pressed)
				if (e.Label != null)
				{
					// then change the name of the type in the schema
					UpdateTypeAndName(null, e.Label, null);

					// if this is a root node...
					if (e.Node.Parent == tvSchema.Nodes[0])
					{
						// ...then also change the name in the global list
						// (this is not case sensitive!)
						int idx=cbGlobalTypes.FindStringExact(prevLabel);
						if (idx != -1)
						{
							cbGlobalTypes.Items[idx]=new GlobalElementType(e.Label, ((GlobalElementType)cbGlobalTypes.Items[idx]).type);
						}
					}
				}
			}
		}
		#endregion

		#region EventTreeViewKeyPress
		// shortcuts:
		// F2 - edit tree node label
		// Ctrl+A - bring up popup menu to Add a subnode
		// Ctrl+T - go to Top of tree
		// Ctrl+P - go to Parent of currently selected node
		private void EventTreeViewKeyUp(object sender, KeyEventArgs e)
		{
			e.Handled=false;
			// F2
			if (e.KeyCode==Keys.F2)
			{
				if (tvSchema.SelectedNode != tvSchema.Nodes[0])
				{
					tvSchema.SelectedNode.BeginEdit();
					e.Handled=true;
				}
			}
			// Ctrl+A
			else if ( (e.KeyCode==Keys.A) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				tvcmSchema.Show(this, tvSchema.Location+new Size(50, 50));
			}
			// Ctrl+T
			else if ( (e.KeyCode==Keys.T) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				tvSchema.SelectedNode=tvSchema.Nodes[0];
			}
			// Ctrl+P
			else if ( (e.KeyCode==Keys.P) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				TreeNode node=tvSchema.SelectedNode.Parent;
				if (node != null)
				{
					tvSchema.SelectedNode=node;
				}
			}
		}
		#endregion

		#region Schema Text Box Lost Focus
		private void EventSchemaTextBoxLostFocus(object sender, EventArgs e)
		{
			mnuCompile_Click(sender, e);
		}
		#endregion

		#region TreeView MouseDown
		// On a mouse down, we want to select the node on which the mouse clicked.
		// This way we know what node the user right-clicked on when adding sub-nodes
		private void EventMouseDown(object sender, MouseEventArgs e)
		{
			TreeNode tn=tvSchema.GetNodeAt(e.X, e.Y);
			if (tn != null)
			{
				tvSchema.SelectedNode=tn;
			}
		}
		#endregion

		#region TreeView AfterSelect
		// After selecting a node, we want to:
		// 1. highlight the line in the schema that corresponds to the tree node
		// 2. update the simple and global type combo boxes to show what the type is for the selected node.
		private void tvSchema_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			XmlSchemaObject obj=e.Node.Tag as XmlSchemaObject;
			// if this is a schema object...
			if (obj != null)
			{
				// find the corresponding line in the XSD source and highlight it
				if ( (obj.LineNumber != 0) && (obj.LineNumber < edSchema.Lines.Length) )
				{
					int length=0;
					for (int i=0; i<obj.LineNumber-1; i++)
					{
						// get the length of the line including CRLF
						length+=edSchema.Lines[i].Length+2;
					}
					// highlight the line
					edSchema.Select(length, edSchema.Lines[obj.LineNumber-1].Length);
				}

				// Update simple and global type combo boxes.
				// Get the name of the element type so that we can find it in the simple or global type list
				XmlQualifiedName name=null;		// assume failure
				if (obj is XmlSchemaAttribute)
				{
					// this is easy.
					name=((XmlSchemaAttribute)obj).SchemaTypeName;
				}
				else if (obj is XmlSchemaSimpleType)
				{
					// if it's a simple type, get the restriction type, if it exists
					XmlSchemaSimpleTypeRestriction restriction=((XmlSchemaSimpleType)obj).Content as XmlSchemaSimpleTypeRestriction;
					if (restriction != null)
					{
						name=restriction.BaseTypeName;
					}
				}
				else if (obj is XmlSchemaElement)
				{
					// if it's an element, determine if it's a simple type subnode of a complex type...
					// and then get the restriction type, if it exists
					XmlSchemaElement el=obj as XmlSchemaElement;
					if (el.SchemaType is XmlSchemaSimpleType)
					{
						XmlSchemaSimpleType st=el.SchemaType as XmlSchemaSimpleType;
						XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
						if (rest != null)
						{
							name=rest.BaseTypeName;
						}
					}
					else
					{
						// otherwise get the element name
						name=el.SchemaTypeName;

						// if the name is null, then there must be a reference instead
						if (name.Name=="")
						{
							name=el.RefName;
						}
					}
				}

				// select the name from either the simple type list or the global element type list
				if (name != null)
				{
					// see if the name exists in the simple type list
					int idx=cbSimpleTypes.FindStringExact(name.Name);
					cbSimpleTypes.SelectedIndex=idx;
					cbSimpleTypes.Enabled=true;

					// see if the name exists in the complex type list
					idx=cbGlobalTypes.FindStringExact(name.Name);
					cbGlobalTypes.SelectedIndex=idx;
					cbGlobalTypes.Enabled=true;
				}
				else
				{
					// if there is no name, then disable the comboboxes
					cbSimpleTypes.SelectedIndex=-1;
					cbGlobalTypes.SelectedIndex=-1;
					cbSimpleTypes.Enabled=false;
					cbGlobalTypes.Enabled=false;
				}
			}
			else
			{
				// if this isn't a schema object, then disable the comboboxes
				cbSimpleTypes.SelectedIndex=-1;
				cbGlobalTypes.SelectedIndex=-1;
				cbSimpleTypes.Enabled=false;
				cbGlobalTypes.Enabled=false;
			}
		}
		#endregion

		#region cbSimpleTypes Index Changed
		// the user has selected a simple type.  Select it and clear the global type combo box.
		private void cbSimpleTypes_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (cbSimpleTypes.SelectedIndex != -1)
			{
				UpdateTypeAndName(cbSimpleTypes.SelectedItem.ToString(), null, "http://www.w3.org/2001/XMLSchema");
				cbGlobalTypes.SelectedIndex=-1;
			}
		}
		#endregion

		#region cbGlobalTypes Index Changed
		// the user has selected a global type.  Select it and clear the simple type combo box.
		private void cbGlobalTypes_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (cbGlobalTypes.SelectedIndex != -1)
			{
				UpdateTypeAndName(cbGlobalTypes.SelectedItem.ToString(), null, null);
				cbSimpleTypes.SelectedIndex=-1;
			}
		}
		#endregion


		#endregion

		#region Misc. Helpers

		#region CreateRootNode
		// This helper function destroys the existing tree and creates a new tree.
		// It also clears the global type list, since there are no global types defined
		//	with a blank tree.
		private void CreateRootNode()
		{
			tvSchema.Nodes.Clear();
			TreeNode rootNode=new TreeNode("Schema:");
			tvSchema.Nodes.Add(rootNode);
			rootNode.ImageIndex=(int)TreeViewImages.Schema;
			rootNode.SelectedImageIndex=(int)TreeViewImages.Schema;
			cbGlobalTypes.Items.Clear();
		}
		#endregion

		#region CompileSchema
		// Compile the schema as it exists in the XmlSchema structure, displaying any
		// errors in the schema error edit box and displaying the schema itself in
		// the schema edit box.
		private void CompileSchema()
		{
			edSchemaErrors.Text="";
			schema.Compile(new ValidationEventHandler(SchemaValidationHandler));
			StringWriter sw=new StringWriter();
			schema.Write(sw);
			edSchema.Text=sw.ToString();
		}
		#endregion

		#region CreateNode
		// This helper function creates a subnode off of the selected node and requests
		// that the node label be immediately editable.
		private TreeNode CreateNode(string name)
		{
			TreeNode tn=tvSchema.SelectedNode;
			TreeNode newNode=new TreeNode(name);
			tn.Nodes.Add(newNode);
			tn.Expand();
			tvSchema.SelectedNode=newNode;
			newNode.BeginEdit();
			return newNode;
		}
		#endregion

		#region AddToCollection
		// Add a schema type to the specified schema object collection.
		// The tree node references the schema type being added.
		// The image indices are set.
		// The schema is recompiled, which shows any errors and updates the schema display.
		void AddToCollection(XmlSchemaObjectCollection coll, XmlSchemaObject obj, TreeNode node, TreeViewImages imgIdx)
		{
			coll.Add(obj);
			node.Tag=obj;
			node.ImageIndex=(int)imgIdx;
			node.SelectedImageIndex=(int)imgIdx;
			CompileSchema();
		}
		#endregion

		#region ChangeElementToComplexType
		// When adding a subnode to an element or a simple type, the node must be changed to a complex type.
		private XmlSchemaComplexType ChangeElementToComplexType(XmlSchemaElement el, TreeNode tn)
		{
			// if the element is currently a reference, we need to remove the reference
			// and set the name to something, which in this case is the old ref name.
			if (el.RefName != null)
			{
				el.Name=el.RefName.Name;
				el.RefName=null;
			}
			// creat the complex type.
			XmlSchemaComplexType ct=new XmlSchemaComplexType();
			el.SchemaType=ct;
			// a complex type cannot have a type name
			el.SchemaTypeName=null;
			// create the sequence
			XmlSchemaSequence sequence=new XmlSchemaSequence();
			ct.Particle=sequence;

			// update the image indices
			tn.ImageIndex=(int)TreeViewImages.ComplexType;
			tn.SelectedImageIndex=(int)TreeViewImages.ComplexType;

			return ct;
		}
		#endregion

		#region AddToComplexType
		// add a type to a complex type
		private bool AddToComplexType(object obj, XmlSchemaObject item, TreeNode newNode, TreeViewImages imgIdx)
		{
			bool success=true;
			XmlSchemaElement el=obj as XmlSchemaElement;
			XmlSchemaComplexType complexType=obj as XmlSchemaComplexType;

			// is it an element...
			if (el != null)
			{
				// of complex type (so we know it's a local complex type, not a global one!)
				XmlSchemaComplexType ct=el.SchemaType as XmlSchemaComplexType;
				if (ct != null)
				{
					// does it have a sequence?
					XmlSchemaSequence seq=ct.Particle as XmlSchemaSequence;
					if (seq != null)
					{
						// yes--add it to the sequence collection
						AddToCollection(seq.Items, item, newNode, imgIdx);
					}
					else
					{
						// no--we can't add it.
						MessageBox.Show("Complex type is missing sequence!");
						success=false;
					}
				}
				else
				{
					// change the basic element to a complex type by adding a sequence and then
					// add the sub-element
					ct=ChangeElementToComplexType(el, newNode.Parent);
					AddToCollection(((XmlSchemaSequence)ct.Particle).Items, item, newNode, imgIdx);
				}
			}
			// or is it a global complex type...
			else	if (complexType != null)
			{
				XmlSchemaSequence seq=complexType.Particle as XmlSchemaSequence;
				// which should have a sequence!
				if (seq != null)
				{
					// yes--add it to the collection
					AddToCollection(seq.Items, item, newNode, imgIdx);
				}
				else
				{
					// no--we can't add it.
					MessageBox.Show("Complex type is missing sequence!");
					success=false;
				}
			}
			else
			{
				// failure--current node is not an element and not a complex type
				success=false;
			}
			return success;
		}
		#endregion

		#region UpdateTypeAndName
		// This is a dual purpose function that updates either the type or the name.
		// It can also update both at once, but isn't used in that way in this program.
		// Pass in a null for typeName if only changing the name.
		// Pass in a null for name if only changing the typeName.
		// Pass in a null for the nameSpace if the typeName is a global type.
		private void UpdateTypeAndName(string typeName, string name, string nameSpace)
		{
			// Is the type referenced by the tree node an XmlSchemaObject?
			XmlSchemaObject obj=tvSchema.SelectedNode.Tag as XmlSchemaObject;
			if (obj != null)
			{
				// is it an attribute?
				if (obj is XmlSchemaAttribute)
				{
					XmlSchemaAttribute attrib=obj as XmlSchemaAttribute;
					// if we're changing the name:
					if (name != null)
					{
						attrib.Name=name;
						CompileSchema();
					}
					// if we're changing the type:
					if (typeName != null)
					{
						// if the name refers to a global attribute, then use ref instead of type
						int idx=cbGlobalTypes.FindStringExact(typeName);
						GlobalElementType glet=null;
						if (idx != -1)
						{
							glet=cbGlobalTypes.Items[idx] as GlobalElementType;
						}
						// if a global exists of this type...
						if ( (glet != null) && (glet.type is XmlSchemaAttribute) )
						{
							// then get rid of the type name and use a ref instead
							attrib.SchemaTypeName=null;
							attrib.RefName=new XmlQualifiedName(typeName, nameSpace);
							// can't have a name
							attrib.Name=null;
						}
						else
						{
							// otherwise, use a type name and get rid of the ref
							attrib.SchemaTypeName=new XmlQualifiedName(typeName, nameSpace);
							attrib.RefName=null;
							if (attrib.Name==null)
							{
								// if changing from ref to type, we need some sort of default name
								attrib.Name=tvSchema.SelectedNode.Text;
							}
						}
						CompileSchema();
						// update the tree node name
						tvSchema.SelectedNode.Text=attrib.QualifiedName.Name;
					}
				}
				// is it an element?
				else if (obj is XmlSchemaElement)
				{
					XmlSchemaElement el=obj as XmlSchemaElement;
					// if we're changing the name:
					if (name != null)
					{
						el.Name=name;
						CompileSchema();
					}

					// if we're changing the type:
					if (typeName != null)
					{
						if (el.SchemaType is XmlSchemaSimpleType)
						{
							XmlSchemaSimpleType st=el.SchemaType as XmlSchemaSimpleType;
							XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
							if (rest != null)
							{
								rest.BaseTypeName=new XmlQualifiedName(typeName, nameSpace);
								CompileSchema();
							}
						}
						else
						{
							// if the name refers to a global element, then use ref instead of type
							// Same deal as for changing the element type name.
							// Since the SchemaTypeName and RefName are not part of any base class shared
							// between the SchemaXmlAttribute and SchemaXmlElement, we need separate code.
							int idx=cbGlobalTypes.FindStringExact(typeName);
							GlobalElementType glet=null;
							if (idx != -1)
							{
								glet=cbGlobalTypes.Items[idx] as GlobalElementType;
							}
							if ( (glet != null) && (glet.type is XmlSchemaElement) )
							{
								el.SchemaTypeName=null;
								el.RefName=new XmlQualifiedName(typeName, nameSpace);
								el.Name=null;
							}
							else
							{
								el.SchemaTypeName=new XmlQualifiedName(typeName, nameSpace);
								el.RefName=null;
								if (el.Name==null)
								{
									el.Name=tvSchema.SelectedNode.Text;
								}
							}
							CompileSchema();
							tvSchema.SelectedNode.Text=el.QualifiedName.Name;
						}
					}
				}
				// is it a simple type?
				else if (obj is XmlSchemaSimpleType)
				{
					XmlSchemaSimpleType st=obj as XmlSchemaSimpleType;
					// if we're changing the name:
					if (name != null)
					{
						st.Name=name;
						CompileSchema();
					}

					// if we're changing the type name:
					if (typeName != null)
					{
						// this must be done in the Restriction object
						XmlSchemaSimpleTypeRestriction restriction=st.Content as XmlSchemaSimpleTypeRestriction;
						if (restriction != null)
						{
							restriction.BaseTypeName=new XmlQualifiedName(typeName, nameSpace);
							CompileSchema();
							cbGlobalTypes.SelectedIndex=-1;
						}
					}
				}
				// is it a complex type?
				else if (obj is XmlSchemaComplexType)
				{
					// if we're changing the name:
					if (name != null)
					{
						((XmlSchemaComplexType)obj).Name=name;
						CompileSchema();
					}
					// there is no such thing as changing the type of a complex type
				}
			}
		}
		#endregion

		#region Add Facet
		// Add a facet to a simple type.
		bool AddFacet(XmlSchemaFacet facet, string val, TreeViewImages imgIdx)
		{
			// get the simple type.
			XmlSchemaSimpleType st=tvSchema.SelectedNode.Tag as XmlSchemaSimpleType;

			// assume failure
			XmlSchemaSimpleTypeRestriction rs=null;
			bool success=false;

			// if the simple type exists, get the restriction type
			if (st != null)
			{
				rs=st.Content as XmlSchemaSimpleTypeRestriction;
			}

			// if the restriction type exists...
			if (rs != null)
			{
				// create the node and add it to the facet collection
				TreeNode newNode=CreateNode(facet.ToString());
				facet.Value=val;
				rs.Facets.Add(facet);
				CompileSchema();
				success=true;
			}
			return success;
		}
		#endregion

		#region TextToNodeArray
		// a helper to create some default documentation text.
		public static XmlNode[] TextToNodeArray(string text) 
		{
			XmlDocument doc = new XmlDocument();
			return new XmlNode[1] {doc.CreateTextNode(text)};
		}
		#endregion

		#endregion
				
		#region DecodeSchema

		// stub that wraps the actual decoding in a try block so we can display errors
		private void DecodeSchema(XmlSchema schema, TreeNode node)
		{
			try
			{
				DecodeSchema2(schema, node);
			}
			catch(Exception err)
			{
				edSchemaErrors.Text=err.ToString();
			}
		}

		// recursive decoder
		private TreeNode DecodeSchema2(XmlSchemaObject obj, TreeNode node)
		{
			TreeNode newNode=node;

			// convert the object to all types and then check what type actually exists
			XmlSchemaAnnotation annot=obj as XmlSchemaAnnotation;
			XmlSchemaAttribute attrib=obj as XmlSchemaAttribute;
			XmlSchemaFacet facet=obj as XmlSchemaFacet;
			XmlSchemaDocumentation doc=obj as XmlSchemaDocumentation;
			XmlSchemaAppInfo appInfo=obj as XmlSchemaAppInfo;
			XmlSchemaElement element=obj as XmlSchemaElement;
			XmlSchemaSimpleType simpleType=obj as XmlSchemaSimpleType;
			XmlSchemaComplexType complexType=obj as XmlSchemaComplexType;

			// If the current node is the root node of the tree, then we are
			// possibly adding a global attribute, element, simple type, or complex type.
			if (node==tvSchema.Nodes[0])
			{
				if (attrib != null)
				{
					if (attrib.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(attrib.Name, attrib));
					}
				}
				else	if (element != null)
				{
					if (element.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(element.Name, element));
					}
				}
				else if (simpleType != null)
				{
					if (simpleType.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(simpleType.Name, simpleType));
					}
				}
				else if (complexType != null)
				{
					if (complexType.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(complexType.Name, complexType));
					}
				}
			}

			// if annotation, add a tree node and recurse for documentation and app info
			if (annot != null)
			{
				newNode=new TreeNode("--annotation--");
				newNode.Tag=annot;
				newNode.ImageIndex=4;
				newNode.SelectedImageIndex=4;
				node.Nodes.Add(newNode);
				foreach (XmlSchemaObject schemaObject in annot.Items)
				{
					DecodeSchema2(schemaObject, newNode);
				}
			}
			else
				// if attribute, add a tree node
				if (attrib != null)
			{
				newNode=new TreeNode(attrib.QualifiedName.Name);
				newNode.Tag=attrib;
				newNode.ImageIndex=7;
				newNode.SelectedImageIndex=7;
				node.Nodes.Add(newNode);
			}
			else
				// if facet, add a tree node
				if (facet != null)
			{
				newNode=new TreeNode(facet.ToString());
				newNode.Tag=facet;
				newNode.ImageIndex=8;
				newNode.SelectedImageIndex=8;
				node.Nodes.Add(newNode);
			}
			else
				// if documentation, add a tree node
				if (doc != null)
			{
				newNode=new TreeNode("--documentation--");
				newNode.Tag=doc;
				newNode.ImageIndex=5;
				newNode.SelectedImageIndex=5;
				node.Nodes.Add(newNode);
			}
			else
				// if app info, add a tree node
				if (appInfo != null)
			{
				newNode=new TreeNode("--app info--");
				newNode.Tag=annot;
				newNode.ImageIndex=6;
				newNode.SelectedImageIndex=6;
				node.Nodes.Add(newNode);
			}
			else
				// if an element, determine whether the element is a simple type or a complex type
				if (element != null)
			{
				XmlSchemaSimpleType st=element.SchemaType as XmlSchemaSimpleType;
				XmlSchemaComplexType ct=element.SchemaType as XmlSchemaComplexType;

				if (st != null)
				{
					// this is a simple type element.  Recurse.
					TreeNode node2=DecodeSchema2(st, newNode);
					node2.Text=element.Name;
				}
				else if (ct != null)
				{
					// this is a complex type element.  Recurse.
					TreeNode node2=DecodeSchema2(ct, newNode);
					node2.Text=element.Name;
				}
				else
				{
					// This is a plain ol' fashioned element.
					newNode=new TreeNode(element.QualifiedName.Name);
					newNode.Tag=element;
					newNode.ImageIndex=1;
					newNode.SelectedImageIndex=1;
					node.Nodes.Add(newNode);
				}
			}
			else
				// if a simple type, then add a tree node and recurse facets
				if (simpleType != null)
			{
				newNode=new TreeNode(simpleType.QualifiedName.Name);
				newNode.Tag=simpleType;
				newNode.ImageIndex=2;
				newNode.SelectedImageIndex=2;
				node.Nodes.Add(newNode);
				XmlSchemaSimpleTypeRestriction rest=simpleType.Content as XmlSchemaSimpleTypeRestriction;
				if (rest != null)
				{
					foreach (XmlSchemaFacet schemaObject in rest.Facets)
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}
			else
				// if a complex type, add a tree node and recurse its sequence
				if (complexType != null)
			{
				newNode=new TreeNode(complexType.Name);
				newNode.Tag=complexType;
				newNode.ImageIndex=3;
				newNode.SelectedImageIndex=3;
				node.Nodes.Add(newNode);

				XmlSchemaSequence seq=complexType.Particle as XmlSchemaSequence;
				if (seq != null)
				{
					foreach (XmlSchemaObject schemaObject in seq.Items)
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}

			// now recurse any object collection of the type.
			foreach (PropertyInfo property in obj.GetType().GetProperties())
			{
				if (property.PropertyType.FullName == "System.Xml.Schema.XmlSchemaObjectCollection")
				{
					XmlSchemaObjectCollection childObjectCollection=(XmlSchemaObjectCollection) property.GetValue(obj, null);
					foreach (XmlSchemaObject schemaObject in childObjectCollection) 
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}
			return newNode;
		}
		#endregion
	}
}

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Comments and Discussions