XML 元编程语言 Metah.X

码农软件 · 软件分类 · XML相关工具 · 2019-09-17 19:44:20

软件介绍

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的用处。

本文地址:https://codercto.com/soft/d/14819.html

C陷阱与缺陷

C陷阱与缺陷

凯尼格 / 高巍 / 人民邮电出版社 / 2008-2-1 / 30.00元

作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍。.. 全书分为8章,分别从词法分析、语法语义、连接、库函数、预处理器、可移植性缺陷等几个方面分析了C编程中可能遇到的问题。最后,作者用一章的篇幅给出了若干具有实用价值的建议。.. 本书......一起来看看 《C陷阱与缺陷》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具