并不是每一份文档最初都是用 XML 写的,这可能与您想像的正好相反。事实上,大多数文档都是用其他一些工具准备出来,然后再转换成 XML 的。许多文档来源于 关系数据库,或者来源于 Microsoft Office 应用程序,比如 Word,或是 Excel。
我发现很多业务中都用 Excel 编辑和准备数据。这个工具简单易用,得到了广泛采用,其表格格式对各种信息都十分适合,比如产品清单、姓名清单、金融数据、统计数据等等。人们通常会把 Excel 电子表格用电子邮件发给用户,让用户填写其中的空白。
当人们从某个私有应用程序中收集和准备数据的时候,通常会遇到如何恢复数据的问题。幸好在 Excel 中不存在这样的问题。尽管对 Excel 文件格式的定义并没有公开,我们还是可以用一些方法从电子表格中提取出 XML 信息。本篇技巧文章将回顾一下可用的方法,并着重指出每一种解决方案的优缺点。
最新版本的 Excel(包括 Excel 2002 和 Excel XP)可以将电子表格导出为 XML。虽然您无法选择其中使用哪些标签,但是的确可以得到一个有效的 XML 文档。您可以用包括 XSLT 样式表在内的任意一种 XML 工具来处理它。这种格式称为 XMLSS。
如果符合下列条件,这就是最简单的方法:
- 您的用户具有最新版本的 Excel,并且
- 您在工作站上处理 XML 数据。
第一种条件是显而易见的,第二个则需要多解释一下。
假设您设置好一台服务器,用来收集和处理统计数据。您的用户用 Excel 准备好数据,然后将这些电子表格上传到服务器上,以供后续处理。第一步是将电子表格转换成 XML。一种解决方法是在 Excel 中打开电子表格,然后将其导出为 XMLSS 格式。我曾经见过一些公司用这种办法处理文档,虽然是可行的,但是有一点必须牢记:Excel 的设计工作环境是工作站,而不是服务器。
这样的解决方案尽管能够实现功能,但是却有可能不像您期望的那样稳定。在其他问题当中,电子表格转换本身就可能成为瓶颈,因为转换过程很难实现为多线程。最糟糕的情况是,每一请求都在单个 Excel 副本中排起队来。同时,这种方法也限制了您的主机系统,因为 Excel 仅仅能在 Windows 和 MacOS 中使用。
第一种替代的方法是,不操作实际的电子表格,而是改为操作 CSV(comma-separated value)文件。CSV 是用来交换电子表格文件的常用格式。任何适当的电子表格都可以通过 CSV 文件导出和导入。
此外,很多可以处理电子表格的第三方产品也都支持 CSV。例如,大多数会计软件包都可以处理 CSV 文件。尽管 CSV 文件不是 XML,但用 XI 之类的工具也很容易将其转换成 XML 文件。TopXML 站点上也包含了纯 XSLT 转换方法的算法。
使用 CSV 文件对于服务器的吸引力更大一些。首先您不再被限制在某种特定的平台上,而是为用户提供了更多的选择。用户现在可以用 Lotus 1-2-3 以及其他电子表格工具,也可以使用很多能够识别 CSV 格式的第三方工具。
这种方法唯一的缺点是,用户必须花费额外的步骤,将数据保存到 CSV 中。我从实践中发现这很少出现问题,但您的情况可能会不一样。
最后一种方法是用特殊的库来读取 Excel 文档。Excel 文件格式并没有官方文档,但是一些第三方机构曾对其进行逆向工程。他们还生成了一些用于解码 Excel 文件的库(参阅 参考资料)。下面列出一些可用的 API:
- Java Excel这个 API 是我最喜欢的一种,因为它是可移植的,可以很好地读取 XML 文档,还可以转换成 XML。
- XML::Excel这是一个 Perl API,用于将 Excel 文档转换成 XML。
- OpenOffice其中包括用于读取 Excel 文档的 C++ 库。您可以用这些库作为将 Excel 转换成 XML 的基础。
- Apache POI它支持在 Java 代码中读取 Excel 文件。同样,您也可以把它用作 Excel 转换成 XML 的基础。
上面列表只是一些有代表性的例子,其他工具可用于不同平台。
转换 Excel 文件能带来三方面的好处:
- 文件可以运行于任何平台上。
- 这些库可以很容易地与服务器集成。
- 用户不需要自己导出数据。
这种解决方案最主要的风险就是,没有哪一种库能够十全十美,您会发现有些电子表格并不能很好地转换。您需要针对您的项目测试出最好的库。
Excel 是一种流行的工具软件,可用于准备各种想用 XML 处理的数据。幸运的是,本篇技巧文章向您展示了很多从 XML 中获取数据的方法。最好的选择有赖于您的项目的特定需求。
不管您是如何转换电子表格的,您将发现最终得到的 XML 文档和您期望的相差甚远。也许里面会包含一些不需要的单元格,或甚至连 XML 词汇表都不是您想要的。您不用为此担心,大多数情况下,您只需要准备一个简单的 XSLT 样式表,就可以过滤掉不需要的数据,或是对一些标签进行重命名。
下面是 Apache POI 操作 Excel 并生成相应 XML 文件的一个DEMO
Excel 数据如下:
客户 机种 出货料号 总库存 备注 张三 K18 GAPJ4004010 5,000 张三 K19 GAPJ4004011 3,800 张三 K20 GAPJ4004012 14,500 张三 K21 GAPJ4004013 - 张三 K22 GAPJ4004014 5,000 张三 K23 GAPJ3001010 7,000 张三 K24 FCPJ3020010 115,500 张三 K25 FCPJ3019010 22,500 张三 K26 FCPJ3021010 30,500 张三 K27 GAPWF003010 12,000 张三 K28 GAPWF001010 4,000 张三 K29 GAPWD001010 76,600 张三 K30 GAPWD002010 152,200 张三 K31 GAPWD003010 11,000 张三 K32 GAPWB004010 - 张三 K33 GAPWB005010 52,000 张三 K34 GAPWB006010 - 张三 K35 GAPGA001010 4,000 张三 K36 GAPGA002010 76,000 张三 K37 GAPGA003010 165,000 张三 K38 GAPG7011010 19,000 张三 B64 GAPW9001010 117,457
要生成的 XML 数据格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<HubStorage>
<SEQNUM>123</SEQNUM>
<StorageItem HubName="张三" VendorCode="AAA-AAA" Materials="GAPJ4004010" State="1" Lfimg="5000" Minps="1" />
<StorageItem HubName="张三" VendorCode="AAA-AAA" Materials="GAPJ4004010" State="1" Lfimg="5000" Minps="1" />
<StorageItem HubName="张三" VendorCode="AAA-AAA" Materials="GAPJ4004010" State="1" Lfimg="5000" Minps="1" />
</HubStorage>
具体实现如下:
首先打开 把相应的JAR 导入进来,并引入工程。 (这是使用的 poi-3.7 的jar 包).
代码:
/**
* 解析 Excel
*/
POIFSFileSystem fs=new POIFSFileSystem(new FileInputStream("e:/XSLT/XSLT_DEMO/成品库存.xls"));
// 读取 Excel 信息
HSSFWorkbook wb = new HSSFWorkbook(fs);
// 选择工作薄 这是选择的是第一个工作薄
HSSFSheet sheet = wb.getSheetAt(0);