XML - 报表数据的新大陆
发布日期:2021-08-14 17:36:12 浏览次数:10 分类:技术文章

本文共 3385 字,大约阅读时间需要 11 分钟。

   随着B/S系统的普及和XML技术的深入应用,越来越多的数据包裹着XML的外衣被存储和扔来扔去。这些数据很多源自数据库,但经过一定的处理,数据更精简,更贴近应用。如果报表工具能利用这些XML数据,则可以减少数据库查询和报表数据运算操作,因为这些XML数据的始作俑者已经完成了这些操作。因此说XML是报表数据的新大陆。

  传统的报表工具都是只能处理关系型数据库,基本上不能处理其他数据。随着时代的发展,一些报表工具加上了处理XML文档的能力,但需要编程,编写并配置插件,如此报表程序结构复杂,接口众多,用户还需要根据各种规范动手编写程序,若XML文档格式有很多种,就需要编写很多种的插件,报表开发量不小。

   如果实现了一种能处理XML文档,从中获得报表数据的通用方法。则在定制报表模板的时候就教育报表引擎如何从XML文档获得数据,则对于所有的或大部分的XML文档无需编程,可减少报表开发量。

  那么如何通用的处理具有复杂树状结构的XML文档呢?

   大家知道,处理XML文档有两种模式,一个是DOM方式,另一个是流模式。DOM方式处理方便,但速度慢耗内存,流模式处理速度快,省内存但使用不方便。对于.NET平台,使用System.Xml.XmlDocument对象来使用DOM方式处理XML文档,而使用XmlReader 来使用流模式处理XML文档。

   W3C国际标准组织设计XML文档的目标是方便的存储和交换小型数据包,而不考虑数据的冗余。因此若实际系统中出现巨大的XML文档,则大多数情况下可以认为是不恰当的使用XML技术。因此我认为报表工具不应当处理巨大的XML文档,在此前提下,为了实现方便,采用DOM方式来处理XML文档。

   在.NET中使用XmlDocument加载一个XML文档后,会形成一个以XmlDocument为根节点的XML对象树状结构,面对这个XML树结构,获取其中的数据方法很自然的就是使用XPath技术了。XPath技术就是在XML树状结构中,以某个节点作为起始节点,使用特定的描述表示的路径移动到其他的节点,一般的是向其下层节点移动,比如移动到某个子节点或孙节点,移动到某个属性等等。

    传统的报表数据源模型是两层的,即使扩展到可以处理XML文档也只能处理一次,既从根节点出发,使用某个XPath 获得字段的值。如此只能处理一次,处理完毕后XML就被扔掉了。但很多时候需要对XML文档进行进一步处理。此时传统的两层报表数据源模型是不够的。

    为了能对XML文档进行精耕细作,需要从传统的两层数据源结构突破到多层的报表数据源模型。在多层数据源节点中,每一个节点都映射到XML文档中的某个节点,而它的子节点则使用XPath路径映射到XML中的其他节点。如此递归循环后则多层的数据源可以映射到XML文档中的任意节点。多层数据源模型实际上就是一个数据源树,因此处理XML文档也就是将两颗树在某些节点上钉在一起,而XPath就是钉子。因此需要注意各级数据源节点的XPath配置的连续性,若一个数据源节点的XPath设置不对,就像它钉错了XML节点或者干脆钉在空处。则它本身和所有的子孙节点都都会绑定落空的。

   在实际应用中,由于XML文档不是专门为报表而产生的,因此报表工具还可能要离开XML文档来获取更多的报表数据,此时可能需要从XML文档跳到其他XML文档,或者返回数据库继续执行SQL查询。这就非常考验报表数据源模型的灵活性了。

    大家都知道RSS文档是一种XML文档,在这里使用博客园的RSS文档为例子说明从XML读取报表数据的过程。首先考察一下RSS文档的结构,博客园首页的RSS文档URL为 ,根节点为 rss , 然后有个 channel 子节点,下面包含了RSS文档的基本信息,然后有若干个item节点,列出了所有文章的基本信息。item节点下面是文章的基本信息,其中 wfw:commentRss 子节点的内容是针对该文章回帖信息RSS文档的URL。可以根据这个URL加载的回帖信息RSS文档,根据RSS文档结构可以定义出如下的报表数据源和RSS文档的映射关系。

rssxml.gif

   这里的RSSXML文档有三层结构,而且需要动态加载XML文档进行更深入的处理,因此传统的两层结构是肯定不够的,必须采用多层次的报表数据源结构。其过程是相当复杂的,步骤为

  1. 加载 处的XML文档,作为主XML文档,生成一个System.Xml.XmlDocument 对象,并以该XML文档对象作为处理的出发点。
  2. 使用XPath"rss"遍历所有符合该路径的XML节点,很显然只处理了一个节点,此时当前位置就移动到rss节点。
  3. 从当前节点处使用XPath"channel/title"获得网站标题,使用"channel/link"获得网站地址,"channel/description"获得网站说明,"channel/pubDate"获得文档发布时间。
  4. 从当前节点处使用"channel"遍历所有符合该路径的XML节点,很显然只处理了一个节点,此时当前位置就移动到了"channel"节点。
  5. 变量当前节点下的所有的item子节点,并依次设置为当前节点。
  6. 从当前节点处使用“title"获得文章标题,使用"link"获得文章地址,使用”author"获得作者,“pubDate"获得发布时间,"description"获得文章内容,"slash:comment"获得回复数,“wfw:commentRss"获得回复RSSXML文档的URL。
  7. 当处理"wfw:commentRss"节点时,程序根据某个特定的设置加载该节点数据指向的XML文档,也就是加载针对当前文章的回复RSSXML文档。并遍历刚刚加载的XML文档的所有符合"rss/channel/item"的节点,并依次设置为当前节点。
  8. 从当前节点处,使用"author"获得回复作者,使用”pubDate"获得回复时间,使用"description"获得回复内容。
  9. 由于RSSXML文档中的description节点处保存的时HTML代码,因此还需要解析HTML代码并提取其中的纯文本内容。

   从上面的步骤可以看出,数据源结构中的每一个节点都钉到了XML文档中的某个节点,而且在回复列表这个节点中,程序执行了XML文档的跳转,从主XML文档跳到回复RSSXML文档,而且是处理树状结构的,因此是递归操作,很多状态信息都由系统调用堆栈自动保存,无需程序自己保存了。

   如果报表程序能直接连接到博客园数据库的话,还可以从文章作者这个节点执行XML文档到数据库的跳转,直接查询数据库,获得文章作者的一些注册信息。实事上,这个数据源树状结构中每一个节点都可以发生XML到XML,XML到数据库,数据库到XML的三种跳转,这大大扩展了获取报表数据的灵活性。

   如果一个信息系统是纯XML应用的话,则报表工具就可以在众多的XML文档中跳跃着采集数据而不需要查询数据库,就像少林寺的武僧在梅花桩上打架而不用碰地,因此也就不用管下面是JAVA土壤的还是.NET土壤。此时所有的数据库操作,业务逻辑等等都运行在后台,而报表工具无需关心,只要系统底层安全可靠,则报表模块也就安全可靠,系统底层无论如何修改,只要XML文档格式不变则报表模块就不需要修改。对于非常复杂的报表数据源,超出了报表工具的定制能力,则可以编程提供一个XML文档供报表程序使用。以前系统是直接通过API向报表程序提供复杂报表数据,而现在通过XML文档以“隔山打牛”的方式向报表程序提供复杂报表数据。此时系统结构更安全,边界更清楚,体现了XML WebService的指导思想。这种获取数据的思想可以不局限于报表数据的获取,还可以应用到其他领域。

   以上讨论的应用系统限于B/S系统,但可以设想,C/S系统经过改造,可以通过某种方式向报表工具提供XML数据文档。

   从上面的讨论可以看出,XML确实是报表数据的新大陆,本人写的报表工具已经初步体现了这种思想。但这种思想可能有点激进,还不成熟不完善,希望大家多多指点。

XDesigner 软件工作室 2006-8-30

转载于:https://www.cnblogs.com/xdesigner/archive/2006/08/31/490943.html

转载地址:https://blog.csdn.net/weixin_30731287/article/details/95544057 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:js 替换json对象中的键名
下一篇:继承之super关键字的使用

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年11月12日 23时08分32秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

html生成word页眉图片,[转载]一些WORD VBA代码(替换页眉页脚、批量设置格式、图片插入等)... 2019-06-17
html自定义列表图标,自定义列表项符号list-style-image详解 2019-06-17
html开源库,开源Html分析器解析库对比 2019-06-17
支持预览html的解压软件,Bandizip 2.05:轻量级压缩软件(支持右键预览) 2019-06-17
手机端登录注册html5,手机端的注册表单验证js代码 2019-06-17
木瓜移动每日资讯0628:TikTok测试类似小程序的 Jumps 新功能 2019-06-17
木瓜移动每周跨境资讯:TikTok测试Jumps,店小秘收购17TRACK,Facebook推出新闻通讯平台Bulletin 2019-06-17
shell获取sqlplus变量_转:sqlplus与shell互相传值的几种情况 2019-06-17
python如何创建子程序_这些子程序是做什么的? 2019-06-17
立创商城的元件原理图怎么弄到ad_(50条消息)立创EDA元件封装导入AD软件教程 2019-06-17
java aes加密长度_关于Java下的AES加密明文长度的问题 2019-06-17
crc可以检出奇数个错误_差错检测和纠正技术 2019-06-17
mysql generator 中文注释_mybatis generator 使用方法教程(生成带注释的实体类) 2019-06-17
mysql socket php fpm_nginx+php-fpm的socket配置小结 2019-06-17
php 和mysql连接测试代码_php中mysql连接和基本操作代码(快速测试使用,简单方便)_php实例... 2019-06-17
python getattr函数_在python中对self使用getattr函数 2019-06-17
java 音量_java – 音量为零? 2019-06-17
python绑定事件_Python tkinter之Bind(绑定事件)的使用示例 2019-06-17
scala map java map_scala中Map集合的简单使用 2019-06-17
java构造方法左右_java构造方法 2019-06-17