核心语义 Web 技术就是 RDF,这是一种 W3C 标准,用于将所有数据缩减成三部分的语句,即三元组(triple)。如果您的数据满足三元组数据模型,并存储在一种叫做三元组仓库(triplestore)的专门数据库中,那么语义 Web 技术的优势会很显著。但是这并不表示,数据是更为传统的格式(比如关系数据库和电子表格),这种技术就毫无用处。有开源和商业工具可用于将这些格式的数据转换成三元组,从而让您可以轻松组合多个来源、不同格式的数据。如果您想要在异构源之间交叉引用,或者用另一个源的数据增强某个源的数据,那么到三元组的临时转换是进行特定数据集成的优秀方式。
随着越来越多的数据变得作为 Linked Data(参见 参考资料)公共可用,您可以使用这些数据来增强本地存储的数据,使之意义更丰富,也更有趣。作为一个例子,本文展示如何用公共可用的关于所列公司的数据来增强(虚假的)分析师买入/卖出/持有推荐的 Excel® 电子表格,做出一个更具吸引力、富有信息的报表。此应用程序的输入、输出和脚本都使用免费软件,可供 下载。
三元组的三个部分被正式称为主语(subject)、谓语(predicate)和宾语(object)。如果您来自比较传统的数据库背景,可能会把它们看作资源标识符、属性名称和属性值。例如,如果一个关系数据库或电子表格说雇员 94321 的雇佣日期是 2007-10-14,那么很容易表达为三元组。
三元组的主语和谓语必须表达为 URI,以便彻底明确,并且利用流行领域做这件事情的标准模式和最佳实践变得越来越成熟。由惟一标识符提供的额外上下文表示,指定三元组集合中数据结构的模式是可选的,尽管它对于添加可启用推理和约束检查的元数据很有用。当您认为组合多个关系数据集或 XML 数据集最困难的环节是链接它们模式的对应部分时,您可以看到,由于不需要 RDF 模式,使得组合多个 RDF 数据集更为简单 — 通常简单到只是连接文件。
要通过抽取数据子集、排序并重新排列数据而实现应用程序逻辑,关系数据库具有 SQL,XML 具有 XSLT 和 XQuery。RDF 具有用于查询三元组的对应 W3C SPARQL 标准,在您组合了一些三元组集合之后,此标准将尤其方便,正如您在本文中将会看到的一样。
图 1 展示了 analystRecs.xls Excel 文件(参见 下载)的前几行:
图 1. 用作输入数据的 Excel 电子表格的前几行
图 1 中的每一行数据由以下部分组成:
- 一个虚假的分析师姓名
- 一家公司的股票代号
- 公司名称
- 该公司股票的一个(随机的)买入/卖出/持有推荐
- 推荐的日期和时间
- 公司的分析通常由传统上由出版商用于测试布局外观的 "lorem ipsum" 文本组成
图 2 展示了电子表格中列出的第三家公司 (IBM) 的增强版本,正如它出现在最终报表中一样:
图 2. 最终报表的 IBM 数据增强版本
除了来自 Excel 文件的推荐、分析师姓名、公司分析和推荐日期之外,图 2 还包含报表生成脚本运行时的当前股票价格、去年的一些财务数据,以及公司的描述。股价数据来自免费的 finance.yahoo.com web 服务(它将数据返回为 CSV),而 2009 年的数据和公司描述来自 Wikipedia。
图 3 展示了从这些输入创建报表的应用程序的一般架构:
图 3. 应用程序的架构图
如 图 3 所示:
- 来自电子表格、Yahoo! web 服务和 Wikipedia 的数据被转换成 RDF。
- RDF 数据被 SPARQL 引擎分类、交叉引用和转换成 XML。
- XSLT 引擎将 XML 转换成 HTML 以产生最终的报表。
我使用了免费软件来实现这整个架构,用一个 10 行的(不计算空白和注释)批文件 build.bat 驱动整个过程。您也可以用商业工具(比如 TopQuadrant 的 TopBraid Composer)实现与此相同的架构,工具可以自动化几个开发步骤,从而需要更少的编码。但是比特定实现更为重要的是,您现在可以从日益增长的工具队伍中选择工具,为灵活而特别的、使用语义 Web 数据标准的数据集成实现架构。
我选择使用 Python 将 Excel 数据转换成 RDF。免费的 Lingfo Python 库完成了读取二进制 Excel 文件这项困难的工作,所以我只费很少的精力编写了一个简短的 Python 脚本,为读入的每个单元格产生 RDF 三元组。
finance.yahoo.com 网站提供一个 web 服务,当您使用正确的 URL 时,它会返回当前股票数据的逗号分隔列表。例如,以下 URL 检索关于 IBM、Nokia 和 Honda 的数据:
http://download.finance.yahoo.com/d/quotes.csv?f=sl1d1t1ohgv&e=.csv&s=IBM,NOK,HMC |
返回的数据为每个所请求的公司具有一行,具有由请求数据的 URL 中的 f= 参数指定的数据字段。
由于 web 服务完成了检索股票数据并存储在一个简单的数据结构中,所以我只需要将数据转换成 RDF。Perl 的内置 split() 函数使得分割分隔的文本很容易,所以我编写了一个简短的 Perl 脚本 yahooCSV2RDF.pl 来做这件事情。(我本应该使用 Python 来完成 CSV 到 RDF 的转换,但是我之前已经用 Perl 编写了太多类似的脚本,所以我知道能够很快翻版成这个 Perl 脚本。)该脚本的很大一部分逻辑是将日期和时间字段,比如 7/22/2010 和 4:00pm,组合成一种更加顺应 ISO 8601 的格式,比如 2010-07-22T16:00:00,这样的格式更容易在其他系统中分类和重用。
Wikipedia 数据的转换不需要我的额外工作。DBpedia 项目已经从您在 Wikipedia 页面右侧灰色矩形框中经常会看到的字段“信息框”数据创建并存储了 10 亿多个三元组。例如,如果查看 Nokia 的 Wikipedia 页面 (http://en.wikipedia.org/wiki/Nokia),您会看到信息框;如果查看 Nokia 的 DBpedia 页面 (http://dbpedia.org/page/Nokia),您会看到 Nokia 的信息框信息和更多信息,可以用 SPARQL 查询语言进行查询。
DBpedia 的网站包含一个页面,您可以在那里输入关于数据的 SPARQL 查询 (http://dbpedia.org/snorql/)。在那里输入以下查询,请求关于 Vodafone 的所有 DBpedia 三元组:
CONSTRUCT { <http://dbpedia.org/resource/Vodafone> ?p ?o }
WHERE { <http://dbpedia.org/resource/Vodafone> ?p ?o }
|
如果您将该查询存储在一个 URI 中(在做了适当的字符转义之后。字符转义是大多数编程语言中的一个函数调用),那么对于任何可以发送 URI 并检索结果的程序,您都可以使用该 URI 来检索 Vodafone 三元组。开源的 cURL 工具就是这样一个程序。例如,如果您在 Windows® 或 Linux® 命令行输入以下命令,那么 cURL 会下载 Google 首页的一份副本,并存储在 googleHomepage.html 文件中:
curl http://www.google.com > googleHomepage.html |
您可以从由批文件或 shell 脚本驱动的应用程序调用 cURL。要从 DBpedia 检索公司数据,build.bat 调用另一个批文件 getDbpediaData.bat,该文件中的每一行都调用 cURL 来检索特定公司的数据。作为参数提供给每个调用的 URL 包含 SPARQL CONSTRUCT 查询的一个已转义版本,类似于上面的那个查询。
收集了所有数据的 RDF 版本之后,我使用另一个 SPARQL 查询(参见 清单 1)来为最终的报表抽取数据:
清单 1. 为最终报表抽取数据的 SPARQL 查询
# PickDataForReport.spq: select data from the combination of RDF sources
# used to create the fake analyst report. Bob DuCharme 2010 no warrantee
# expressed or implied.
PREFIX fn: <http://www.w3.org/2005/xpath-functions#>
PREFIX xs: <http://www.w3.org/2001/XMLSchema#>
PREFIX ar: <http://www.snee.com/ns/analystRatings#>
PREFIX sq: <http://www.rdfdata.org/2009/12/stockquotes#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?tickerSymbol ?coName ?analyst ?description ?recommendation
?recDateTime ?lastPrice ?quoteDateTime ?dayHigh ?dayLow ?openingPrice
?volume ?revenue ?netIncome ?abstract
WHERE {
?analystData ar:analyst ?analyst ;
ar:company ?coName;
ar:description ?description ;
ar:tickersymbol ?tickerSymbol ;
ar:recommendation ?recommendation ;
ar:date-time ?recDateTime .
?quoteData sq:tickerSymbol ?tickerSymbol ;
sq:lastPrice ?lastPrice ;
sq:dateTime ?quoteDateTime ;
sq:dayHigh ?dayHigh ;
sq:dayLow ?dayLow ;
sq:lastPrice ?lastPrice ;
sq:openingPrice ?openingPrice ;
sq:volume ?volume .
# Next line is why we added language tags to coName: so we
# could compare it to ?dbURI rdfs:label properly.
?dbpURI rdfs:label ?coName .
?dbpURI <http://dbpedia.org/ontology/revenue> ?revenue .
OPTIONAL {
?dbpURI <http://dbpedia.org/ontology/netIncome> ?netIncome .
} .
OPTIONAL {
?dbpURI <http://dbpedia.org/ontology/abstract> ?abstract .
FILTER (lang(?abstract) = "en") .
} .
}
|
这个 SPARQL 查询包含一些逻辑用于识别来自各个文件的哪些数据组合到一起,但是这也相当简单。如果说查询看起来有点长,那只是因为它列出了很多要从中抽取数据的字段。
要运行这个本地 SPARQL 查询,我使用 arq 命令行工具,它是开源的基于 Java™ 的 Jena 框架(参见 参考资料)的一部分。调用 arq 的 build.bat 行为每个调用提供三种信息:
- 输入数据的源(本例中是多个源)
- SPARQL 查询运行的文件的名称
- 一个指示表明我想要结果为 SPARQL Query Results XML Format
结果保持到文件 reportData.xml 中。
命令使用 --data 开关来告诉 arq,哪个数据用作输入。尽管 图 3 中的架构图展示了来自三个源的数据组合到一起,但是我不需要使用特殊的工具来组合它们。批文件只将 4 个这样的 --data 参数添加到调用 arq 的命令行(第四个是应用程序为容易交叉引用而创建的公司名称文件)。清单 2 展示了批文件的这一行,由于版面原因,这里拆成了三行,当用各种参数调用 Java 程序时,结果被重定向到 reportData.xml 文件:
清单 2.
arq 命令指定数据源、SPARQL 查询的位置和结果格式java -cp %CP% arq.arq --results=XML --query=PickDataForReport.spq --data=analystRecs.rdf --data=coNamesWithLangTags.n3 --data=quoteData.rdf --data=dbpedia.n3 > reportData.xml |
何谓 SPARQL Query Results XML Format?大多数 SPARQL 讨论关注的是查询语言和其名称中的 Q 和 P 所代表的协议。Query Results XML Format 是一个单独的规范,用于定义 SPARQL 查询处理程序返回数据的 XML 结构(参见 参考资料)。这种格式足够直观,可由一个相对简单的 XSLT 电子表格处理,这将我带到批文件的最后一步:创建最终的 HTML 报表。
项目最困难的部分 — 从三个源抽取数据并组合成典型工具可以使用的格式 — 现在已经完成,其实并不是很难。所有剩下的工作就是将最后一步产生的 XML 转换成 HTML,这是由批文件利用 XSLT 电子表格 SPARQLXML2HTML.xsl 完成的。查询引擎返回的 XML 具有一种常规的表状结构,这使得电子表格在创建 analystReport.html 报表时很容易找到它需要的数据。(我使用了开源 libxslt C 库附带的 xsltproc
XSLT 处理程序来应用电子表格。若要改为使用 Xalan 或 Saxon,只需要更改命令行中参数的顺序即可。)
符合 SPARQL Query Results XML Format 规范的查询结果是一个大的 sparql 元素,头部信息在 head 元素中,实际的结果在 results 元素中。results 元素为结果中的每一行保留一个 result 元素,而每个 result 元素为这一行中的每个值都具有一个 binding 元素。
清单 3 展示了来自 SPARQLXML2HTML.xsl 的 XSLT 电子表格模板,用于处理 result 元素:
清单 3. 用于处理
result 元素的 XSLT 电子表格模板
<xsl:template match="s:result">
<tr><td colspan="3"><hr/></td></tr>
<tr>
<td><xsl:apply-templates select="s:binding[@name='coName']"/></td>
<td colspan="3"><xsl:apply-templates select="s:binding[@name='tickerSymbol']"/>
$<xsl:apply-templates select="s:binding[@name='lastPrice']"/>
at <xsl:apply-templates select="s:binding[@name='quoteDateTime']"/>
</td> </tr>
<tr>
<td><b>2009 figures:</b></td>
<td>
<b>Revenue </b>
<xsl:apply-templates select="s:binding[@name='revenue']"/>
</td>
<td>
<b>Net Income </b>
<xsl:apply-templates select="s:binding[@name='netIncome']"/>
</td>
</tr>
<tr>
<td colspan="3">
<xsl:apply-templates select="s:binding[@name='abstract']"/>
</td>
</tr>
<tr class="rec">
<td>
<b>Analyst </b>
<xsl:apply-templates select="s:binding[@name='analyst']"/>
</td>
<td>
<b>Recommendation </b>
<xsl:apply-templates select="s:binding[@name='recommendation']"/>
</td>
<td>
<b>Date </b>
<xsl:apply-templates select="s:binding[@name='recDateTime']"/>
</td>
</tr>
<tr>
<td colspan="3">
<xsl:apply-templates select="s:binding[@name='description']"/>
</td>
</tr>
</xsl:template>
|
清单 3 中的模板创建单个 HTML 表行,行中的每个单元格保留返回的一段信息或者该信息的一个标签。
build.bat 批文件在 10 步中完成以上所有操作:
-
设置 Java
CLASSPATH以包含arq工具。这一行假设ARQROOT环境变量已经设置为此工具的主目录。(参见 参考资料,阅读 关于arq的文档。) -
使用 xls2rdf.py Python 脚本,从 analystRecs.xls 电子表格读取数据,并作为 RDF 保存在 analystRecs.rdf 文件中。
-
利用
arq和存储在 augmentAnalystRecs.spq 文件中的 SPARQL 查询,从 analystRecs.rdf 读取公司名称并创建文件 coNamesWithLangTags.n3,该文件中每个公司名称都包含一个en语言标记。这使得交叉引用带有 DBpedia 数据的数据更为容易。 -
将 MakeGetTickerInfo.xsl XSLT 电子表格应用于 analystRecs.rdf,输出批文件 getTickerInfo.bat,它从 Yahoo! 服务检索股价数据。
-
运行 getTickerInfo.bat,它将 Yahoo! 数据检索为一个 CSV 文件,即 quoteData.csv。
-
运行 yahooCSV2RDF.pl Perl 脚本,将 quoteData.csv 转换成 quoteData.rdf RDF 文件。
-
将 MakeGetDbpediaData.xsl XSLT 电子表格应用于 analystRecs.rdf,以创建 getDbpediaData.bat 批文件,它从 DBpedia 检索公司数据。此批文件的每一行调用 cURL,给它传递一个 URI 参数,其中具有一个内嵌的 SPARQL 查询,负责检索一个公司的数据。
-
运行 getDbpediaData.bat 批文件,并将输出保存在 dbpedia.n3 文件中。
-
针对前面创建的四个数据文件(analystRecs.rdf、quoteData.rdf、coNamesWithLangTags.n3 和 dbpedia.n3),运行 PickDataForReport.spq 中的 SPARQL 查询,并将结果的 XML 版本保持在 reportData.xml 中。
-
将 SPARQLXML2HTML.xsl XSLT 电子表格应用于 reportData.xml 文件,以创建最终的报表文件 analystReport.html。
其他一些工具可能合并和自动化了一些步骤,实现与此相同的架构会更容易,但是要做的基本工作是相同的。
组合三个源的数据创建囊括 9 家公司的报表,对于使用我刚才介绍的技术来说是很小的规模。开源的 D2RQ 接口让您可以将关系数据当作一个三元组集合对待,因而该数据可以合并到这样的应用程序中。例如,假设一个这样的财务机构,它将有关其客户股票投资组合的数据存储在一个关系数据库系统中,比如 MySQL、DB2 或 Oracle。向本文描述的应用程序增加一点代码,就可以让它为每个客户产生类似于 analystReport.html 的定制报表,只列出此客户持有的股票,包括现值 — 通过将来自 Yahoo! 的股价乘以持有的股数计算得出。
整个应用程序不需要 RDF Schema 或 OWL 本体语言。但是这种模式元数据也存储为三元组,所以您若确实想要合并此类数据的话,它是又一类输入数据,可以增强您组合来创建报表的数据。使用这些模式标准存储规则(或者类似的东西)和其他关系元数据,而不是将它们存储在编译后的代码中,这增加了业务逻辑更易于维护和移植的优势。
日益增长的 Linked Data 源为您提供了越来越多的数据合并到应用程序,而语义 Web 标准为将此数据与其他数据源混合并匹配带来了新的灵活性。很多企业也发现,符合这些标准的工具对于在加入任何公共可用的数据之前在其企业内组合多个源的数据是很有价值的。有很多新工具可用于让所有这一切更为容易,但是正如您在这里看到的,一些熟悉的、受信任的老工具和技术在以有用的新方式合并数据方面也扮演了重要角色。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 批文件、它调用的脚本,以及样例数据 | comboPubPrivData.zip | 86KB | HTTP |
学习
- SPARQL Query Results XML Format:从 W3C 规范更多地了解此格式。
- Downloading Yahoo data:查看 finance.yahoo.com 股价服务的所有选项。
- About the Linking Open Data dataset cloud:探索公共链接数据源的 Linked Data 云。
arq:查看arq命令行应用程序的文档。- 用 SPARQL 搜索 RDF 数据(Philip McCarthy,developerWorks,2005 年 5 月):了解 SPARQL 的特性,学习如何利用 Jena语义 Web Toolkit 从 Java 应用程序使用 SPARQL 查询。
- 借助语义技术构建 Wikipedia 查询表单(Bob DuCharme,developerWorks,2009 年 7 月):了解您的应用程序如何可以通过使用公共的 SPARQL 端点而包含 Linked Data。
- XML 专区:在 XML 专区获取提高您的专业技能所需的资源。
- My developerWorks:个性化您的 developerWorks 体验。
- IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
- XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。此外,阅读更多的 XML 技巧。
- developerWorks 技术活动 和 网络广播:随时关注这些活动中的技术。
- developerWorks 播客:收听面向软件开发人员的有趣访谈和讨论。
- developerWorks 演示中心:观看各种演示,从针对初学者的产品安装和设置,到针对有经验的开发人员的高级功能。
获得产品和技术
- Jena - A语义 Web Framework for Java:从 Jena 项目获得
arq和更多语义 Web 开发工具。 -
cURL:下载 cURL 工具从命令行检索 web
资源。cURL 默认安装在大多数 UNIX® 和 Linux 系统上;Windows 版本也可以下载得到。
- Lingfo:获得用于读取 Excel 文件的 Lingfo Python 库。
-
IBM 产品评估试用版软件:下载或 在线试用 IBM SOA Sandbox,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
讨论
- XML 专区讨论论坛:参与任何一个 XML 相关讨论。
- developerWorks 博客:阅读这些博客并参与讨论。
