这篇是转载的,讲如何利用免费在线报表软件Zoho Reports的API的。我其实看不太懂,但是感觉还比较有价值,因为我自己用Zoho Reports,只要把excel数据导进去,它可以很方便地生成各种饼图、柱状图、对比图、透视图、.......这个文章应该说的是利用它的API在任何其他第三方软件里使用。推荐一阅。原文地址:http://www.ibm.com/developerworks/cn/xml/x-xmlzoho/
为任何应用程序上的分析和报告组合使用 XML 和 Zoho Reports
云分析允许开发人员添加传统业务智能解决方案的很多特性,无需任何开销。探究如何使用 Zoho Reports、Zoho API 和 XML 来利用云分析的威力,从而向任何应用程序(不管是云中的,还是本地的)添加分析功能。
云分析提供一种业务智能 (BI) 报告引擎,无需安装和维护传统报告引擎时所需的开销和成本。它们也能被更广泛的受众所访问,因为建立和维护它们不需要专门技能。跟传统的报告引擎不同,用于云分析的数据可以驻留在报告引擎外面的很多位置中。
那么,云分析的主要挑战就是要保证数据能够高效地传输到报告引擎中。很多云分析平台允许从电子表格或逗号分隔值 (CSV) 文件导入数据。它们也通过 Web 服务提供一个编程接口。
Zoho® Reports是一个示例应用程序,它将传统的应用程序与云服务进行集成,以在云中提供分析。本文中的例子展示了传统应用程序如何将 Zoho Reports 用于数据存储和检索以及报告目的,还可以将产生的图形嵌入在 Web 页面中。
Zoho Reports 提供一个宿主数据库(用于存储数据)和一个 REST-ful API(以允许与数据的交互)。REST-风格的架构是理想的解决方案,因为它允许通过 HTTP 进行简单的消息传递。利用简单的 HTTP 消息,您可以与服务器通信,服务器可以返回 XML 格式的数据。
了解 Zoho Reports
Zoho Reports 是一个在线报告工具,它为业务分析提供一种宿主的解决方案。数据以熟悉的数据库方式存储,组织为表的形式。用于定义数据结构的接口是电子表格与数据库的混合。您也可以通过上载的文件结构定义表的结构。
可以用很多方式将数据输入 Zoho Reports 中,包括:从诸如 CSV、Microsoft® Office Excel® (XLS) 和 HTML 等格式上载;在电子表格之类的界面中手工输入;或者通过使用 Reports API 输入。对于报告功能,Zoho Reports 提供诸如传统报告应用程序中可以找到的那些组件 — 图表、透视图表和数据表格视图。它允许通过拖放界面进行数据的可视分析,也可以使用熟悉的 sql 数据库语言查询数据。
在 Zoho Reports 中定义报告之后,可以将报告嵌入在 Internet 上的任何地方,比如博客、定制应用程序或其他 Web 站点。这样,就可以灵活地在不同的位置使用相同的报告。
使用 Zoho API
Zoho API 为通过 HTTP 与数据库中的数据交互提供一个 REST-风格的接口。对 API 的调用包括数据库名和要使用的表。此 API 的功能包括:
- 添加或修改数据。
- 使用 CSV 文件批量添加或更新数据。
- 基于指定的条件批量更新或删除数据。
- 以诸如 PDF、HTML、CSV、JavaScript Object Notation (JSON) 和图像之类的格式导出数据和报告。
- 使用 sql
SELECT
查询从数据库取回数据。
要使用该 API,必须首先从 http://writer.zoho.com/apikey.htm 请求一个密钥。所有 API 调用都要传递此密钥。
每个 Zoho Reports 报告的第二个重要部分是 ticket
参数。该票据(ticket)是在您首次登录时生成的。这个票据然后被用于所有后续 API 调用。
请求格式使用一种 HTTP POST
请求格式,并在参数中指定要采取的动作,以及 API 密钥、票据、API 版本和输出格式。请求的数据在请求体中传递。Zoho wiki 上有请求格式的详细信息。
请求中指定的响应格式可以是 XML 或 JSON。XML 格式指定一个 <response>
标记,其中嵌套着一个 <result>
标记。<response>
标记指定调用的 URI 和采取的动作:
<?xml version="1.0" encoding="UTF-8" ?> <response uri="/api/loginname/databasename/tablename" action="specifiedaction"> <result> <!-- The specific XML response based on the action goes here --> </result> </response>
为了促进与 Zoho API 的交互,Zoho Reports 提供一个用 Java™ 语言和 Python 语言编写的客户端库;此外,Google App Engine 客户端被作为 Python 库的一个扩展提供。本文中的例子使用 Java 语言库,该库为与 Zoho Reports 的交互提供一个相当简单的接口。
使用的主类是 ReportClient
,它代表与 Zoho Reports 交互的主客户端。开始,登录到客户端,然后获得将用于与服务器交互的 URI:
ReportClient reportClient = ZohoConfig.getReportClient(); reportClient.login(ZohoConfig.LOGINNAME,ZohoConfig.PASSWORD); String uri = reportClient.getURI(ZohoConfig.LOGINNAME,ZohoConfig.DATABASENAME,"WordFrequency");
此代码登录到 ZohoConfig
中指定的数据库,即 BlogAnalyzer。然后指定了将要使用的表 — 本例中是 WordFrequency。
reportClient.logout();
利用 Zoho Reports 分析 RSS 提要
作为一个简单的例子,我们来分析很多 RSS 提要,找出每个单词出现的频率。由于 RSS 是使用 XML 指定的,所以很容易在 Java 语言中读取和解析 RSS。示例应用程序使用 Rome,一个用于解析、生成和发布 RSS 提要的 Java 库。Rome 使用 JDOM XML 解析器来支持提要解析,以及来回转换不同格式的提要。
利用 Rome 读取 RSS 提要极为简单。根据要读取的 RSS 提要的 URL,构造一个 XMLReader
,然后读取提要:
URL FeedUrl = new URL(url); XmlReader xmlReader = new XmlReader(FeedUrl); SyndFeedInput input = new SyndFeedInput(); SyndFeed Feed = input.build(xmlReader);
该代码将一系列条目存储在 Feed
对象中。然后您可以迭代通过这些条目,从条目中解析出一系列单词,如 清单 1 所示。
清单 1. 迭代通过并解析条目
List entriesList = Feed.getEntries(); for (Object obj : entriesList) { SyndEntryImpl syndEntry = (SyndEntryImpl) obj; String title = syndEntry.getTitle(); parseWordsFromString(title); SyndContent description = syndEntry.getDescription(); parseWordsFromString(description.getValue()); }
parseWordsFromString()
方法更新单词映射,其中统计了每个单词的频率。解析完取得的每个提要的所有条目之后,循环通过密钥集,查看每个单词的频率。例如,单词 and 出现了 1015 次,Apple 出现 45 次,Adobe 出现两次。
从字符串解析单词
清单 2 中所示用于从字符串解析单词的方法是从 Java2s Web 站点上的相同方法修改而来的:
清单 2. 从字符串解析单词
public void parseWordsFromString(String nxtString) throws CharacterCodingException { // Create line pattern Pattern linePattern = Pattern.compile(".*$",Pattern.MULTILINE); // Create word pattern Pattern wordBreakPattern = Pattern.compile("[\\p{Punct}\\s}]"); // Match line pattern to buffer Matcher lineMatcher = linePattern.matcher(nxtString); Integer ONE = new Integer(1); // For each line while (lineMatcher.find()) { // Get line CharSequence line = lineMatcher.group(); // Get array of words on line String words[] = wordBreakPattern.split(line); // For each word for (int i = 0,n = words.length; i < n; i++) { String nxtWord = words[i].trim(); if (nxtWord.matches("[a-zA-Z]{2,}?")) { nxtWord = nxtWord.toLowerCase(); Integer frequency = (Integer) map.get(nxtWord); if (frequency == null) { frequency = ONE; } else { int value = frequency.intValue(); frequency = new Integer(value + 1); } map.put(nxtWord,frequency); } } } }
parseWordsFromString
使用 Java 正则表达式来解析字符串。首先,它创建一个正则表达式模式用于查找句子末尾,并为每个单词创建一个 ONE 变量,用于统计单词的出现频率。然后循环通过每个句子,并基于单词分割模式将句子分割成单词。对于每个长于两字符的单词,将统计数存储在频率映射中。
现在有了 RSS 提要中每个单词的频率,就可以将此数据上载到 Zoho Reports 进行分析了。为此,创建一个如 清单 3 中所示的散列映射,其中包含您想要存储在表中的行数据。
清单 3. 构建一个带有要分析的行数据的散列映射
SimpleDateFormat dtFmt = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Set wordSet = map.keySet(); for (Object objs : wordSet) { String nxtWord = (String) objs; Integer frequency = (Integer) map.get(nxtWord); HashMap rowValsMap = new HashMap(); rowValsMap.put("Date",dtFmt.format(new Date())); rowValsMap.put("Word",nxtWord); rowValsMap.put("Frequency",frequency); Map result = reportClient.addRow(uri,rowValsMap,null);; }
循环中的最后一个调用,调用报告客户端,并告诉它将行值添加到表中。登录到 Zoho Reports 查看 WordFrequency 表中的数据,如 图 1 所示。
图 1. Zoho Reports 中的 WordFrequency 表
为了让该表真正有用,应该进一步精炼单词列表。比如说,过滤掉诸如 http 和 com 之类的常见单词。
优化上载过程
前一个例子每次上载一行数据 — 显然不是最佳的方法。运行这个例子要花较多的时间上载数据。更好的方法是使用批量上载来一次上载所有的数据。目前,Zoho API 只提供选项来上载 CSV 文件。
CSV 文件的格式很简单:第一行包含列标题列表,下面的行包含数据。传递 CSV 文件时,您可以在 POST
体中指定附加的上载参数,包括很多用于上载数据的选项,比如创建新表、追加到现有的表,或者更新表中的现有值。可用选项的详细信息在 Zoho wiki 中。
要优化 RSS 单词分析程序,可更改上载过程以使用 Zoho API import
方法。导入数据调用返回一个 XML 文档,详细记录了上载的结果 — 上载的列数、总行数和其他信息。它也具有一个导入错误列表,比如说一个值的类型与某一列不符。
要使用 import
方法,必须首先使用 opencsv.将数据集转换成 CSV 文件。要填充文件,可循环通过单词映射中的值,将每个值写到文件中的一行(参见 清单 4)。
清单 4. 创建 CSV 文件用于上载
Calendar today = GregorianCalendar.getInstance(); SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yy.H.mm.ss"); String dateStr = formatter.format(today.getTime()); String csvFileName = "benchmark-results" + dateStr + ".csv"; CSVWriter writer = new CSVWriter(new FileWriter(csvFileName)); String[] columns = new String[]{"Date","Word","Frequency"}; writer.writeNext(columns); SimpleDateFormat dtFmt = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); String crntDateStr = dtFmt.format(new Date()); Set wordSet = map.keySet(); for (Object objs : wordSet) { String nxtWord = (String) objs; Integer frequency = (Integer) map.get(nxtWord); String[] values = new String[]{crntDateStr,nxtWord,frequency.toString()}; writer.writeNext(values); } writer.close();
创建 CSV 文件之后,只要在 ReportClient
上将文件名作为参数传递给 importData()
方法即可。该方法解析返回的 XML 文档,并利用导入的详细结果填充 ImportResult
类,如 清单 5 所示。
清单 5. 优化 RSS 单词分析程序上载
ReportClient reportClient = ZohoConfig.getReportClient(); System.out.println(" Logging into the server"); reportClient.login(ZohoConfig.LOGINNAME,ZohoConfig.PASSWORD); System.out.println(" Successfully logged in."); String uri = reportClient.getURI(ZohoConfig.LOGINNAME,"WordFrequency"); System.out.println("uri = " + uri); ImportResult importResult = reportClient.importData(uri,"APPEND",new File(csvFileName),getImportConfig(),false); System.out.println("imported " + importResult.getTotalRowCount() + " rows"); reportClient.logout();
更改导入过程以使用批量上载的成效显著:对于 6000 行数据的上载过程,时间从几分钟缩短到几秒钟。
从 Zoho Reports 导出 XML
可以使用两种方法之一从 Zoho Reports 导出数据到 XML、CSV 或图像格式的文件中。第一种方法是利用可选的标准过滤器指定直接导出。第二种方法是使用某种类似于 sql SELECT
语句的东西。
直接导出在 URI 中指定导出的表,输出可以直接保存到文件或输出流。清单 6 提供一个例子,使用搜索条件直接导出到 XML 文件。对于本例来说,您只想看到统计频率高于 400 的单词。
清单 6. 从 Zoho Reports 导出到 XML 文件
String exportUri = reportClient.getURI(ZohoConfig.LOGINNAME,"WordFrequency"); File topXmlFile = new File("topFrequencyWords.xml"); String xmlCriteria = "(\"Frequency\" > 400)"; reportClient.exportData(exportUri,"XML",topXmlFile,xmlCriteria,null);
在本例中,您指定自己只想要返回频率值高于 400 的数据。输出直接保存到 topFrequencyWords.xml 文件。清单 7 提供了此 XML 文件的一个片段。
清单 7. 摘自 topFrequencyWords.xml
<?xml version="1.0" encoding="UTF-8" ?> <response uri="/api/flexanvil/BlogAnalyzer/WordFrequency" action="EXPORT"> <criteria>("Frequency" > 400)</criteria> <result> <rows> <row> <column name="Word">http</column> <column name="Frequency">2687</column> <column name="Date">19 May,2009 16:43:26</column> </row> <row> <column name="Word">com</column> <column name="Frequency">2587</column> <column name="Date">19 May,2009 16:39:05</column> </row>
在第二个例子中,使用 sql 来指定想要导出的数据。对于本例来说,使用一些基本的 sql 函数来分析数据。如果想要看到频率值的平均值、统计数、最大值和标准值,可以使用类似于 清单 8 中的代码。
清单 8. 针对 Zoho Reports 运行 sql 查询
String sqlUri = reportClient.getURI(ZohoConfig.LOGINNAME,ZohoConfig.DATABASENAME); System.out.println("sqlUri = " + sqlUri); String sql = "SELECT avg(\"Frequency\") as Average,count(\"Frequency\") as Count,max(\"Frequency\") as Maximum," + "std(\"Frequency\") as Standard FROM \"WordFrequency\""; File xmlFile = new File("frequencyData.xml"); reportClient.exportDataUsingsql(sqlUri,xmlFile,sql,null);
本例指定 sql 字符串来用于导出数据。sql 代码针对数据库执行,结果存储在 XML 文件 frequencyData.xml 中,如 清单 9 所示。
清单 9. 摘自 frequencyData.xml
<?xml version="1.0" encoding="UTF-8" ?> <response uri="/api/flexanvil/BlogAnalyzer" action="EXPORT"> <result> <rows> <row> <column name="Average">11.796</column> <column name="Count">5834</column> <column name="Maximum">2687</column> <column name="Standard">78.0844</column> </row> </rows> </result> </response>
导出数据的 sql 方法关键的区别在于,URI 没有指定使用哪个表,这允许 sql 方法组合多个表的数据。例如,您可能有一个单独的表,其中列出您想要追踪的公司。然后您可以使用一个 sql inner join
语句来得到列表中每个公司被提到的频率,如 清单 10 所示。
清单 10. 针对 Zoho Reports 进行的复杂 sql 查询的例子
String companysql = "SELECT wf.Frequency,wf.Word,cm.Name From WordFrequency wf inner join Companies cm on wf.word = cm.name"; File companyXmlFile = new File("companyFrequency.xml"); reportClient.exportDataUsingsql(sqlUri,companyXmlFile,companysql,null);
本例使用 SELECT
查询,它定义了 WordFrequency
和 Companies
之间的 inner join
,其中单词与公司名匹配。清单 11 展示了运行该查询产生的 XML 输出。
清单 11. sql SELECT 查询产生的输出
<?xml version="1.0" encoding="UTF-8" ?> <response uri="/api/flexanvil/BlogAnalyzer" action="EXPORT"> <result> <rows> <row> <column name="wf.Frequency">52</column> <column name="wf.Word">apple</column> <column name="cm.Name">Apple</column> </row> <row> <column name="wf.Frequency">3</column> <column name="wf.Word">sun</column> <column name="cm.Name">Sun</column> </row> <row> <column name="wf.Frequency">17</column> <column name="wf.Word">intel</column> <column name="cm.Name">Intel</column> </row> <row> <column name="wf.Frequency">80</column> <column name="wf.Word">microsoft</column> <column name="cm.Name">Microsoft</column> </row> </rows> </result> </response>
由于所有这些例子都产生 XML,所以您可以很容易将输出集成回应用程序中。例如,您可能在 Java 应用程序中解析该 XML,以便显示在应用程序中。
创建和导出图形
Zoho Reports 的独特特性之一是可视分析器(visual analyzer)。可视分析器允许您快速创建数据的图表、图形和其他常见报告。作为一个例子,假设您想要创建一个图形,表示出现频率最高的一些单词。图 2 展示了用于创建基本条形图的可视设计器(visual designer)。
@H_403_293@图 2. Zoho Reports 可视分析器中的条形图创建此图之后,通过调用 exportData()
方法并为输出指定一种图像格式,下载其最新版的图像:
String imgURI = reportClient.getURI(ZohoConfig.LOGINNAME,"FrequencyChart"); File imgFile = new File("FrequencyChart.png"); reportClient.exportData(imgURI,"IMAGE",imgFile,null,null);
exportData()
方法将图形保存为 PNG 文件。然后您可以使用该 PNG 文件来在应用程序中显示图形。
结束语
利用 Zoho Reports 提供的 REST-ful 的 Web 服务,可以向传统应用程序添加云分析。而这又允许您导入和导出数据、导出 XML 报告以及导出预定义的图形。这种无需安装报告引擎而快速分析数据和产生报告的能力,让您可以将更多的时间用于进行开发。云分析也为广大受众提供访问数据和执行可视分析的能力 — 也许是云分析的最大优点。对您的数据采用强大的云分析吧。