Metah.X - XML 元编程语言
MIT
Windows
C#
软件简介
Metah.X(简称MX)用自创的语法实现了XML Schema
1.0的语义,并且用C#实现了一个Schema-lized Document
Object Model (SDOM),编译器编译MX代码后将生成使用SDOM的C#代码,这将XML Schema的语义映射到C#上,从而完全释放出XML
Schema的力量。尽管现在只有C#版,实现Java版或其它语言版本是完全可能的。
MX是个开源项目,欢迎参与,比如实现Java版或其它语言版本;MX没有定型,欢迎提出修改意见。
XML Schema定义了XML数据(或叫XML实例)的形状及需要遵守的规则,比如下面的XSD代码:
<E1 xmlns="http://ns1">
<E2 A1="123">abc</E2>
<E3 xmlns="">
<p:E4 xmlns:p="http://ns2" p:A1="true" A1="123" />
def
</E3>
</E1>
下面是合法的XML数据:
12345678-33487654321
因为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的内容:
12345678-33487654321
下面是d:\customer2.xml的内容:
12345678-3348765432111223344
也就是说,MX的用处 = XML Schema的用处 + Document Object Model的用处。