辛怀声 王鹏
摘要:在开展数据处理和数据分析的工作前,常常需要对采集的原始数据进行解析处理,常规的方法是针对大量的数据接口分别开发解析代码,这样做不仅工作量大,代码冗余度高,日后对接口进行修改或添加时都需要同步修改解析程序的相应代码,给数据分析处理工作带来极大的困难。为了有效解决这一问题,该文提出了一种基于XML的数据解析方法,实现接口定义和程序编码的隔离,能够在不改动程序代码情况下,实现数据接口的按需添加或修改,有利于节约后期针对解析程序的开发和维护成本。
关键词:XML;数据解析;隔离;接口
中图分类号:TP319 文献标识码:A 文章编号:1009-3044(2014)01-0057-03
1 概述
在日常软件工程中为了优化或者增加新功能往往需要对数据接口进行修改或删减。这时数据记录设备记录下来的数据格式也会随之发生改变。对于事后的数据分析处理工作来说,这意味着数据解析的开发工作会伴随着数据接口的改变而一直进行。经常出现的一种情况就是进行数据解析时程序报錯,进行错误定位之后发现是数据格式发生了变化,于是需要对相应的数据接口进行代码开发或更改,这给数据解析工作带了很大的不便,降低了数据分析的效率,也加大了数据解析和分析出错的几率。
2 解决办法
可扩展标记语言(Extensible Markup Language, XML)是一种用于描述数据与平台无关的语言,以一种开放的自我描述方式定义数据结构,在描述数据内容的同时突出对结构的描述,是一种存储结构化数据的规范[1-2]。XML是一种元标记语言, 可以用来定义其他的标记语言, 并且这些标记语言的元素标记是由用户自己定义的。所以由XML可以派生出无限多种标记语言。在这些标记语言必须根据一定得规则来定义和组织,但是这些标记在其含义上是非常灵活的[3]。
本文使用XML对接口数据进行映射,不在程序代码中对数据接口进行“硬编码”,之后针对XML生成文件解析指令序列,最后按照指令序列对数据文件进行解析,把解析程序代码与接口定义进行隔离,从而使数据接口的更改对解析程序代码的影响降到最低。
3 程序设计
3.1 XML与数据结构映射
待解析的数据都是由网络报文记录而成的二进制文件,报文内容如图1所示。
如图1所示,最前面的数据是消息代码,用来标识消息类型,之后是消息长度,用来标识消息之间的边界位置。通过这两个值我们可以识别和解析数据文件中的所有二进制数据的内容。对于上述数据,我们可以用数据结构(struct)或类(class)来进行抽象。如下面C++代码所示:
struct Header
{int messagetype;
int length;
char spare[4]
};
struct DataTypeA
{Header head;
int A;
int B
};
接口数据类型DataTypeA包括了消息头结构和消息体数据A和B。消息头包括了消息类型消息长度和一些其他数据以及保留数据空间。
进一步可以用XML对其进行表示,如下所示:
<?xml version="1.0" encoding="utf-8"?>
上面的XML中ID表示数据项名称。Array表示是否为数组,如果Array的值是1,则表示单个数据项,如果大于1,则表示一个数组。Style表示是否为嵌套的数据结构,如果值为“element”表示不是数据结构,如果值为“structure”则表示是数据结构,需要从XML中另行查找它的具体定义。 从上面XML中可以看出,这里定义了两类数据结构,一类是HEADER数据结构,另一类是DataTypeA数据结构,而DataTypeA数据结构又嵌套了HEADER数据结构。这与前面的C++代码是一致的。通过上面的步骤,我们建立了一种二进制接口数据到XML的映射。
3.2 文件解析指令序列
对数据接口进行XML映射之后,程序代码就可以与具体的数据接口定义进行隔离了,从而实现数据接口变化不影响程序代码的目标。为了实现程序代码与数据接口隔离,程序将根据XML文件的内容生成一系列的数据解析指令。 这里的指令序列指的是由一系列文件读取的长度和数据类型组成的序列,如下表1所示:
表1 数据解析指令序列
[接口类型\&数据名称\&数据类型\&DataTypeA\&MESSAGE_TYPE\∫\&MESSAGE_LEN\∫\&MESSAGE_SPARE\&char\&MESSAGE_SPARE\&char\&MESSAGE_SPARE \&char\&MESSAGE_SPARE\&char\&A\∫\&B\∫\&]
之后我们就可以根据上述指令序列对待解析的文件进行解析读取。
3.3 XML文件处理流程
为了生成文件解析指令序列,我們需要对XML文件进行处理。XML文件的处理流程如下图2所示,首先读取DataTypeA对应的XML文件,然后定位到定义DataTypeA的节点,之后循环处理DataTypeA的子节点。处理过程是:如果该子节点为简单数据类型,则将该节点中的数据类型信息和数据名称加入解析指令序列;如果该节点表示的是一个数据结构则启动递归过程找到定义该数据类型的节点,并重复与DataTypeA相同的处理过程,直到处理完所有DataTypeA的子节点为止。
3.4 文件数据解析流程
生成了接口数据类型对应的文件解析指令序列后,我们可以根据文件解析指令序列对文件进行解析。顺序读取解析指令,根据数据类型决定调用的文件读取函数。例如:如果当前一条文件读取指令指示的数据类型为char,我们就可以调用相应的类似ReadChar()之类的函数(由用户的变成语言确定);如果指示的数据类型为float,我们就可以调用类似ReadFloat()之类的函数。流程如图3所示。
4 结束语
由于大多数编程语言都对XML处理提供了强大的处理函数,该文介绍的利用XML文件映射接口数据,之后再解析数据的方法可以用于大部分编程语言环境。本方法使程序代码与接口定义解除耦合关系,做到了新定义接口或修改后的接口的“即插即用”,无需针对接口的修改对解析程序进行修改和重新编译,提高了数据解析的工作速度和正确率。
参考文献:
[1] 甘小斌.XML标准体系介绍[J].信息技术与标准化,2004(9): 41-44.
[2] 陈春咏.基于XML的指挥自动化辅助决策系统研究[D].南京:东南大学,2007.
[3] 怀石工作室.XML完全手册[M].北京:中国电力出版社,2000.