从这篇开始将正式讲解整个重要部分的实现细节,本篇讲解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;
            }
        }
View Code

       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;
            }
        }
View Code
        /// <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;
            }
        }
View Code

       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;
        }       
View Code

    其它信息操作可以查看源代码里面的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);
            }
        }
View Code
  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);
        }
View Code
 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);
        }
View Code
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);
        }
View Code

 

 

工具源代码下载

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

数据字典生成工具V2.0安装程序 最新安装程序
数据字典生成工具源代码 最新源代码
http://code.taobao.org/svn/DataDicPub SVN最新源码共享地址

学习使用

      如果你使用了该工具,或者想学习该工具,欢迎加入这个小组,一起讨论数据字典生成工具、把该工具做的更强,更方便使用,一起加入147425783 QQ群

      更多数据字典生成工具资料请点击数据字典生成工具专题

 

posted on 2014-07-14 12:52  焰尾迭  阅读(5275)  评论(7编辑  收藏  举报