浏览 1287 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2014-04-17
XML Schema 1.0的语义,并且用C#实现了一个Schema-lized Document Object Model (SDOM),编译器编译MX代码后将生成使用SDOM的C#代码,这将XML Schema的语义映射到C#上,从而完全释放出XML Schema的力量。尽管现在只有C#版,实现Java版或其它语言版本是完全可能的。
Metah.X(简称MX)用自创的语法实现了
MX是个开源项目,欢迎参与,比如实现Java版或其它语言版本;MX没有定型,欢迎提出修改意见。请访问:http://metah.codeplex.com/。 XML Schema定义了XML数据(或叫XML实例)的形状及需要遵守的规则,比如下面的XSD代码: <?xml version="1.0" encoding="utf-8"?> <!--HelloWorld.xsd--> <schema targetNamespace="http://schemas.example.com/projecta" elementFormDefault="qualified" xmlns:tns="http://schemas.example.com/projecta" xmlns="http://www.w3.org/2001/XMLSchema"> <simpleType name="String20"> <restriction base="string"> <minLength value="1"></minLength> <maxLength value="20"></maxLength> </restriction> </simpleType> <simpleType name="PhoneCategory"> <restriction base="string"> <enumeration value="Unknown"></enumeration> <enumeration value="Work"></enumeration> <enumeration value="Home"></enumeration> </restriction> </simpleType> <complexType name="Phone"> <simpleContent> <extension base="tns:String20"> <attribute name="Category" use="optional" type="tns:PhoneCategory"></attribute> </extension> </simpleContent> </complexType> <complexType name="Customer"> <sequence> <element name="Phone" minOccurs="1" maxOccurs="unbounded" type="tns:Phone"></element> </sequence> <attribute name="Name" use="required" type="tns:String20"></attribute> <attribute name="Email" use="required"> <simpleType> <restriction base="tns:String20"> <pattern value="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"></pattern> </restriction> </simpleType> </attribute> <attribute name="RegistrationDate" use="optional" type="dateTime"></attribute> </complexType> <element name="Customer" type="tns:Customer"></element> </schema> 下面是合法的XML数据: <e0:Customer Name="Tank" Email="tank@example.com" RegistrationDate="2014-04-15T16:56:53.0568964Z" xmlns:e0="http://schemas.example.com/projecta"> <e0:Phone Category="Work">12345678-334</e0:Phone> <e0:Phone>87654321</e0:Phone> </e0:Customer> 因为XSD相当繁琐不便于书写,MX自创了用户友好的语法来表达XML Schema的语义,下面的MX代码和上面的XSD代码表达了相同的语义: //HelloWorld.mxcs xnamespace {"http://schemas.example.com/projecta"} [namespace: Example.ProjectA] { type String20 restrict String facets { lengthrange: 1..20; }; ; type PhoneCategory restrict String facets{ enums: Unknown = "Unknown", Work = "Work", Home = "Home" }; ; type Phone extend String20 attributes { attribute Category[?] as PhoneCategory; }; ; type Customer attributes { attribute Name as String20; attribute Email as type restrict String20 facets { patterns: @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"; }; ; ; attribute RegistrationDate[?] as DateTime; }; children { element Phone[+; membername: Phones] as Phone; }; ; element Customer as Customer; } MX编译器编译HelloWorld.mxcs后,将生成如下的C#代码: //HelloWorld.mxcs.cs //Generated by MX compiler namespace Example.ProjectA { public partial class PhoneCategory : ... { public static readonly string @Unknown = "Unknown"; public static readonly string @Work = "Work"; public static readonly string @Home = "Home"; ... } public partial class Phone : ... { public partial class AttributeSetClass : ... { public string Category_Value { get; set; } ... } public AttributeSetClass AttributeSet { get; set; } public AttributeSetClass EnsureAttributeSet(); public string Value { get; set; } ... } public partial class Customer : ... { public partial class AttributeSetClass : ... { public string Name_Value { get; set; } public string Email_Value { get; set; } public DateTime? RegistrationDate_Value { get; set; } ... } public AttributeSetClass AttributeSet { get; set; } public AttributeSetClass EnsureAttributeSet(); public partial class ComplexChildClass : ... { public partial class Phones_Class : ... { public partial class ItemClass : ... { public Phone Type { get; set; } ... } public ItemClass CreateAndAddItem(); ... } public Phones_Class Phones { get; set; } public Phones_Class Ensure_Phones(); ... } public ComplexChildClass ComplexChild { get; set; } public ComplexChildClass EnsureComplexChild(); ... } public partial class Customer_ElementClass : ... { public Customer Type { get; set; } public static bool TryLoadAndValidate(XmlReader reader, Metah.X.Context context, out Customer_ElementClass result); ... } } 使用编译器生成的代码,就可以创建、查询、修改、保存、装载及验证XML数据,下面的手写代码演示了如何使用编译器生成的代码: //Program.cs using System; using System.Xml;//for XmlReader & XmlWriter using X = Metah.X; namespace Example.ProjectA { class Program { static void Main(string[] args) { var customer = new Customer(); var cattset = customer.EnsureAttributeSet(); cattset.Name_Value = "Tank"; cattset.Email_Value = "tank@example.com"; cattset.RegistrationDate_Value = DateTime.Now; var phones = customer.EnsureComplexChild().Ensure_Phones(); var phone = phones.CreateAndAddItem(); phone.EnsureAttributeSet().Category_Value = PhoneCategory.Work; phone.Value = "12345678-334"; phones.CreateAndAddItem().Value = "87654321"; var customerElement = new Customer_ElementClass { Type = customer }; using (var writer = XmlWriter.Create(@"d:\customer.xml", new XmlWriterSettings { Indent = true })) customerElement.Save(writer); // var ctx = new X.Context(); using (var reader = XmlReader.Create(@"d:\customer.xml")) { Customer_ElementClass customerElement2; if (Customer_ElementClass.TryLoadAndValidate(reader, ctx, out customerElement2)) { var customer2 = customerElement2.Type; Console.WriteLine("Name={0}, Email={1}, RegistrationDate={2}", customer2.AttributeSet.Name_Value, customer2.AttributeSet.Email_Value, customer2.AttributeSet.RegistrationDate_Value); foreach (var phone2 in customer2.ComplexChild.Phones) { Console.WriteLine("\tCategory={0}, Value={1}", phone2.Type.AttributeSet.Category_Value, phone2.Type.Value); } customer2.AttributeSet.Name_Value += "-Knat"; customer2.AttributeSet.RegistrationDate = null; var phone3 = customer2.ComplexChild.Phones.CreateAndAddItem(); phone3.EnsureAttributeSet().Category_Value = PhoneCategory.Home; phone3.Value = "11223344"; using (var writer = XmlWriter.Create(@"d:\customer2.xml", new XmlWriterSettings { Indent = true })) customerElement2.Save(writer); } else { foreach (var diag in ctx.Diagnostics) Console.WriteLine(diag); } } } } } 下面是d:\customer.xml的内容: <?xml version="1.0" encoding="utf-8"?> <e0:Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="e0:Customer" Name="Tank" Email="tank@example.com" RegistrationDate="2014-04-17T08:45:21.4460232Z" xmlns:e0="http://schemas.example.com/projecta"> <e0:Phone xsi:type="e0:Phone" Category="Work">12345678-334</e0:Phone> <e0:Phone xsi:type="e0:Phone">87654321</e0:Phone> </e0:Customer> 下面是d:\customer2.xml的内容: <?xml version="1.0" encoding="utf-8"?> <e0:Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="e0:Customer" Name="Tank-Knat" Email="tank@example.com" xmlns:e0="http://schemas.example.com/projecta"> <e0:Phone xsi:type="e0:Phone" Category="Work">12345678-334</e0:Phone> <e0:Phone xsi:type="e0:Phone">87654321</e0:Phone> <e0:Phone xsi:type="e0:Phone" Category="Home">11223344</e0:Phone> </e0:Customer> 也就是说,MX的用处 = XML Schema的用处 + Document Object Model的用处。欲知详情,请访问:http://metah.codeplex.com/ 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |