從這篇開始將正式講解整個重要部分的實現細節,本篇講解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; }
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最新源碼共享地址 |
學習使用
如果你使用了該工具,或者想學習該工具,歡迎加入這個小組,一起討論數據字典生成工具、把該工具做的更強,更方便使用,一起加入147425783 QQ群。
更多數據字典生成工具資料請點擊數據字典生成工具專題。