周 游,陆安江
(贵州大学,贵州 贵阳 550025)
XML是一种广泛用来描述不同数据类型以及异构关系数据库的可扩展标记语言,并在异构关系数据库之间的转换过程发挥桥梁作用[1-3]。为了更好的应用和开发基于关系模型的数据库系统,为了实现数据共享,开发了许多转换算法和方法。文献[4]提出一种转换方法,可以实现XML到word之间的转换,同时也可以实现word到XML之间的转换;文献[5]通过Java可以实现从word文本到XML文本之间的转换;文献[6]提出一种基于XML文档为中间件,利用ASP+XML技术,使用基于模型驱动的方法来映射XML与关系数据库数据之间的关系,然后借助SQL实现数据转换。本文提出一种基于文档类型定义(DTD)的XML模式转换为对象关系模型模式的可逆转换方法。
在这一部分,我们将对在本文中使用到的术语、定义、符号以及用法进行介绍。对于对象关系模型的结构组成成分,通过文献[7-10]可概括为以下四个部分:
(1)对象类型或具有属性的用户定义类型(UTD);
(2)对象表、泛型类型以及继承;
(3)对象的集合或引用的集合;
(4)对象的引用或类型引用。
对于XML文档模型,我们采用<>来表示,以“<”开始,以“>”停止,则可通过式(1)中的符号来对使用其属性和内容模型的XML元素进行定义[11]。那么,对于XML文档中的元素A,它的定义就可以通过A给出。如式(1)所示:
通过文献[11]可知在式(1)中:(1)::=符号表示被定义为;(2)A表示元素的名称;(3)N表示元素A的内容模型;(4)Attrs表示元素A的属性列表,即Attrs=Attr1,Attr2,…,Attrm通过式(1)中对Attrs(下划线Attrs)属性列表的定义,我们可知它可以通过‘_’和属性Attri(1≤i≤m)获得。因此我们可以这样来表示Attrs,即Attrs=Attr1,Attr2,...,Attrm= Attr1,Attr2...,Attrm。
接下来我们对属性Attri,即Attri进行定义,如式(2)所示:
在式(2)中,(1)Attri表示属性;(2)ToV表示在XML模型中的属性类型或其值的列表[12];(3)Dp表示属性默认值,其定义如式(3)所示:
通过文献[13]可知在式(3)中,1)|表示或;#REQUIRED表示属性是必须的;2)#IMPLED表示属性不是必须的;3)#FIXED value表示属性是固定的;4)value表示属性是默认的。
通过对术语、定义及符号的介绍,接下来我们将介绍XML文档与对象关系模型之间的映射。
接下来我们考虑一个多态函数β,该函数允许我们将XML schema转换为对象关系模型。此函数将对象关系模型中的对象A与每一个XML中的元素A进行关联,因此可以给出对象类型β(A)的定义,其定义如式(4)所示:
在式(4)中,(1)A(在::=右边)表示对象关系类型中关联到XML文档中元素A的对象关系类型;(2)L表示属性定义列表。
在这个列表中的每一个元素都是对象类型中属性的定义,这个定义可以通过式(5)得到:
在式(5)中,(1)Attri表示对象类型属性;(2)Type表示属性Attr的类型;(3)M表示值的约束列表。这些约束可以为空(null)、非空(not null)、唯一性(unique)、外键约束(foreign key)、以及检查约束(check)[14]。由巴科斯范式(BNF)可知,用尖括号(<>)括住表示必选项,用方括号([])括住表示可选项[15]。
接下来我们看看如何通过β函数来计算对象类型“A”的属性;在式(1)中我们有:A::=〈A;Attrs;N〉。因此可以给出对象类型的定义,其定义如式(6)所示:
在式(6)中“U”表示联合运算符;为了能得到对象类型 A,我们不得不分别计算 β(Attrs)和 β(N)。
β(Attrs)是对象类型的属性定义列表,β(Attrs)计算算法流程如图1所示。
通过式(2)可知,在XML schema中每个属性Attri可以通过Attri::=〈Attri;ToV;Dp〉得到;因此对于 β(Attri),我们可以通过 β(Attri)::= β(<Attri;ToV;Dp>)得到。对于β(<Attri;ToV;Dp>)的值,我们可以通过式(7)计算得到:
式(7)中C表示约束。通过式(7)我们可知,为了求 β(Attri),我们必须计算 β(ToV),β(Dp)和 C。
图1 β(Attrs)算法流程
在对象关系模型中β(ToV)表示的是属性Attri类型的值,以及值得约束。我们可以通过表1得到 β(ToV)。
在表 1中:(1)Varchar(n)表示在数据库系统里字符串使用类型的标准,n表示类型的大小;(2)Varchar(p)表示在对象关系型数据库里值集合的数据类型,p表示集合的大小;(3)嵌套表表示的是在关系型数据库里使用的数据类型,它反映的是大小没有限制的值的集合:(4)通过文献[16]我们可知Letter和Digit是按以下规律定义的:Letter::=[A...Za...z].Digit::=[0...9]。
在表1的约束列有:(1)唯一约束(UC)表示在属性是一个明确的值;(2)外键约束(FKC)表示引用一个完整性的约束;(3)枚举约束(ELConstraint)表示具有与指定XML元素的内容模型属性的枚举值对应的值列表的约束。我们使用LAC 来表示 (Letter|_)(Letter|_|Digit|:|.|-)。
表1 β(ToV)的计算
为 了 计 算 β(Attri), 我 们 不 得 不 计 算 β(Dp)。β(Dp)的值通常是一个数据库约束的列表,通过表2可以求出 β(Dp)的值。
表2 β(Dp)的计算
为了更好的理解函数β,我们看一下下面的列子:
<!ELEMENTcinema(...)>
<!ATTLIST cinema id ID #REQUIRED>
<!ATTLIST cinema popularity CDATA #IMPLIED>
以上定义了id元素,元素cinema有两个属性:cinema和popularity;β(id)=β(〈id;ID;#REQUIRED〉),β(popularity)=β(〈popularity;CDATA;#IMPLED〉)。
我们把函数β应用到cinema可得:
β(cinema)=cinema(β(id),β(popularity)...)
首先,我们计算β(id),通过式(2)我们可得:
β(id)=β(<id;ToV;Dp>)
通过式(7)可得:
β(<id;ToV;Dp>)=<id;β(ToV)-C;β(Dp)+C>
由表1和表2可得:
β(id)=〈id;β(ID)-(LAC+UC)〉;
β(#REQUIRED)+(LAC+UC);
β(#REQUIRED)=not null;
那么
β(id)= <id; varchar; not null +(LAC+UC)>。
接下来我们计算 β(popularity),同理可得:β(popularity)=<popularity;varchar;null>。
则cinema的对象变为:
cinema(〈id; varchar; not null +(LAC+UC)〉;
popularity;varchar;null,...)
通过以上分析有:XML文档属性到对象属性的算法(命名为算法2)。具体流程如图2所示。
图2 XML文档属性到对象属性的算法
通过式(6)可知:β(A)::=A(β(Attrs)Uβ(N),通过(1)我们已经对β(Attrs)的计算进行详细介绍,为了得到完整的对象类型的属性列表,我们必须计算 β(N)。接下来展开对 β(N)计算的介绍。
通过式(1)有:A::=〈A;Attrs;N〉,其中N表示元素A的内容模型,可以为any(该模型包含文本、元素和空格),empty(禁止把文本或者元素作为一个声明为空的子元素)和混合模型(包含文本、内容和属性)。接下来看一个DTD的列子:
<!ELEMENT cinema (time+)>
<!ELEMENT cinema id ID #REQUIRED category CDATA #IMPLIED>
<!ELEMENT time(date+)>
<!ELEMENT date(move+)>
<!ELEMENT move(move_name,director)>
<!ELEMENT move_name (#PCDTATA)>
<!ELEMENT director(#PCDTATA)>
通过式(1)可知cinema元素可表示为:
cinema::=<cinema;id,category; time +>。
其中time+为cinema元素N的值;其定义如下:time::=<time;;date +>。
同样,对于元素move可以定义为:move::=<move;; move_name, director>。“move_name,director”是move元素N的值。
元素move_name的定义如下:move_name::=<move_name;;#PCDATA>;元素director的定义为:director::=< director;;#PCDATA>。 因 此 move_name和director元素的N值为#PCDATA。
为了使β(N)的计算更加简化,我们利用巴克斯范式(BNF)语法来对XML文档的内容模型进行求解(其中A是N的元素)。我们称这种语法为,将语法G与式(1)结合可得语法G,最终可得β(G)。具体如下所示:
(1)β(A)::=β(ANY);(ANY 指任何数据和任何类型)
(2)β(A)::=β(EMPTY);(EMPTY指空的字符串)
(3)β(A)::=(-A-1,A--2):=β(A--1),β(A--2);(A1,A2是用来区别’=’左边和右边的元素A)
(4)β(A)::=(+,β(A--1),β(A--2);(定义一种可以保存对象类型 β(-A-1)和 β(A--2)的一般类型)
(5)β(A)::={β(A)};(具有空约束的 β(A)表)
(6)β(A)::={β(A)};(具有非空约束的 β(A)表)
(7)β(A)::=[β(A)];(具有空约束的 β(E)
(8)β(A)::=β(#PCDATD)。
β(#PCDATD)的值通过 β(#PCDATD)::=<value;varchar;””>来计算。
为了更好的理解β函数,接下来看以下列子:
那么move_name是一个具有属性命名值得对象类型,属性类型是没有约束的varchar。
(2)接下来看一个复杂的列子,对于XML文档中的move元素我们定义如下所示:
move::=<move;;move_name,director>, 则β(move)=move(β(move_name,director)=move(β(move_name), β(director)。假设用其值来代替 β(move_name)和 β(director),那么可得:β(move)=move(move_name(<value;varchar;””>),director(<value;varchar;””>)。
因此,’move’是一个具有两个属性(move_name和director)的对象类型,它们中的每一个都具有一个与之对应的属性命值的对象类型。计算β(N)可以通过以下算法(命名为算法3)获得:
(1)开始;
(2)输入N,一个XML文档元素A的内容模型;
(3)在不同的A中随机选择V,使得β(V)在β(N)中;
(4)如果 β(V)不在 V 中,那么通过 β(G)和算法 2 计算 β(V);
(5)如果没有 β(V)在 β(N)中或者在 β(N)中的每一个 β(V)都没在 V 中再或者 β(V)=β(E),那么退出循环;否则返回c。
(6)输β(N),对象属性列表;
(7)结束。
图3 β(N)计算流程
通过以上的介绍,接下来我们考虑如何将XML模型转换为对象关系模型。为了创建XML文档到对象类型的映射,我们从以下两方面进行讨论:A)对象属性的创建;B)创建与XML schema关联的对象类型。
将对象属性的创建函数命名为COA,COA函数以一个属性作为具有目录列表的参数,并返回表达式〈attr;typeOfAttribute;M〉。通过式(5)可知,该表达式反映的是对象关系模型中属性的定义。该函数基于以上定义的β函数计算的值,其定义如下所示:
通过上述定义的β函数计算元素x的值;
对于在 attr 中的每一个 {β(x)},如果与 x 相关的类型没有被创建,那么创建对象类型x作为不。完整类型;创建一个列表类型,称为xs;在attr中用 <”xs”;xs;’’> 来替换 {β(x)};
对于在 attr 中的每一个 [β(x)],在 (x(...)添加一个空约束(null constraint),然后在 attr中用 (x(...))来替换 [β(x)];
如果与attr相关的类型没有被创建,那么创建一个对象类型,称为attr,返回<”attr”;attr;””>;其中每一个attr属性相当于目录列表中的目录;
对于形如 x(<value;varchar;””>)模型,创建对象属性 (x(...),返回(4);
对于形如x(y(<value;varchar;””>), f(<value;varchar;””>),…)模型,创建对象属性 (x(...),在 attr 中 用 x(<”y”;y;””>,<”f”; f;””>,…)来替换,返回(4)。
对于元素 e(...)与正则表达式(…β(x)…)有关,如果x类型没有被创建,那么创建一个对象类型,并用〈”x”;refx;〉替换 β(x)。
为了更好的理解上诉定义,接下来看一个例子:
<!ELEMENTmove(move_name,director,cite?)>
<!ELEMENT move_name(#PCDAT)>
<!ELEMENTdirector(fn,ln)>
<!ELEMENTfn(#PCDAT)>
<!ELEMENTln(#PCDAT)>
<!ELEMENTcite(move*)>
β(move)可以通过以下表达式来计算:β(move)=move(β(move_ame),β(director),[β(cite)]); 为 了 创 建对象属性,我们不得不分别计算:β(move_ame),β(director)和 [β(cite)]。
通过计算有:β(move_name)=move_name(<value;varchar;””>);
β(director)=director(fn(<value;varchar;””>),ln(<value;varchar;””>);
[β(cite)]的值为 [cite({[β(move)]})]。
则β(move)=move(move_name(<value;varchar;””>),director(fn(<value;varchar;””>), ln(<value;varchar;””>), [cite({β(move)})])。
为了创建move的对象属性,我们分别对move_name(<value;varchar;””>,director(fn(<value;varchar;””>), ln(<value;varchar;””>),[cite({β(move)})]进行转换。
首先对 [cite({β(move)})]进行转换,为了去掉”{”和”}”,使用步骤(2),可得:{β(move)}通过<”moves”;moves;””>替换掉,然后我们得到表 达 式 [cite(<”moves”;moves;null_constrant>)];为了去掉”[”和”]”,使用步骤(3),可得:(cite(<”moves”;moves;null_constrant>);通过步骤(4)可得:<”cite”;cite;null_constraint>。
其次对move_name(<value;varchar;””>)进行转换,使用步骤(5),可得对象属性为:(move_name(<value;varchar;””>), 通 过 步 骤(4) 可 得 <”move_name”;move_name;””>。
接 下 来 对 director(fn(<value;varchar;””>),ln(<value;varchar;””>) 进 行 转 换, 由 表 达 式可 知 director属 x(y(<value;varchar;””>),f(<value;varchar;””>),..)模型,通过步骤(6)可得:(director(<”fn”;fn;””>, <”ln”;ln;””>)),通过步骤(4)可得:<”director”;director;””>。
最后,我们可得move表达式为:move(<”move_name”;move_name;””>,<”director”;-directoe;””>,<”cite”;cite;null_constraint>);对象属性表达式为:<”move”;move;constraint_on(cite)>。
与XML schema关联的对象类型创建方法具体如下所示:
设y是一个对象属性,通过对象属性的创建可知y的表达式为:〈”object”;object;constraints〉;然后将其返回〈object;constraints〉(一个伴有约束的对象类型)。
通过上诉方法我们可得〈”moeve”;move;constraint_on(cite)〉的对象类型为:〈move;constraint_on(cite)〉。
最终转换算法如下所示(见图4):
(1)开始;
(2)输入XML文档,A是XML中的元素;
(3)通过β(G)计算元素A的值;
(4)通过对象属性创建函数计算元素A的对象属性;
(5)通过与XML schema关联的对象类型创建方法计算元素A的对象类型;
(6)创建一个对象列表,命名为:“A_table”,此列表伴有对象类型A和约束(列表“A_table”是用来存储XML文档内容的);
(7)输出对象关系模式;
(8)结束。
图4 转换算法流程
基于对象类型move,我们创建一个名为Move_table的表,具体如图5所示。
图5 Move_table结构
图5 中:(1)id表 示 一 个 数 量 属 性;(2)move_name表示一个具有名的属性对象;(3)directors表示每个元素具有fn和ln属性对象;(4)cite表示“move”对类型应用的集合。
在这篇文章里介绍了一种将XML模式转换为对象关系模式的方法,同时也可以将对象关系模型转化为XML模型。该方法在处理XML数据的时候可以保护其数据结构,同时也提供一些语义约束;该方法与其他方法相比较,在整合XML元素的时候仅需较少的对象列表。