【IT168 技术文档】摘要:本文介绍了使用XML框架文件来建立数据文件的数据模型,以剥离数据文件的定义和存储,从而减少数据格式改变对数据处理造成的影响。
一、 引言
在数据处理系统中,开发人员最怕听到的就是数据格式的改变,这是因为对数据格式的任何改变都需要与所涉及到的数据处理同步,其中包括和所有应用程序涉及到的可能使用的那部分数据访问代码。所以如何将数据的定义和存储剥离开来,减少数据格式改变对数据处理的影响对于数据处理系统变得尤为重要。
二、设计思路和要点
对于常见的数据文件而言,都是采取以记录方式存放。即1个数据文件中存放多条记录,记录与记录之间按照约定的分隔符进行分隔,一般常用的就是换行符(‘\n’),每1行对应1条记录。而每条记录又包含多个字段,字段与字段之间也是通过约定的分隔符进行分隔。常用的CSV文件就是以逗号(‘,’)来分隔字段。以下是数据文件所包含的内容与数据模型的对应关系对应表: 
表1:数据文件与数据模型元素对应关系表
按照上述分析,我们就可以考虑按照:数据表→记录→字段来建立数据文件的数据模型。
在定义需要把握以下3个原则:
(1)将数据定义和存储剥离,这样才能减少数据定义对存储的影响。
(2)数据定义的变更只表现在定义部分,而对数据存储的定义没有影响。
(3)要考虑字段类型的多样性,例如:组合字段。
三、定义数据文件模型
考虑到XML框架的良好扩展性,下面采用XML框架来定义数据文件模型。以下是两组XML定义: 
图1:XML定义1 
图2:XML定义2
图1和图2中,定义了两种格式不同(字段顺序和内容存在差异)的数据文件,但是采用了相同的定义模式:
(1)通过数据表名称(Table Name),字段数量(Field Count)和主键(Primary Key)来定义数据表(Table)。通过数据表名称可以获取对应数据表的属性信息。
(2)通过名称(Field Name),最大值(Max Size),是否为空(Is Null),默认值(Default)和分隔符(Separator)来定义字段(Field)。通过字段名称来获取对应字段的属性信息。
(3)记录的定义隐含在字段定义和字段顺序信息中。
需要注意的是:
(1)当某些字段是组合字段时,通过字段的分隔符属性(Separator)就可以实现对该组合字段的判定和分解。
(2)数据定义的不同只表现在属性内容(例如:名称,最大值)和顺序的不同,定义框架无须改变。
四、将数据文件模型导出到XML文件
考虑到数据格式定义的可维护性,我们采用DOM模型和XML框架文件来管理和导出数据文件模型。通过建立DOM模型的数据表(Table),记录(Record),关键字段(Primary Key)和字段(Field)等结点来与数据文件模型元素建立对应,再由DOM模型导出到XML文件。实施的步骤是:
1.建立空的DOM模型
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); //Dummy document //Root node Element root = doc.createElement("TableStructure"); doc.appendChild(root); Table Structure是所有数据表定义的根结点,该结点下可以包含多个数据表定义。
2.定义数据表和记录字段
public Element defineTable(Document __doc, Element __root, String __name, String __fieldCount, String __primaryKey) { Element table = __doc.createElement("Table"); __root.appendChild(table); //One table have 3 attributes table.setAttribute("NAME", __name); table.setAttribute("FIELD_COUNT", __fieldCount); table.setAttribute("PRIMARY_KEY", __primaryKey); return (table); } public void defineField(Document __doc, Element __table, String __name, String __type, String __null, String __default, String __separator) { Element field = __doc.createElement("Field"); __table.appendChild(field); //One field have 4 attributes field.setAttribute("NAME", __name); field.setAttribute("MAX_SIZE", __type); field.setAttribute("NULL", __null); field.setAttribute("DEFAULT", __default); field.setAttribute("SEPARATOR", __separator); //Field may be composite field } 数据表以“Table”结点进行定义,主键的定义存在于数据表的定义中。字段以“Field”结点进行定义,字段的内容及顺序隐含了记录的定义。
3.添加数据表和字段定义到DOM模型
//Defines table Element table = defineTable(__doc, __root, "ROAD", "16", "ID"); //Defines fields defineField(__doc, table, "ID", "13", "NOT", "", ""); //#1 defineField(__doc, table, "CLASS", "3", "NOT", "", ""); //#2 defineField(__doc, table, "WIDTH", "3", "NOT", "", ""); //#3 当数据定义改变时,只需调整数据表以及字段的属性即可。这些调整包括:添加新表/字段,删除表/字段,调整字段顺序,拆分字段,字段合并(字段组合)。
4.将DOM模型结构转换成XML文档
TransformerFactory factory = TransformerFactory.newInstance(); Transformer tf = factory.newTransformer(); DOMSource source = new DOMSource(__doc); StreamResult result = new StreamResult(new File(__fileName)); tf.setOutputProperty(OutputKeys.STANDALONE, "yes"); tf.setOutputProperty(OutputKeys.INDENT, "yes"); tf.transform(source, result); 通过XSLT(Extensible Style sheet Language Transformations)引擎来实现将DOM模型转换成XML文件。详细内容请参见XSLT相关参考。
五、小结
(1)数据文件的模型结构与DOM结构比较近似,使用DOM模型可以完全满足数据文件的模型定义。
(2)DOM模型到XML文件的导出比较透明,这样极大方便了数据模型的维护:只需要DOM模型与数据文件的模型一致即可,不用考虑XML文件的维护的细节。
(3)模型定义的导出可以是“一次导出,多次使用”,只有当数据文件模型发生改变时,才需要重新导出新的XML文档,这样极大方便了模型定义的版本管理。