private static void GetAttributes(Тэг t, TypeInterface ti) { foreach (Атрибут a in t.Атрибуты) { string body = " Result := AttributeNodes['" + a.имяXML + "'].NodeValue;"; if (a.TypeCode == XmlTypeCode.String) { body = " Result := AttributeNodes['" + a.имяXML + "'].Text;"; } ti.PropertyAccessors.Add(new Метод("function", "Get_" + a.Id + ": " + a.PascalType + ";", body)); } }
private static DelphiGenerator GetDelphiGenerator(string имяXMLФайла) { DelphiGenerator dg = null; XmlSchema Схема = Program.ПолучитьСхемуXMLФайла(имяXMLФайла); foreach (DictionaryEntry de in Схема.Elements) { Тэг корень = Program.Build((XmlSchemaElement)de.Value); dg = new DelphiGenerator(корень); break; // обрабатываем только первый элемент } return(dg); }
public DelphiGenerator(Тэг корень) { this.корень = корень; Подготовка(корень); GlobalFunctions.Add(new Function("function Get" + корень.Id + "(Doc: IXMLDocument): IXML" + корень.Id + ";", " Result := Doc.GetDocBinding('" + корень.имяXML + "', TXML" + корень.Id + ", TargetNamespace) as IXML" + корень.Id + ";")); GlobalFunctions.Add( new Function("function Load" + корень.Id + "(const FileName: WideString): IXML" + корень.Id + ";", " Result := LoadXMLDocument(FileName).GetDocBinding('" + корень.имяXML + "', TXML" + корень.Id + ", TargetNamespace) as IXML" + корень.Id + ";")); GlobalFunctions.Add(new Function("function New" + корень.Id + ": IXML" + корень.Id + ";", " Result := NewXMLDocument.GetDocBinding('" + корень.имяXML + "', TXML" + корень.Id + ", TargetNamespace) as IXML" + корень.Id + ";")); }
public static void Main(string[] args) { if (args.Length >= 2) { string ИмяВходногоXMLФайла = args[0]; string ИмяВыходногоPascalФайла = args[1]; XmlSchema Схема = ПолучитьСхемуXMLФайла(ИмяВходногоXMLФайла); if (args.Length == 3) { string ИмяФайлаДляСохраненияXSDСхемы = args[2]; ЗаписатьXSDСхемуВФайл(Схема, ИмяФайлаДляСохраненияXSDСхемы); } foreach (DictionaryEntry de in Схема.Elements) { Тэг корень = Build((XmlSchemaElement)de.Value); (new DelphiGenerator(корень)).Сгенерировать(ИмяВыходногоPascalФайла); break; // обрабатываем только первый элемент } } else { Console.WriteLine("DelphiXML <ИмяВходногоXMLФайла> <ИмяВыходногоPascalФайла> [<ИмяФайлаДляСохраненияXSDСхемы>]"); } }
private void Подготовка(Тэг t) { if (t.типТэга == ТипТэга.ПростойТип) { return; } bool ОдиночныйВложенныйПовторяющийсяТэг = t.ВложенныеТэги.Count == 1 && t.ВложенныеТэги[0].Повторяется; TypeInterface ti = new TypeInterface(); ti.InterfaceName = "IXML" + t.Id; ti.TypeName = "TXML" + t.Id; ti.InterfaceType = "interface(IXMLNode)"; ti.TypeType = "class(TXMLNode, " + ti.InterfaceName + ")"; TypeList.Add(ti); GetAttributes(t, ti); foreach (Тэг tt in t.ВложенныеТэги) { if (tt.типТэга == ТипТэга.Структура) { ti.AfterConstruction += " RegisterChildNode('" + tt.имяXML + "', TXML" + tt.Id + ");" + Utils.NewLine; } } ti.AfterConstruction = ti.AfterConstruction.TrimEnd(); if (ОдиночныйВложенныйПовторяющийсяТэг) { string idТэга = t.ВложенныеТэги[0].Id; ti.InterfaceType = "interface(IXMLNodeCollection)"; ti.TypeType = "class(TXMLNodeCollection, " + ti.InterfaceName + ")"; string тип = t.ВложенныеТэги[0].PascalType; string типItemInterface = "IXMLNode"; if (t.ВложенныеТэги[0].типТэга == ТипТэга.Структура) { типItemInterface = "IXML" + t.ВложенныеТэги[0].Id; тип = типItemInterface; ti.Methods.Add(new Метод("function", "Add: " + типItemInterface + ";", " Result := AddItem(-1);")); ti.Methods.Add( new Метод("function", "Insert(const Index: Integer): " + типItemInterface + ";", " Result := AddItem(Index);")); } else { ti.Methods.Add(new Метод("function", "Add(const " + idТэга + ": " + тип + "): " + типItemInterface + ";", " Result := AddItem(-1);" + Utils.NewLine + " Result.NodeValue := " + idТэга + ";")); ti.Methods.Add( new Метод("function", "Insert(const Index: Integer; const " + idТэга + ": " + тип + "): " + типItemInterface + ";", " Result := AddItem(Index);" + Utils.NewLine + " Result.NodeValue := " + idТэга + ";")); } ti.PropertyAccessors.Add(new Метод("function", "Get_" + idТэга + "(Index: Integer): " + тип + ";", " Result := List[Index].NodeValue;")); if (ti.AfterConstruction != "") { ti.AfterConstruction += Utils.NewLine; } ti.AfterConstruction += " ItemTag := '" + t.ВложенныеТэги[0].имяXML + "';" + Utils.NewLine + " ItemInterface := " + типItemInterface + ";"; } else { if (ti.AfterConstruction != "") { ti.AfterConstruction += Utils.NewLine; } foreach (Тэг tt in t.ВложенныеТэги) { if (tt.типТэга == ТипТэга.Структура && tt.Повторяется) { ti.Fields.Add("F" + tt.Id + ": IXML" + tt.Id + "List;"); ti.AfterConstruction += " F" + tt.Id + " := CreateCollection(TXML" + tt.Id + "List, IXML" + tt.Id + ", '" + tt.имяXML + "') as IXML" + tt.Id + "List;" + Utils.NewLine; } } ti.AfterConstruction = ti.AfterConstruction.TrimEnd(); foreach (Тэг tt in t.ВложенныеТэги) { string body = " Result := ChildNodes['" + tt.имяXML + "'].NodeValue;"; if (tt.TypeCode == XmlTypeCode.String) { body = " Result := ChildNodes['" + tt.имяXML + "'].Text;"; } if (tt.типТэга == ТипТэга.Структура) { if (tt.Повторяется) { body = " Result := F" + tt.Id + ";"; } else { body = " Result := ChildNodes['" + tt.имяXML + "'] as IXML" + tt.Id + ";"; } } ti.PropertyAccessors.Add(new Метод("function", "Get_" + tt.Id + ": " + tt.PascalType + ";", body)); } } foreach (Атрибут a in t.Атрибуты) { ti.PropertyAccessors.Add(new Метод("procedure", "Set_" + a.Id + "(Value: " + a.PascalType + ");", " SetAttribute('" + a.имяXML + "', Value);")); ti.Properties.Add("property " + a.Id + ": " + a.PascalType + " read Get_" + a.Id + " write Set_" + a.Id + ";"); } if (!ОдиночныйВложенныйПовторяющийсяТэг) { foreach (Тэг tt in t.ВложенныеТэги) { switch (tt.типТэга) { case ТипТэга.Структура: ti.Properties.Add("property " + tt.Id + ": " + tt.PascalType + " read Get_" + tt.Id + ";"); break; case ТипТэга.ПростойТип: ti.PropertyAccessors.Add(new Метод("procedure", "Set_" + tt.Id + "(Value: " + tt.PascalType + ");", " ChildNodes['" + tt.имяXML + "'].NodeValue := Value;")); ti.Properties.Add("property " + tt.Id + ": " + tt.PascalType + " read Get_" + tt.Id + " write Set_" + tt.Id + ";"); break; } } foreach (Тэг tt in t.ВложенныеТэги) { Подготовка(tt); } } if (t.Повторяется) { TypeInterface tiList = new TypeInterface(); tiList.InterfaceName = "IXML" + t.Id + "List"; tiList.TypeName = "TXML" + t.Id + "List"; tiList.InterfaceType = "interface(IXMLNodeCollection)"; tiList.TypeType = "class(TXMLNodeCollection, " + tiList.InterfaceName + ")"; tiList.Methods.Add(new Метод("function", "Add: " + ti.InterfaceName + ";", " Result := AddItem(-1) as " + ti.InterfaceName + ";")); tiList.Methods.Add(new Метод("function", "Insert(const Index: Integer): " + ti.InterfaceName + ";", " Result := AddItem(Index) as " + ti.InterfaceName + ";")); tiList.Methods.Add(new Метод("function", "Get_Item(Index: Integer): " + ti.InterfaceName + ";", " Result := List[Index] as " + ti.InterfaceName + ";")); tiList.Properties.Add("property Items[Index: Integer]: IXML" + t.Id + " read Get_Item; default;"); TypeList.Add(tiList); } if (ОдиночныйВложенныйПовторяющийсяТэг) { if (t.ВложенныеТэги[0].типТэга == ТипТэга.Структура) { ti.Properties.Add("property " + t.ВложенныеТэги[0].Id + "[Index: Integer]: IXML" + t.ВложенныеТэги[0].Id + " read Get_" + t.ВложенныеТэги[0].Id + "; default;"); } else { ti.Properties.Add("property " + t.ВложенныеТэги[0].Id + "[Index: Integer]: " + t.ВложенныеТэги[0].PascalType + " read Get_" + t.ВложенныеТэги[0].Id + "; default;"); } t.ВложенныеТэги[0].Повторяется = false; Подготовка(t.ВложенныеТэги[0]); } }
/// <summary> /// Создаём в памяти дерево по XSD схеме /// XSD-схема, на мой взгляд, не самый удобочитаемый и наглядный вариант представления структуры данных. /// Поэтому я строю своё собственное дерево, в котором структура видна более явно. /// Для ещё большей наглядности структура записывается в начало генерируемого Pascal файла. /// </summary> /// <param name="schemaObject"></param> /// <returns>Дерево тегов</returns> public static Тэг Build(XmlSchemaObject schemaObject) { if (schemaObject == null) { return(null); } Тэг тэг; Type type = schemaObject.GetType(); switch (type.Name) { case "XmlSchemaElement": XmlSchemaElement element = (XmlSchemaElement)schemaObject; тэг = Build(element.ElementSchemaType); if (тэг == null) { тэг = new Тэг(); тэг.типТэга = ТипТэга.ПростойТип; } тэг.имяXML = element.Name; тэг.TypeCode = element.ElementSchemaType.TypeCode; тэг.Повторяется = (element.MaxOccursString == "unbounded"); break; case "XmlSchemaComplexType": XmlSchemaComplexType complexType = (XmlSchemaComplexType)schemaObject; тэг = Build(complexType.Particle); if (тэг == null) { тэг = new Тэг(); } тэг.типТэга = ТипТэга.Структура; foreach (XmlSchemaAttribute schemaAttribute in complexType.Attributes) { Атрибут атрибут = new Атрибут(); атрибут.имяXML = schemaAttribute.Name; атрибут.TypeCode = schemaAttribute.AttributeSchemaType.TypeCode; тэг.Атрибуты.Add(атрибут); } break; case "XmlSchemaSequence": XmlSchemaSequence schemaSequence = (XmlSchemaSequence)schemaObject; тэг = new Тэг(); foreach (XmlSchemaObject item in schemaSequence.Items) { тэг.ВложенныеТэги.Add(Build(item)); } break; case "XmlSchemaSimpleType": XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)schemaObject; тэг = new Тэг(); // тэг.Повторяется = (simpleType.MaxOccursString == "unbounded"); break; default: string text = "case \"" + type.Name + "\":\n " + type.Name + " x = (" + type.Name + ") schemaObject;\n" + " break;"; Clipboard.SetText(text); throw new Exception(text); } if (тэг == null) { throw new Exception("Не сработал switch! " + schemaObject); } return(тэг); }