数据字典生成工具之旅(3):PowerDesign文件组成结构介绍及操作

       从这篇开始将正式讲解整个重要部分的实现细节,本篇讲解Pdm文件的解析。其实PDM文件就是XML文件,可以用Editplus或者VS打开查看。了解到这一点之后大家就能猜到,可以用解析XML的方式读取PDM文件了。

阅读目录

回到顶部

PDM文件结构及在本工具的存储方式

        下面看看用Editplus读取出来的XML,这里我只关注Table节点,这是一个表的最小节点了。  

          <o:Table Id="o97">
            <a:ObjectID>41144D16-B6B3-43CD-8B36-57CBAFB26654</a:ObjectID>
            <a:Name>预算资源面积月事实表</a:Name>
            <a:Code>y_FactYsRoomAreaMonth</a:Code>
            <a:CreationDate>1366118213</a:CreationDate>
            <a:Creator>huzhiwen</a:Creator>
            <a:ModificationDate>1396403208</a:ModificationDate>
            <a:Modifier>gongw</a:Modifier>
            <a:TotalSavingCurrency/>
            <c:Columns>
              <o:Column Id="o361">
                <a:ObjectID>F03D6EA9-183A-4B6A-BD52-7B711572AA45</a:ObjectID>
                <a:Name>ID</a:Name>
                <a:Code>ID</a:Code>
                <a:CreationDate>1366118213</a:CreationDate>
                <a:Creator>huzhiwen</a:Creator>
                <a:ModificationDate>1381212250</a:ModificationDate>
                <a:Modifier>huzw</a:Modifier>
                <a:DataType>bigint</a:DataType>
                <a:Identity>1</a:Identity>
                <a:Mandatory>1</a:Mandatory>
              </o:Column>
            </c:Columns>
            <c:Keys>
              <o:Key Id="o380">
                <a:ObjectID>F9089FCD-D9E9-4FB0-92F3-B7268D49526D</a:ObjectID>
                <a:Name>PK_Z_DIMROOMMONTH</a:Name>
                <a:Code>PK_Z_DIMROOMMONTH</a:Code>
                <a:CreationDate>1366118213</a:CreationDate>
                <a:Creator>huzhiwen</a:Creator>
                <a:ModificationDate>1366118213</a:ModificationDate>
                <a:Modifier>huzhiwen</a:Modifier>
                <c:Key.Columns>
                  <o:Column Ref="o361"/>
                </c:Key.Columns>
              </o:Key>
            </c:Keys>
            <c:PrimaryKey>
              <o:Key Ref="o380"/>
            </c:PrimaryKey>
            <c:ClusterObject>
              <o:Key Ref="o380"/>
            </c:ClusterObject>
          </o:Table>

       可以看到这些节点都是带命名空间,所以我们解析这段XML的时候需要加上命名空间。表的<a:Name>(中文名称),<a:Code>(表名),<c:Columns>是所有列节点集合,具体到每一列的<o:Column>则有中文名称,英文名称,主键,是否空,默认值,是否自增等关键信息了。        参考上面的设计,添加了四个实体,ColumnInfo,TableInfo,PkKeyInfo,PhysicalDiagramInfo

回到顶部

PDM文件读取

        1.加载XML    

   /// <summary>
        /// 读取xml文件返回XmlDocument对象
        /// </summary>
        /// <returns>XmlDocument对象</returns>
        private XmlDocument GetXmlDom()
        {
            try
            {
                if (xmlDoc == null)
                {
                    StreamReader sr = new StreamReader(_pdmPath);
                    xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(ReplaceLowOrderASCIICharacters(sr.ReadToEnd()));                 
                }
                return xmlDoc;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

       2.设置XML的命名空间

 /// <summary>
        /// 设置xml文件命名空间
        /// </summary>
        /// <returns>XmlNamespaceManager</returns>
        private XmlNamespaceManager GetXmlNamespace()
        {
            XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(GetXmlDom().NameTable);
            xmlnsManager.AddNamespace("a", "attribute");
            xmlnsManager.AddNamespace("c", "collection");
            xmlnsManager.AddNamespace("o", "object");
            return xmlnsManager;
        }

View Code

       3.从中XML读取表信息 

 /// <summary>
        /// 从中XML读取表信息
        /// </summary>
        /// <returns> List</returns>
        public List<TableInfo> GetTableInfo()
        {
            try
            {
                XmlDocument xmlDoc = GetXmlDom();
                XmlNamespaceManager xmlnsManager = GetXmlNamespace();
                XmlNode xnTables = xmlDoc.SelectSingleNode("//" + "c:Tables", xmlnsManager);
                List<TableInfo> Tables = new List<TableInfo>();
                foreach (XmlNode xnTable in xnTables.ChildNodes)
                {
                    Tables.Add(GetTable(xnTable));
                }
                return Tables;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 获取节点中表的信息
        /// </summary>
        /// <param name="xnTable">xmlNode</param>
        /// <returns>表信息</returns>
        private TableInfo GetTable(XmlNode xnTable)
        {
            try
            {
                TableInfo mTable = new TableInfo();
                XmlElement xe = (XmlElement)xnTable;
                mTable.TableID = xe.GetAttribute("Id");
                XmlNodeList xnTProperty = xe.ChildNodes;
                foreach (XmlNode xnP in xnTProperty)
                {
                    switch (xnP.Name)
                    {
                        //表的ID
                        case "a:ObjectID":
                            mTable.TableObjectID = xnP.InnerText;
                            break;
                        //表的中文名称
                        case "a:Name":
                            mTable.Name = xnP.InnerText;
                            break;
                        //表的英文名称
                        case "a:Code":
                            mTable.Code = xnP.InnerText;
                            break;
                        //表的描述
                        case "a:Comment":
                            mTable.Comment = xnP.InnerText;
                            break;
                        //表的列信息
                        case "c:Columns":
                            InitColumns(xnP, mTable);
                            break;
                        //表的主键信息
                        case "c:Keys":
                            InitKeys(xnP, mTable);
                            break;
                        default:
                            break;
                    }
                }
                if (string.IsNullOrEmpty(mTable.Comment))
                {
                    mTable.Comment = mTable.Name;
                }
                if (mTable.ListPkKeyInfo != null && mTable.ListPkKeyInfo.Count > 0)
                {
                    foreach (PkKeyInfo pkInfo in mTable.ListPkKeyInfo)
                    {
                        ColumnInfo info = mTable.ListColumnInfo.Single(c => c.ColumnId == pkInfo.ColumnId);
                        pkInfo.Name = info.Code;
                        info.PK = true;
                        mTable.PkKeyNameList = mTable.PkKeyNameList + pkInfo.Name + ",";
                    }
                }
                //杜冬军2014-05-16 修改没有主键  生成SQL有问题的BUG  V1.4
                else
                {
                    mTable.ListPkKeyInfo=new List<PkKeyInfo>();
                }
                if (!string.IsNullOrEmpty(mTable.PkKeyNameList))
                {
                    mTable.PkKeyNameList = mTable.PkKeyNameList.Substring(0, mTable.PkKeyNameList.Length - 1);
                }
                return mTable;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

       4.读取列信息 

  /// <summary>
        /// 获取列信息
        /// </summary>
        /// <param name="xnColumn">列节点</param>
        /// <returns>列信息</returns>
        private ColumnInfo GetColumn(XmlNode xnColumn)
        {

            ColumnInfo mColumn = new ColumnInfo();
            XmlElement xe = (XmlElement)xnColumn;
            mColumn.ColumnId = xe.GetAttribute("Id");
            XmlNodeList xnCProperty = xe.ChildNodes;
            foreach (XmlNode xnP in xnCProperty)
            {
                switch (xnP.Name)
                {
                    //列ID
                    case "a:ObjectID":
                        mColumn.ColumnObjectId = xnP.InnerText;
                        break;
                    //列中文名称
                    case "a:Name":
                        mColumn.Name = xnP.InnerText;
                        break;
                    //列英文名称
                    case "a:Code":
                        mColumn.Code = xnP.InnerText;
                        break;
                    //列描述
                    case "a:Comment":
                        mColumn.Comment = xnP.InnerText;
                        break;
                    //列数据类型
                    case "a:DataType":
                        mColumn.DataTypeStr = xnP.InnerText.Replace("(", "(").Replace(")", ")");
                        mColumn.DataType = Common.GetColumnDataType(mColumn.DataTypeStr);
                        mColumn.Width = Common.GetColumnWidth(mColumn.DataTypeStr);
                        break;
                    //列宽度
                    case "a:Length":
                        mColumn.Length = xnP.InnerText;
                        break;
                    //列是否自增
                    case "a:Identity":
                        mColumn.Identity = Common.ConvertToBooleanPG(xnP.InnerText);
                        break;
                    //列默认值
                    case "a:DefaultValue":
                        mColumn.DefaultValue = xnP.InnerText;
                        break;
                    //列是否可为空
                    case "a:Mandatory":
                        mColumn.Nullable = Common.ConvertToBooleanPG(xnP.InnerText);
                        break;
                    default:
                        break;
                }
            }
            if (string.IsNullOrEmpty(mColumn.Comment))
            {
                mColumn.Comment = mColumn.Name;
            }
            if (string.IsNullOrEmpty(mColumn.DefaultValue))
            {
                mColumn.DefaultValue = "";
            }
            return mColumn;
        }       

    其它信息操作可以查看源代码里面的PDMReader.cs文件

回到顶部

XML文件操作增删改查

       PDM文件操作完毕,大家可以发现归根到底就是XML的增删改查操作,读取XML文件用Xpth比较方便。

       我做了一个小例子供大家参考:XmlDemo

 public void Read()
        {
            XmlNodeList xmlNodeList = null;
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            Console.WriteLine("遍历item节点");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                Console.WriteLine("item节点的RoomInfo属性读取:{0}", xmlNode.Attributes["RoomInfo"].Value);
                Console.WriteLine("item节点的RoomInfo的值读取:{0}", xmlNode.InnerText);
            }
            Console.WriteLine("遍历items下的item节点");
            xmlNodeList = XmlDoc.SelectNodes("/root/items/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                Console.WriteLine("item节点的RoomInfo属性读取:{0}", xmlNode.Attributes["RoomInfo"].Value);
                Console.WriteLine("item节点的RoomInfo的值读取:{0}", xmlNode.InnerText);
            }
            Console.WriteLine("遍历第一个items下的item节点");
            xmlNodeList = XmlDoc.SelectNodes("/root/items[@id='item1']/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                Console.WriteLine("item节点的RoomInfo属性读取:{0}", xmlNode.Attributes["RoomInfo"].Value);
                Console.WriteLine("item节点的RoomInfo的值读取:{0}", xmlNode.InnerText);
            }
            Console.WriteLine("遍历第二个items下的Group下的item节点");
            xmlNodeList = XmlDoc.SelectNodes("/root/items[@id='item2']/Group[@id='g1']/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                Console.WriteLine("item节点的RoomInfo属性读取:{0}", xmlNode.Attributes["RoomInfo"].Value);
                Console.WriteLine("item节点的RoomInfo的值读取:{0}", xmlNode.InnerText);
            }
        }
  public void Update()
        {
            Console.WriteLine("修改所有的item节点RoomInfo的属性的值为123");
            XmlNodeList xmlNodeList = null;
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.Attributes["RoomInfo"].Value = "123";
            }
            Console.WriteLine("修改所有的item节点的值为123");
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.InnerText = "123";
            }
            Console.WriteLine(XmlDoc.InnerXml);
        }
 public void Delete()
        {
            Console.WriteLine("删除所有的item节点");
            XmlNodeList xmlNodeList = null;
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.ParentNode.RemoveChild(xmlNode);
            }
            Console.WriteLine("删除所有的items下的子节点");
            xmlNodeList = XmlDoc.SelectNodes("/root/items");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.RemoveAll();
            }
            Console.WriteLine(XmlDoc.InnerXml);
        }
public void Add()
        {
            Console.WriteLine("item节点添加test=123属性");
            XmlNodeList xmlNodeList = null;
            XmlAttribute xmlAttribute = null;
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlAttribute = XmlDoc.CreateAttribute("test");
                xmlAttribute.Value = "123";
                xmlNode.Attributes.Append(xmlAttribute);
            }
            Console.WriteLine("item节点添加子节点<test name='123'>");
            xmlNodeList = XmlDoc.SelectNodes("/root/item");
            XmlElement xmlNewNode = null;
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNewNode = XmlDoc.CreateElement("test");
                xmlNewNode.SetAttribute("name", "123");
                xmlNewNode.InnerText = "123";
                xmlNode.AppendChild(xmlNewNode);
            }
            XmlDoc.Save("C:\\123.xml");
            Console.WriteLine(XmlDoc.InnerXml);
        }

回到顶部

工具源代码下载

      目前总共有经过了七个版本的升级,现在提供最新版本的下载地址

数据字典生成工具V2.0安装程序

最新安装程序

数据字典生成工具源代码

最新源代码

http://code.taobao.org/svn/DataDicPub

SVN最新源码共享地址

回到顶部

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

Enterprise Library Policy Injection Application Block 之三:PIAB的扩展—创建自定义CallHandler(提供Source Code下载)

本系列的第一部分对PIAB使用场景进行了简单的介绍,作中阐述了通过PI(Policy Injection)的方式实现了Business Logic和Non-Bu...

25710
来自专栏算法修养

Lucene.net(4.8.0) 学习问题记录二: 分词器Analyzer中的TokenStream和AttributeSource

前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移。因为项目整体要迁移到ASP.NET Core ...

3057
来自专栏岑玉海

MD5鉴定文件是否相同

由于诸多安全因素,需要对网上下载的一些文件进行完整性校验。比如,由于工作需要我下载了一个EMOS_1.5_i386.iso镜像文件(extmail邮件系统),需...

3895
来自专栏个人随笔

C#编写街道管理系统

项目需求: 一、语言和环境A、实现语言 C#B、环境要求 Visual Studio 2012 二、功能要求 现使用.NET WinForms技术为居委会开发...

3316
来自专栏跟着阿笨一起玩NET

C#实现文件数据库

本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。

411
来自专栏技术记录

通讯协议序列化解读(一) Protobuf详解教程

2537
来自专栏大内老A

WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)

[爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道《天天山海经》为此录制的节目视频(苏州话)]]通过上篇的介绍,我们知道了WCF所有与编码与...

1959
来自专栏菩提树下的杨过

Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)

题外话:个别朋友总是问我同样的问题,做为一名c#/silverlight程序员为啥还要学flash ? 回 答:看日本片时,就不能对照看欧美的么? 不体会日本的...

1777
来自专栏上善若水

021android初级篇之android的Context

021android初级篇之Android注解支持(Support Annotations)

543
来自专栏Android Note

Android 资源文件

1304

扫码关注云+社区