基于模型映射方法实现XML与关系数据的相互转换
2014-09-24张屹
张屹
摘 要:基于模型映射方法可以独立于XML文档的DTD或Schema,在关系型数据库中设计固定的关系模式用于存储XML文档。采用Dietz编码方法对XML文档中的元素进行编码,通过编码值对反应元素之间的祖先/后裔关系,并在关系表中存储元素的Dietz编码值,并依此作为依据设计算法将存储于关系数据库中的XML文档进行还原。
关键词:模型映射;关系数据库;XML;Dietz编码
中图分类号:TP311.1 文献标识码:A
Implementation of Mutual Conversion Between XML and RDBMS
Based on Model Mapping Method
ZHANG Yi
(Library of Tianjin Medical University,Tianjin 30070,China)
Abstract:Model-based mapping method can be independent of the XML document DTD or Schema.This paper design a fixed relational pattern in order to store XML documents based on model mapping method.Firstly elements in XML are encoded by Dietz coding method.The pair of encoded value expressed ancestor/descendant relationships of elements.RDBMS stores these values.Algorithm can restore XML documents which store in RDBMS based on Dietz coding values.
Keywords:model mapping;RDBMS;XML;dietz encoding method
1 引言(Introduction)
可扩展的标识语言XML(Extensible Markup Language)与传统的关系数据明显不同,SQL Server、Oracle等数据库管理系统为关系数据提供了数据存储、查询以及分析这些功能支持,而XML仅用于存储数据。XML是一种半结构化数据,由于其自身结构特点导致对于XML数据不能方便的进行数据查询和更新操作,如何有效的对XML进行查询和存储成为XML研究领域的重要研究方向。
关系数据库技术是目前应用最为广泛且技术成熟的数据存储和处理技术,它为数据提供了数据定义、数据操纵以及完整性约束的支持,因此使用关系表存储XML文档是一种较为理想的解决方案。关系表是一种二维表结构,而XML文档是树形结构,两者在数据结构上存在差异,如何实现这两种数据结构的相互转化是目前相关研究工作的热点,本文提出了独立于XML文档DTD或Schema的模型映射存储方法,采用固定的关系模式存储XML文档并且保存文档中元素结点的编码值。
2 相关研究(Related works)
相关研究成果将XML映射为关系模式进行存储分为两类方法:模型映射(Model-Mapping)和结构映射(Structure-Mapping)[1]。结构映射方法中,需要将XML Schema(或DTD)映射为关系模式,再将XML文档存储在相应的关系模式中,文献[2-4]介绍了如何根据XML文档DTD或模式映射为关系模式存储XML。使用结构映射方法,关系表之间的参照完整性关系可以反映元素之间的祖先/后裔关系,通过关系表之间的连接操作可以将关系数据还原为原先的XML文档。由于关系模式依赖于XML文档的结构,映射的关系模式依照XML文档结构的变化而发生变化。模型映射方法独立于XML文档的结构,Xpev[5]系统是一种典型的模型映射方法。采用固定的关系模式存储XML,但是缺点在于由于使用不同的关系表存储XML文档树不同类型的结点就无法反应文档中元素之间的祖先/后裔关系,进而无法将存储好的文档进行还原。
3 关系数据库存储和还原XML文档(Store/restore
XML in RDBMS)
3.1 Dietz编码标记XML文档元素
本文所提出的方法是一种模型映射方法,与以往的研究成果相比有点在于:(1)采用固定的关系模式存储XML文档,不依赖于文档结构,能够存储不同结构的XML;(2)使用Dietz编码[6]这种区间编码方式对XML文档中元素进行编码并存储,在关系表中也能反应所存储元素的祖先/后裔关系;(3)通过关系表保存的区间编码所反映元素之间的祖先/后裔关系可以将关系数据还原为XML文档,克服了以往模型映射方法所存储XML文档无法进行还原的问题。
定义1 XML文档表示为树型结构,文档树中的每个元素结点被赋予一个二元组
编码值对,分别代表元素先序遍历和后序遍历值。由于文档树的每个元素结点u在先序遍历(后序遍历)序号中必然出现在它的后裔元素结点v之前(之后),因此,元素u和v之间是祖先/后裔关系,当且仅当pre(u)图1 XML文档示例
Fig.1 XML document demo.
图2 XML文档元素Dietz编码
Fig.2 Encoding elements in XML by Dietz method
3.2 关系数据库存储XML文档
设计固定结构关系模式即采用模型映射方法来存储 XML 文档。本文根据XPath数据模型和XML文档的编码方法设计出一种全新的模型映射方法。
表Document存储的是数据库中需要保存的XML文档的文件名。表Element、Attribute和Text分别保存的是数据库当前存储XML文档元素、属性、文本这三种类型的结点。属性ElementPre和ElementPost用于表示元素的Dietz编码值对,由于XML文档中元素至多有一个父元素,因此属性ParentPre表示当前元素父元素的先序编码。表Element中属性TagName表示元素标记名。表Attribute和表Text同样还要要保存当前元素的属性名、属性值以及元素文本内容。
图3 存储XML文档的关系模式
Fig.3 Relational pattern of storing XML
算法1:关系数据库存储XML文档
输入:XML文档
StoreXMLDoc(XMLDoc)//该函数用来描述存储XML文档的算法
① 获取XML文档或文档片段根元素getRootElement(XMLDoc);
② 对当前元素进行Dietz编码DietzEncode(RootElement);
③ 判断当前结点是否包含子结点
if(RootElement.haschild){
if(child instance of Text)// 如果为Text,在表Text保存该结点以及当前元素Dietz编码值
else if(child instance of Attribute)// 子节点类型如果为Attribute,在表Attribute保存该结点以及当前元素Dietz编码值
else StoreXMLDoc(Element)//子结点类型如果为Element,以当前元素的子元素为参数递归调用函数StoreXMLDoc()
}
else
InsertElement(EncodePair, Element); //如当前元素无子结点,在表Element中保存该元素以及该元素的Dietz编码值对
3.3 关系数据还原为XML文档
关系模式中存储了当前元素及其父元素的Dietz编码值,两组编码值之间通过参照完整性关系来反映元素结点之间的父子关系。首先构造XML文档根元素结点,再根据当前元素结点的先序编码在Element表中查找属性ParentPre取值与之相对应的元组,将这些元组构造为已构造好元素的子元素,递归的执行以上过程直到无法继续构造出子元素为止。这种方法能够使还原出来的XML文档与原文档一致。
算法2:关系数据库还原XML文档
输入:关系数据
输出:XML文档
ConstructXMLDoc()//还原XML文档{
RootElement = new Element(TagName);//当前元组属性TagName的取值,构造XML文档根元素
XMLDocument = new Document(RootElement);//根据该根元素构造XML文档
ConstructAttribute(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的属性
ConstructText(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的文本
ChildElementList=RootElement.getElementPre();//查找以根元素为父元素的元组集合
for(i=0;i ChildElement=new Element(ChildElementList.get(i).getTagName()); ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); ChildElementSet=RecursiveConstruct(ChildElement);//当前元组为参数调用递归函数RecursiveConstruct(),构造当前元素的子元素集 XMLDocument.getRootElement().addContent(ChildElement);//将构造的元素集添加为当前元素的子元素,形成XML文档 } Output(XMLDocument);//输出XML文档; } Element RecursiveConstruct(CurrentElement){ //递归函数是用来构造当前元素的子元素 ChildElementList(CurrentElement.getElementPre()); for(i=0;i< ChildElementList.size();i++){ ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); CurrentElement.addContent(RecursiveConstruct(ChildElementList.get(i)));//递归调用RecursiveConstruct()将构造的元素集添加为当前元素的子元素 } 4 结论(Conclusion) 文章所提出的方法独立于文档结构采用固定关系模式存储XML文档,同时克服以往模型映射方法中无法还原出所存储的XML文档的缺点。通过在关系模式中存储元素的Dietz编码值对形成的参照完整性关系来反映元素之间的父子关系。通过关系表之间的连接操作能够将存储在关系数据库中的XML文档还原出来。 参考文献(References) [1] 万常选,刘云生.基于关系数据库的XML数据管理[J].计算机 科学,2003,30(8):64-68. [2] 周傲英,等.基于关系的XML数据存储[J].计算机应用,2000, 20(9):9-12. [3] 杨健,雄前心.XML文档架构与关系数据模型间的映射研究 [J].计算机工程与应用,2004,40(27):169-172. [4] 刘伟.基于schema的XML模式与关系模式映射算法的研究[J]. 计算机应用与软件,2006,23:113-115. [5] 秦杰,杨树强,窦文华.一种基于模型映射的XML文档存储模 型[J].计算机工程与科学,2005,27(11):12-14. [6] Dietz P F. Maintaining Order in a Linked List [C].In: Lewis H Retal Eds. Proceedings of the 14th Annual ACM Symposium on Theory of Computing (STOC'82).San Francisco,California, USA. May 5-7,1982.New York: ACM Press,1982:122-127. 作者简介: 张 屹(1983-),男,硕士,助理工程师.研究领域:软件 工程.
表Document存储的是数据库中需要保存的XML文档的文件名。表Element、Attribute和Text分别保存的是数据库当前存储XML文档元素、属性、文本这三种类型的结点。属性ElementPre和ElementPost用于表示元素的Dietz编码值对,由于XML文档中元素至多有一个父元素,因此属性ParentPre表示当前元素父元素的先序编码。表Element中属性TagName表示元素标记名。表Attribute和表Text同样还要要保存当前元素的属性名、属性值以及元素文本内容。
图3 存储XML文档的关系模式
Fig.3 Relational pattern of storing XML
算法1:关系数据库存储XML文档
输入:XML文档
StoreXMLDoc(XMLDoc)//该函数用来描述存储XML文档的算法
① 获取XML文档或文档片段根元素getRootElement(XMLDoc);
② 对当前元素进行Dietz编码DietzEncode(RootElement);
③ 判断当前结点是否包含子结点
if(RootElement.haschild){
if(child instance of Text)// 如果为Text,在表Text保存该结点以及当前元素Dietz编码值
else if(child instance of Attribute)// 子节点类型如果为Attribute,在表Attribute保存该结点以及当前元素Dietz编码值
else StoreXMLDoc(Element)//子结点类型如果为Element,以当前元素的子元素为参数递归调用函数StoreXMLDoc()
}
else
InsertElement(EncodePair, Element); //如当前元素无子结点,在表Element中保存该元素以及该元素的Dietz编码值对
3.3 关系数据还原为XML文档
关系模式中存储了当前元素及其父元素的Dietz编码值,两组编码值之间通过参照完整性关系来反映元素结点之间的父子关系。首先构造XML文档根元素结点,再根据当前元素结点的先序编码在Element表中查找属性ParentPre取值与之相对应的元组,将这些元组构造为已构造好元素的子元素,递归的执行以上过程直到无法继续构造出子元素为止。这种方法能够使还原出来的XML文档与原文档一致。
算法2:关系数据库还原XML文档
输入:关系数据
输出:XML文档
ConstructXMLDoc()//还原XML文档{
RootElement = new Element(TagName);//当前元组属性TagName的取值,构造XML文档根元素
XMLDocument = new Document(RootElement);//根据该根元素构造XML文档
ConstructAttribute(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的属性
ConstructText(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的文本
ChildElementList=RootElement.getElementPre();//查找以根元素为父元素的元组集合
for(i=0;i ChildElement=new Element(ChildElementList.get(i).getTagName()); ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); ChildElementSet=RecursiveConstruct(ChildElement);//当前元组为参数调用递归函数RecursiveConstruct(),构造当前元素的子元素集 XMLDocument.getRootElement().addContent(ChildElement);//将构造的元素集添加为当前元素的子元素,形成XML文档 } Output(XMLDocument);//输出XML文档; } Element RecursiveConstruct(CurrentElement){ //递归函数是用来构造当前元素的子元素 ChildElementList(CurrentElement.getElementPre()); for(i=0;i< ChildElementList.size();i++){ ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); CurrentElement.addContent(RecursiveConstruct(ChildElementList.get(i)));//递归调用RecursiveConstruct()将构造的元素集添加为当前元素的子元素 } 4 结论(Conclusion) 文章所提出的方法独立于文档结构采用固定关系模式存储XML文档,同时克服以往模型映射方法中无法还原出所存储的XML文档的缺点。通过在关系模式中存储元素的Dietz编码值对形成的参照完整性关系来反映元素之间的父子关系。通过关系表之间的连接操作能够将存储在关系数据库中的XML文档还原出来。 参考文献(References) [1] 万常选,刘云生.基于关系数据库的XML数据管理[J].计算机 科学,2003,30(8):64-68. [2] 周傲英,等.基于关系的XML数据存储[J].计算机应用,2000, 20(9):9-12. [3] 杨健,雄前心.XML文档架构与关系数据模型间的映射研究 [J].计算机工程与应用,2004,40(27):169-172. [4] 刘伟.基于schema的XML模式与关系模式映射算法的研究[J]. 计算机应用与软件,2006,23:113-115. [5] 秦杰,杨树强,窦文华.一种基于模型映射的XML文档存储模 型[J].计算机工程与科学,2005,27(11):12-14. [6] Dietz P F. Maintaining Order in a Linked List [C].In: Lewis H Retal Eds. Proceedings of the 14th Annual ACM Symposium on Theory of Computing (STOC'82).San Francisco,California, USA. May 5-7,1982.New York: ACM Press,1982:122-127. 作者简介: 张 屹(1983-),男,硕士,助理工程师.研究领域:软件 工程.
表Document存储的是数据库中需要保存的XML文档的文件名。表Element、Attribute和Text分别保存的是数据库当前存储XML文档元素、属性、文本这三种类型的结点。属性ElementPre和ElementPost用于表示元素的Dietz编码值对,由于XML文档中元素至多有一个父元素,因此属性ParentPre表示当前元素父元素的先序编码。表Element中属性TagName表示元素标记名。表Attribute和表Text同样还要要保存当前元素的属性名、属性值以及元素文本内容。
图3 存储XML文档的关系模式
Fig.3 Relational pattern of storing XML
算法1:关系数据库存储XML文档
输入:XML文档
StoreXMLDoc(XMLDoc)//该函数用来描述存储XML文档的算法
① 获取XML文档或文档片段根元素getRootElement(XMLDoc);
② 对当前元素进行Dietz编码DietzEncode(RootElement);
③ 判断当前结点是否包含子结点
if(RootElement.haschild){
if(child instance of Text)// 如果为Text,在表Text保存该结点以及当前元素Dietz编码值
else if(child instance of Attribute)// 子节点类型如果为Attribute,在表Attribute保存该结点以及当前元素Dietz编码值
else StoreXMLDoc(Element)//子结点类型如果为Element,以当前元素的子元素为参数递归调用函数StoreXMLDoc()
}
else
InsertElement(EncodePair, Element); //如当前元素无子结点,在表Element中保存该元素以及该元素的Dietz编码值对
3.3 关系数据还原为XML文档
关系模式中存储了当前元素及其父元素的Dietz编码值,两组编码值之间通过参照完整性关系来反映元素结点之间的父子关系。首先构造XML文档根元素结点,再根据当前元素结点的先序编码在Element表中查找属性ParentPre取值与之相对应的元组,将这些元组构造为已构造好元素的子元素,递归的执行以上过程直到无法继续构造出子元素为止。这种方法能够使还原出来的XML文档与原文档一致。
算法2:关系数据库还原XML文档
输入:关系数据
输出:XML文档
ConstructXMLDoc()//还原XML文档{
RootElement = new Element(TagName);//当前元组属性TagName的取值,构造XML文档根元素
XMLDocument = new Document(RootElement);//根据该根元素构造XML文档
ConstructAttribute(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的属性
ConstructText(ElementPre);//根据当前元组属性ElementPre的取值,构造当前根元素的文本
ChildElementList=RootElement.getElementPre();//查找以根元素为父元素的元组集合
for(i=0;i ChildElement=new Element(ChildElementList.get(i).getTagName()); ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); ChildElementSet=RecursiveConstruct(ChildElement);//当前元组为参数调用递归函数RecursiveConstruct(),构造当前元素的子元素集 XMLDocument.getRootElement().addContent(ChildElement);//将构造的元素集添加为当前元素的子元素,形成XML文档 } Output(XMLDocument);//输出XML文档; } Element RecursiveConstruct(CurrentElement){ //递归函数是用来构造当前元素的子元素 ChildElementList(CurrentElement.getElementPre()); for(i=0;i< ChildElementList.size();i++){ ConstructAttribute(ChildElementList.get(i).getElementPre()); ConstructText(ChildElementList.get(i).getElementPre()); CurrentElement.addContent(RecursiveConstruct(ChildElementList.get(i)));//递归调用RecursiveConstruct()将构造的元素集添加为当前元素的子元素 } 4 结论(Conclusion) 文章所提出的方法独立于文档结构采用固定关系模式存储XML文档,同时克服以往模型映射方法中无法还原出所存储的XML文档的缺点。通过在关系模式中存储元素的Dietz编码值对形成的参照完整性关系来反映元素之间的父子关系。通过关系表之间的连接操作能够将存储在关系数据库中的XML文档还原出来。 参考文献(References) [1] 万常选,刘云生.基于关系数据库的XML数据管理[J].计算机 科学,2003,30(8):64-68. [2] 周傲英,等.基于关系的XML数据存储[J].计算机应用,2000, 20(9):9-12. [3] 杨健,雄前心.XML文档架构与关系数据模型间的映射研究 [J].计算机工程与应用,2004,40(27):169-172. [4] 刘伟.基于schema的XML模式与关系模式映射算法的研究[J]. 计算机应用与软件,2006,23:113-115. [5] 秦杰,杨树强,窦文华.一种基于模型映射的XML文档存储模 型[J].计算机工程与科学,2005,27(11):12-14. [6] Dietz P F. Maintaining Order in a Linked List [C].In: Lewis H Retal Eds. Proceedings of the 14th Annual ACM Symposium on Theory of Computing (STOC'82).San Francisco,California, USA. May 5-7,1982.New York: ACM Press,1982:122-127. 作者简介: 张 屹(1983-),男,硕士,助理工程师.研究领域:软件 工程.