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

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

阅读目录

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

PDM文件读取

XML文件操作增删改查

工具源代码下载

学习使用

回到顶部

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

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

41144D16-B6B3-43CD-8B36-57CBAFB26654

预算资源面积月事实表

y_FactYsRoomAreaMonth

1366118213

huzhiwen

1396403208

gongw

F03D6EA9-183A-4B6A-BD52-7B711572AA45

ID

ID

1366118213

huzhiwen

1381212250

huzw

bigint

1

1

F9089FCD-D9E9-4FB0-92F3-B7268D49526D

PK_Z_DIMROOMMONTH

PK_Z_DIMROOMMONTH

1366118213

huzhiwen

1366118213

huzhiwen

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

回到顶部

PDM文件读取

1.加载XML

///

/// 读取xml文件返回XmlDocument对象

///

/// XmlDocument对象

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的命名空间

///

/// 设置xml文件命名空间

///

/// XmlNamespaceManager

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读取表信息

///

/// 从中XML读取表信息

///

/// List

public List GetTableInfo()

{

try

{

XmlDocument xmlDoc = GetXmlDom();

XmlNamespaceManager xmlnsManager = GetXmlNamespace();

XmlNode xnTables = xmlDoc.SelectSingleNode("//" + "c:Tables", xmlnsManager);

List Tables = new List();

foreach (XmlNode xnTable in xnTables.ChildNodes)

{

Tables.Add(GetTable(xnTable));

}

return Tables;

}

catch (Exception ex)

{

throw ex;

}

}

View Code

///

/// 获取节点中表的信息

///

/// xmlNode

/// 表信息

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();

}

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.读取列信息

///

/// 获取列信息

///

/// 列节点

/// 列信息

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节点添加子节点");

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群。

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

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。

如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。

如果,想给予我更多的鼓励,求打

因为,我的写作热情也离不开您的肯定支持。

感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是焰尾迭 。