分享
 
 
 

XML编程思想:将文件合并到RDF模型和基本的RDF查询

王朝other·作者佚名  2008-05-21
窄屏简体版  字體: |||超大  

这篇“Thinking XML”专栏文章演示了如何将从多个 XML 源文档中收集的元数据合并到用于有效查询的单个“资源描述框架”(Resource Description Frame (RDF))模型中。专栏作家 Uche Ogbuji 在前一篇中介绍了如何一起使用 XML 和 RDF 来进行知识管理,本文是上一篇的继续,在本文中他论述了基于用从现有的 XML 格式获取的数据组成 RDF 模型的技术。该文的中心是一个示例,在该示例中,扩展基于 Web 的问题跟踪器(最初开发它来操纵 XML 格式的应用程序数据)来利用 RDF。XSLT 和 Python 样本代码清单演示了将来自 XML 文件的元数据聚合到单个 RDF 模型(一个使用 XSLT ,另一个使用 RDF)以及简单 RDF 查询的示例。

在本专栏的前一篇文章中,即 知识管理的基本 XML 和 RDF 技术,第一部分(在继续阅读之前,可能需要重新回顾一下),介绍了一个基于收集的数据(以 XML 格式表示)的问题跟踪器应用程序示例。然后演示了如何使用 XSLT 从应用程序数据中抽取 RDF。

本专栏文章通过演示如何组合由转换每个 XML 源文档所创建的离散的 RDF 片段来完成这些事情。同时还演示了一些基本的查询技术。

资源批量派生

在上篇专栏文章中,完成了一个从 XML 源文件中抽取作为序列化格式的 RDF 的练习。然而,知识管理的大多数有用之处在于操纵 RDF 语句的抽象模型,而不是个别序列化文件。RDF 模型是图形结构,该结构可以非常简单也可以令人难以置信的复杂。(事实上,极端情况下,Semantic Web 的设想是要创建至少同当前 Web 一样大的 RDF 模型。如果实现该模型的话,它可能是曾经在使用中的最大的计算机数据结构。)

迄今为止,问题跟踪器的示例是由一组 XML 文件组成的,这些文件是 RDF 模型各部分的序列化。每一部分就象七巧板中的一块,如果将它们组合到一块儿,将表示问题跟踪器应用程序中所有数据的 RDF 模型。每一部分本身并不十分重要,因此下一步来讨论如何创建一幅完整的“图画”,该“图画”才是知识管理的真正价值所在。

使用 XSLT 进行批量转换

拼装该“图画”的一种选择是根本不处理七巧板块,而是使用 XSLT 一劳永逸地生成该“图画”。可以编写一个转换,该转换收集每个 XML 问题文档,并运用前一篇文章中所描述的 RDF 转换处理,然后将每次转换结果累积到一个序列化 RDF 结果。要做到这一点,需要利用标准的 document() XSLT 函数,该函数可以读入任意的文档,这些文档是作为用于转换的补充性 XML 源文档。

document() 函数需要知道所要读入文档的准确名称。XSLT 没有(比如说)通过使用通配符来读入多个文档的标准机制。可以通过许多方法解决这一问题(包括借助于 XSLT 扩展,该扩展允许通过通配符或其它机制来批量装入文档)。然而,因为这不是本示例的中心问题,所以选择创建带有每个问题文档清单的集中(hub) XSLT 文档这项折中方案。清单 1 issue-hub.xml 用指定的两个问题文档(在前一篇专栏文章中介绍过)来演示集中文档是什么样子的。

清单 1:带有每个应用程序数据文档的问题文档清单的集中 XML 文档。

issue1.xml

issue2.xml

一旦有了集中文档,就可以将 清单 2metadata-batch.xslt 中的转换应用到作为源文档的集中文档中以从所有列出的问题中创建聚合 RDF。

清单 2 看起来可能非常熟悉;其中大多数同前一篇文章中的转换相同。这是因为我很留意 XML 结构的模块化处理。根模板现在从集中文档中查找每个 issue 元素(注意,这里使用空名称空间)。然后它从每个元素内容中指定的文件名装入文档。注意,这里使用 document(.)/* 而不仅仅是 document(.) 。这种构造防止处理器匹配问题文档的根节点,这会结束调用打算用于集中文档根节点的模板。那些正是本专栏文章的批量转换中的唯一区别。

可以使用任何 XSLT 处理器来执行该转换。我使用 4XSLT 来执行转换,如下所示:$ 4xslt -o issues.rdf issue-hub.xml metadata-batch.xslt

该转换导致 issues.rdf 中的序列化 RDF,它包含来自 issue1.xml 和 issue2.xml 中的元数据。

使用 RDF 工具进行批量转换

将多个 XML 文档聚合到单个 RDF 模型中的另一种选择是(如前一篇文章所述)分别构建每个 RDF 文档,然后使用 RDF 解析器将所有的文档解析成单个抽象模型。例如,通过对从前面一篇专栏文章中的示例问题文件中生成的两个 RDF 文件使用 4RDF,将得到清单 3。

清单 3:从 XML 文件中派生,并由 RDF 解析器(这里是 4RDF)分析的两个 RDF 问题文件的批量转换结果

$ 4rdf -d 1.rdf 2.rdfThe following is a list of resulting tuples, each in the form "subject,predicate, object".[("http://meta.rdfinference.org/ril/issue-tracker/ril-20010502","http://xmlns.rdfinference.org/ril/issue-tracker#issue","#i2001030423"),("#anonymous:e08-e06-30b-90d-a060005104", "id", "i2001030423"),("#anonymous:e08-e06-30b-90d-a060005104","http://xmlns.rdfinference.org/ril/issue-tracker#author","http://users.rdfinference.org/ril/issue-tracker#uogbuji"),("#anonymous:1040d07-20b-909-407-b0e0402205","http://xmlns.rdfinference.org/ril/issue-tracker#author", "AlexandreFayolle "),("#anonymous:1040d07-20b-909-407-b0e0402205","http://xmlns.rdfinference.org/ril/issue-tracker#body", "Theabbreviation in listing 8 doesn't seem necessary to Nico Chauvat orme."),("#anonymous:e08-e06-30b-90d-a060005104","http://xmlns.rdfinference.org/ril/issue-tracker#comment","#anonymous:1040d07-20b-909-407-b0e0402205"),("#anonymous:60e0b06-50a-80c-90c-50a0a08602","http://xmlns.rdfinference.org/ril/issue-tracker#author","http://users.rdfinference.org/ril/issue-tracker#uogbuji"),("#anonymous:60e0b06-50a-80c-90c-50a0a08602","http://xmlns.rdfinference.org/ril/issue-tracker#assignment","http://users.rdfinference.org/ril/issue-tracker#uogbuji"),("#anonymous:e08-e06-30b-90d-a060005104","http://xmlns.rdfinference.org/ril/issue-tracker#action","#anonymous:60e0b06-50a-80c-90c-50a0a08602"),("http://meta.rdfinference.org/ril/issue-tracker/ril-20010502","http://xmlns.rdfinference.org/ril/issue-tracker#issue","#i2001042003"),("#anonymous:2030002-506-10a-201-f090809c08", "id", "i2001042003"),("#anonymous:2030002-506-10a-201-f090809c08","http://xmlns.rdfinference.org/ril/issue-tracker#author","http://users.rdfinference.org/ril/issue-tracker#nchauvat"),("#anonymous:c000706-b0b-d02-d0a-e050c0460b","http://xmlns.rdfinference.org/ril/issue-tracker#author", "AlexandreFayolle "),("#anonymous:c000706-b0b-d02-d0a-e050c0460b","http://xmlns.rdfinference.org/ril/issue-tracker#body", "I agree"),("#anonymous:2030002-506-10a-201-f090809c08","http://xmlns.rdfinference.org/ril/issue-tracker#comment","#anonymous:c000706-b0b-d02-d0a-e050c0460b"),("#anonymous:b0c0c00-800-2-c08-20a0d0f209","http://xmlns.rdfinference.org/ril/issue-tracker#author","http://users.rdfinference.org/ril/issue-tracker#uogbuji"),("#anonymous:b0c0c00-800-2-c08-20a0d0f209","http://xmlns.rdfinference.org/ril/issue-tracker#assignment","http://users.rdfinference.org/ril/issue-tracker#uogbuji"),("#anonymous:2030002-506-10a-201-f090809c08","http://xmlns.rdfinference.org/ril/issue-tracker#action","#anonymous:b0c0c00-800-2-c08-20a0d0f209"),]

清单 3 中第一行里的 -d 选项告诉 $RDF 将 subject/predicate/object 三元组从抽象 RDF 模型转储到命令行,该命令行显示清单 3 的剩余部分.

一旦有了问题跟踪器的完整 RDF 模型,可能希望以一种更易于阅读的格式而不是清单 3 中所显示的那种格式来查看它。例如,如果以清单 3 中的聚合 RDF 文件为例,并使用 Dan Brickley 的 RDF 可视化工具(请参阅 参考资料)来处理它,将得到一幅类似 图 1的图表。对于一般的膝上电脑屏幕来说,它可能太宽,因此请单击链接在单独的窗口中打开图表。

图 1 中的可视化显示的好处在于:可以立即辨别出某种模式,譬如用户“uogbuji”的投稿和职责。当然,我必须承认 RDF 中随同 URI 而来的冗长的标识符妨碍了这一清晰性。

跨系统查询

拥有可用元数据的 RDF 模型的另外一个立杆见影的好处在于:它使许多系统级查询(相对于编写针对一组 XML 文档的 XPath 查询,或将数据集中到专用数据结构以用于查询)变得更简单更一般。虽然,“XML 查询语言”(XQuery)和 XML 资源库供应商提供的专用文档收集查询工具的出现也帮助解决了这一需求,但是现在可以使用 RDF,至少这种基本模型是标准化的。

遗憾的是,RDF 模型的查询还不是标准化的,这是 RDF 社区需要填补的非常重要的漏洞。幸运的是,由于 RDF 模型的简单性,所以非常容易通过基本模式匹配来构建几乎所有形式的查询。这是 4RDF 中所使用的基本方法,其中,查询就是就是查找语句三元组的过程,该三元组匹配给定的主语、谓语和宾语模式。作为示例,请看表 1 中刚创建的部分统一模型。

表 1 .来自问题跟踪器数据的一些语句

主语: #anonymous:a0d010d-f0c-706-20e-80a0407606谓语: http://xmlns.rdfinference.org/ril/issue-tracker#body宾语: Organize a vote on this topic主语: #anonymous:a0d010d-f0c-706-20e-80a0407606谓语: http://xmlns.rdfinference.org/ril/issue-tracker#assign-to宾语: http://users.rdfinference.org/ril/issue-tracker#uogbuji主语: #anonymous:402000d-403-309-c01-9080a205谓语: http://xmlns.rdfinference.org/ril/issue-tracker#body宾语: Correct all to use the "0/1" form in the next draft.主语: #anonymous:402000d-403-309-c01-9080a205谓语: http://xmlns.rdfinference.org/ril/issue-tracker#assign-to宾语: http://users.rdfinference.org/ril/issue-tracker#uogbuji

有了这些三元组,就会非常容易地明白别人是如何会简单地询问如下问题:“给用户 uogbuji 分配的操作标识是什么?”以及“每个操作的主体是什么?”。将第一个问题转换成查找匹配下列模式的三元组,这里的“*”是匹配任何值的通配符:

主语 谓语 宾语 *http://xmlns.rdfinference.org/ril/issue-tracker#assign-tohttp://users.rdfinference.org/ril/issue-tracker#uogbuji

对此的响应之一是带有主语“#anonymous:a0d010d-f0c-706-20e-80a0407606”(表示匹配的操作标识)的语句。注意,该标识是由 4RDF 为匿名资源(如果资源没有标识,则由应用程序显式地分配一个)生成的特殊标识。构成全球唯一标识符(UUID)的一个十六进制值紧跟在“anonymous”序列之后。有了这个标识,第二个示例问题相当于匹配下列模式,该模式返回带有宾语“Organize a vote on this topic”的语句:

主语 谓语 宾语 #anonymous:a0d010d-f0c-706-20e-80a0407606http://xmlns.rdfinference.org/ril/issue-tracker#body*

建立在这一简单的想法上,几乎任何形式的 RDF 查询(甚至关系型(SQL)查询和对象(OQL)查询的等价查询)都是可能的。

编码 RDF 查询

清单 4 中的 Python 程序 query1.py 通过模式匹配、读入 issues.rdf 文件以及打印 uogbuji 的所有任务的主体,使用 4RDF 来运用这项查询技术。(如果没有使用 Python,当然可以使用其它 RDF 查询工具,譬如 RDFDb、Jena 或列在 参考资料中“Dave Beckett 的 RDF 资源指南”中的工具。)

清单 4:演示一个 RDF 模型简单查询的 Python 程序。

from Ft.Rdf import Util#Returns an RDF model object, and the database instance it uses for#persistence (in our case, it's just a memory data structure)model, db = Util.DeserializeFromUri('issues.rdf')db.begin()USER_ID_BASE = 'http://users.rdfinference.org/ril/issue-tracker#'IT_SCHEMA_BASE = 'http://xmlns.rdfinference.org/ril/issue-tracker#'print 'Actions assigned to uogbuji:'#None is used as the wild-cardmatching_statements = model.complete(None,

IT_SCHEMA_BASE+'assign-to',

USER_ID_BASE+'uogbuji'

)for statement in matching_statements:

id = statement.subject

matching_statements = model.complete(id,

IT_SCHEMA_BASE+'body',

None

)

body = matching_statements[0].object

print "*", bodydb.commit()

在清单 4 中,首先从 issues.rdf 文件中读取(解除序列化)RDF;然后执行查询以查找表示指派给 uogbuji 哪些操作的语句。然后使用每个语句的主语(操作标识)来查询每个操作的主体。如果安装了 Python 和 4Suite,运行和下面相同的示例:

$ python query1.pyActions assigned to uogbuji* Organize a vote on this topic* Correct all to use the "0/1" form in the next draft.

这是 RDF 模型查询的最底级别,因此有一点麻烦。清单 5 中的 Python 程序 query2.py 通过直接查询相关主语和宾语等而走了一些捷径。其结果就是清单 4 中同一个功能的更简单的版本。

清单 5:简化查询代码

from Ft.Rdf import Util#Returns an RDF model object, and the database instance it uses for#persistence (in our case, it's just a memory data structure)model, db = Util.DeserializeFromUri('issues.rdf')db.begin()USER_ID_BASE = 'http://users.rdfinference.org/ril/issue-tracker#'IT_SCHEMA_BASE = 'http://xmlns.rdfinference.org/ril/issue-tracker#'print 'Actions assigned to uogbuji:'actions = Util.GetSubjects(model, IT_SCHEMA_BASE+'assign-to',

USER_ID_BASE+'uogbuji')for action in actions:

body = Util.GetObject(model, action, IT_SCHEMA_BASE+'body')

print "*", bodydb.commit()

清单 5 仍然包含两种级别的查询;使用结合多个查询的单个请求将更方便和更有效。(通过使用“RDF 推论语言(RDF Inference Language (RIL))”,那也是可能的,“RDF 推论语言”将在本专栏的后续文章中讨论。顺便提一下,示例问题跟踪器数据中参考了 RIL 开放规范草稿。)清单 6 演示了在使用或不使用 API 捷径情况下,执行基本查询的结果。

清单 6:执行同清单 5 相同任务的简化的查询会话

$ python query2.pyActions assigned to uogbuji* Organize a vote on this topic* Correct all to use the "0/1" form in the next draft.

RDF 查询不必涉及元数据语句组件的精确匹配。大多数的查询语言提供大量的灵活性。作为一个示例, 清单 7(query3.py)中的 Python 程序使用基于正则表达式的查询来查找所有指派给 uogbuji 的操作(该操作的主体包含字符串“vote”)。

同样,通过使用 RIL,清单 7 中的代码将是一个简单查询而且更有效(将在下一篇专栏文章里讲述)。清单 8 演示了查询中正则表达式的使用。

清单 8:演示在查询中使用正则表达式的会话

$ python query3.pyActions assigned to uogbuji* Organize a vote on this topic

下一次……

本专栏文章演示了如何从示例问题跟踪器应用程序将各部分组成完整的 RDF 模型,并且举例说明了该模型的基本查询。在下篇文章中将探讨一种丰富特性,可以利用 RDF 的强大功能来低成本地利用该特性。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有