一、 开发描述图
二、 如何使用JavaScript 结合XSLT转换XML文档
1. 主界面效果如下:
2. 使用跨浏览器的JavaScript 代码 加载XSLT 和XML代码如下:
a. 先要去判断浏览器的类型,判断是否是IE浏览器,选择合适的加载方法,因为不同的浏览器加载转换文件所使用的对象是不同的
b. 在配置的网络地址里面找到XSL文件和XML文件进行组合转换
c. 将转换后的HTML文档插入到页面的右侧区域的DIV标签内部显示出来
d. 代码如下,是当点击某个报表按钮后,所做的前台操作(标有注释):
e. 效果1
f. 效果2
g. 源代码如下
$(document).ready(function() {
$('#MPayPremium').click(function() {
if (document.implementation && document.implementation.createDocument) { //
// 支持Mozilla浏览器
try {
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.async = false;
xmlDoc.load(hostAddress + "MPayPremium/Index.xml" + "?time=" + getExcelFileName('a'));
}
catch (e) {
alert("error:001");
}
try {
xslDoc = document.implementation.createDocument("", "", null);
xslDoc.async = false;
xslDoc.load("chartDir/MPayPremium/index.xsl");
}
catch (e) {
alert("error:002");
}
try {
// 定义XSLTProcessor对象
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslDoc);
var oResultFragment = xsltProcessor.transformToFragment(xmlDoc, document);
// 将解析过的文本输出到页面
$('#rightside').html(oResultFragment);
}
catch (e) {
alert("error:003");
}
}
else if (typeof window.ActiveXObject != 'undefined') { //IE浏览器
// Load XML
var xml = new ActiveXObject("Microsoft.XMLDOM")
xml.async = false
xml.load(hostAddress + "MPayPremium/Index.xml" + "?time=" + getExcelFileName('a'))
// Load XSL
var xsl = new ActiveXObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load("chartDir/MPayPremium/index.xsl")
$('#rightside').html(xml.transformNode(xsl));
$('.divTitle').hover(function() {
$(this).addClass('hover');
}, function() {
$(this).removeClass('hover');
});
$('.divTitle').click(function() {
//设置导出XML的地址
currentXMLUrl = this.title;
//设置导出XML的XSL地址
currentExcelXslUrl = "chartDir/MPayPremium/MPayPremiumToExcel.xsl";
//设置导出文件的名字
currentXslName = this.innerText;
CallMppTable();
})
}
});
});
3. 注意自适应的高度问题
a. 报表的需求希望能够将所有的内容填充到内容区域,如果超出可是范围的显示滚动条。
b. 在没有数据的时候页脚要在页面的最下面,我使用了Js控制,代码如下
c. 判断浏览器的类型,为为浏览器的窗口添加,加载和窗口改变事件代码,将页脚自动的放在最下面,同时如果页面超出了最大视角,页脚还可以向下延伸。
var isIE6 = navigator.userAgent.indexOf('MSIE 6') > 0;
var isIE = navigator.userAgent.indexOf('MSIE') > 0;
function setFooterPosition() {
var objBodycontainer = document.getElementById("container");
var footerHeight = document.getElementById('foot').offsetHeight;
var headerHeight = document.getElementById('header').offsetHeight;
if (!isIE) {
if (window.innerHeight > footerHeight)
document.getElementById('container').style.minHeight = (window.innerHeight - footerHeight) + 'px';
}
else {
if (isIE6) {
if (document.documentElement.clientHeight > footerHeight)
document.getElementById('container').style.height = (document.documentElement.clientHeight - footerHeight) + 'px';
}
else {
if (document.documentElement.clientHeight > footerHeight) {
document.getElementById('container').style.minHeight = (document.documentElement.clientHeight - footerHeight) + 'px';
document.getElementById('showBtn').style.minHeight = (document.documentElement.clientHeight - footerHeight - headerHeight) + 'px';
document.getElementById('leftSpace').style.minHeight = (document.documentElement.clientHeight - footerHeight - headerHeight - 40 * 10) + 'px';
document.getElementById('leftside').style.minHeight = document.getElementById('showBtn').style.minHeight;
}
}
}
}
if (isIE) {
window.attachEvent("onload", setFooterPosition);
window.attachEvent("onresize", setFooterPosition);
} else {
window.addEventListener("load", setFooterPosition, false);
window.addEventListener("resize", setFooterPosition, false);
}
4. XSLT 文件的编写:
XSLT 用于将一种 XML 文档转换为另外一种 XML 文档,或者可被浏览器识别的其他类型的文档,比如 HTML 和 XHTML。通常,XSLT 是通过把每个 XML 元素转换为 (X)HTML 元素来完成这项工作的。
通过 XSLT,您可以向或者从输出文件添加或移除元素和属性。您也可重新排列元素,执行测试并决定隐藏或显示哪个元素,等等。
描述转化过程的一种通常的说法是,XSLT 把 XML 源树转换为 另一种XML 结果树。
XSLT 使用 XPath
XSLT 使用 XPath 在 XML 文档中查找信息。XPath 被用来通过元素和属性在 XML 文档中进行导航。
它如何工作?
在转换过程中,XSLT 使用 XPath 来定义源文档中可匹配一个或多个预定义模板的部分。一旦匹配被找到,XSLT 就会把源文档的匹配部分转换为结果文档。
5. 举例XSLT转换的示例:
XSL 文件
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<div class="tl1">应付保费列表</div>
<xsl:for-each select="Index/file">
<a class="divTitle" >
<xsl:attribute name="title">
<xsl:value-of select="url" />
</xsl:attribute>
<xsl:attribute name="coords">
<xsl:value-of select="createDate" />
</xsl:attribute>
<xsl:attribute name="charset">
<xsl:value-of select="type" />
</xsl:attribute>
<xsl:value-of select="name"/> </a>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XML 文件
<?xml version="1.0" encoding="utf-8" ?>
<Index>
<file id="1">
<name>2009年7月</name>
<url>http://localhost/CharDir/MPayPremium/2009/20097.xml</url>
<createDate>2009-6-12 19:32:32</createDate>
<type>M</type>
</file>
<file id="2">
<name>2009年8月</name>
<url>http://localhost/CharDir/MPayPremium/2009/20097.xml</url>
<createDate>2009-6-12 19:32:32</createDate>
<type>M</type>
</file>
<file id="1">
<name>2009年9月</name>
<url>http://localhost/CharDir/MPayPremium/2009/20097.xml</url>
<createDate>2009-6-12 19:32:32</createDate>
<type>M</type>
</file>
<file id="1">
<name>2009年10月</name>
<url>http://localhost/CharDir/MPayPremium/2009/20097.xml</url>
<createDate>2009-6-12 19:32:32</createDate>
<type>M</type>
</file>
</Index>
6. 示例说明如下:
a. 模板标记
XSL 样式表由一个或多套被称为模板(template)的规则组成。
每个模板含有当某个指定的节点被匹配时所应用的规则。
<xsl:template> 元素
<xsl:template> 元素用于构建模板。
match 属性用于关联 XML 元素和模板。match 属性也可用来为整个文档定义模板。match 属性的值是 XPath 表达式(举例,match="/" 定义整个文档)。
b. 循环语句
<xsl:for-each> 元素允许您在 XSLT 中进行循环。
语句会匹配select="Index/file"中的每一个标记进行遍历
c. 值输出语句
<xsl:value-of> 元素用于提取某个选定节点的值,并把值添加到转换的输出流中
比如:<xsl:value-of select="type" /> 会将Type元素的值输出
d. 属性输出
<a class="divTitle" >
<xsl:attribute name="title">
<xsl:value-of select="url" />
</xsl:attribute>
</a >
上面的语句可以将Url的元素值创建一个Title 的属性给a 标签
e. 效果
7. XPath 的应用:
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。
因此,对 XPath 的理解是很多高级 XML 应用的基础。
XPath 路径表达式
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
XPath 标准函数
XPath 含有超过 100 个内建的函数。这些函数用于字符串值、数值,日期和时间比较、节点和 QName 处理、序列处理、逻辑值等等。
XPath 在 XSLT 中使用
XPath 是 XSLT 标准中的主要元素。如果没有 XPath 方面的知识,您就无法创建 XSLT 文档。
8. XPath 举例:
选取价格高于 35 的 price 价格
下面的例子会选取所有价格高于 35 的 price 节点:
xmlDoc.selectNodes("/bookstore/book[price>35]/price")
9. Excel 的导出:
Excel 的导出,为了能够自适应浏览器插件我使用了JavaScript 的方法去控制导出一个文件到桌面。
示例:
function getXlsFromTbl(xmlUrl,xslUrl,xmlName) {
try {
//xmlUrl = "demo";
var xml = new ActiveXObject("Microsoft.XMLDOM")
xml.async = false
xml.load(xmlUrl)
// Load XSL
var xsl = new ActiveXObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load(xslUrl)
var d = " " + xml.transformNode(xsl);
//去掉 xml 头
var arr = d.split("?>");
//获得文件名
var fileName = getExcelFileName(xmlName);
//导出
doFileExport(fileName, arr[1]);
}
catch (e) {
alert("导出发生异常:" + e.name + "->" + e.description + "!");
}
}
//获得一个文件名
function getExcelFileName(xmlUrl) {
var d = new Date();
var curYear = d.getYear();
var curMonth = "" + (d.getMonth() + 1);
var curDate = "" + d.getDate();
var curHour = "" + d.getHours();
var curMinute = "" + d.getMinutes();
var curSecond = "" + d.getSeconds();
if (curMonth.length == 1) {
curMonth = "0" + curMonth;
}
if (curDate.length == 1) {
curDate = "0" + curDate;
}
if (curHour.length == 1) {
curHour = "0" + curHour;
}
if (curMinute.length == 1) {
curMinute = "0" + curMinute;
}
if (curSecond.length == 1) {
curSecond = "0" + curSecond;
}
var fileName = xmlUrl + "_" + curYear + curMonth + curDate + "_"
+ curHour + curMinute + curSecond + ".csv";
//alert(fileName);
return fileName;
}
//导出Excel
function doFileExport(inName, inStr) {
var xlsWin = null;
if (!!document.all("glbHideFrm")) {
xlsWin = glbHideFrm;
}
else {
var width = 6;
var height = 4;
var openPara = "left=" + (window.screen.width / 2 - width / 2)
+ ",top=" + (window.screen.height / 2 - height / 2)
+ ",scrollbars=no,width=" + width + ",height=" + height;
xlsWin = window.open("", "_blank", openPara);
}
xlsWin.document.write(inStr);
xlsWin.document.close();
xlsWin.document.execCommand('Saveas', true, inName);
xlsWin.close();
}
10. 一次性的导出所有的内容,为了支持分页,我创建了一个专门用于导出Excel的XSL转换文件:
示例:
<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
序号	月份	数量	险种	应付保费	实付保费	保险公司	
<xsl:for-each select="MPayPremium/record">
<xsl:value-of select=" position()"/>	<xsl:value-of select="month"/>	<xsl:value-of select="count"/>	<xsl:value-of select="combo_name"/>	<xsl:value-of select="premiumspayable"/>	<xsl:value-of select="premiumspayed"/>	<xsl:value-of select="supplier_name"/>	
</xsl:for-each>	合计:	<xsl:variable name="x">
<xsl:for-each select="MPayPremium/record">
<span>
<xsl:value-of select="number(count)"/>
</span>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(msxsl:node-set($x)/span)" xmlns:msxsl="urn:schemas-microsoft-com:xslt" />		<xsl:variable name="y">
<xsl:for-each select="MPayPremium/record">
<span>
<xsl:value-of select="number(premiumspayable)"/>
</span>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(msxsl:node-set($y)/span)" xmlns:msxsl="urn:schemas-microsoft-com:xslt" />	<xsl:variable name="z">
<xsl:for-each select="MPayPremium/record">
<span>
<xsl:value-of select="number(premiumspayed)"/>
</span>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(msxsl:node-set($z)/span)" xmlns:msxsl="urn:schemas-microsoft-com:xslt" />	
</xsl:template>
</xsl:stylesheet>
导出的Excel效果如下:
11. Ajax审核功能
审核功能,通过Ajax去访问服务器端的WebService 并传递相应的参数来实现对指定的表单进行审核的功能。
示例:
//应付佣金
if (type == "MPayCommission") {
if (confirm('确认要审核此记录吗?')) {
$.ajax({
type: "POST",
contentType: "application/json",
url: ServiceAddress + "/Report_Service.asmx/MonthReportHandle",
data: "{month:'" + month + "',agent:'" + agent + "',product:'" + product + "',type:'" + type + "'}",
dataType: 'json',
success: function(result) {
if (result.d == 'y') {
CallMppTable();
alert("提交成功!谢谢。");
}
else {
alert("提交失败!请参考下面提示:"n" + result.d);
}
}
});
}
else {
}
}
验证效果如下:
三、 开发工具环境
1. 开发工具
推荐使用VSTS 2008 Sp1 你可以直接双Sln 文件即可打开并此项目进行编辑和运行,所需要的一切都在项目中准备好了
四、 发布部署的环境
1. Windows 2003/2008 系统的PC主机
2. Web 服务器
IIS6 支持
IIS7 支持
Apache 支持
3. 客户端
IE7 支持
IE8 支持
FF 不支持
IE6 不支持
五、 开发中要注意的问题
1. 兼容性
Web开发兼容性一直是一个问题,特别是对IE6和FF的支持,需要花费一定的很久的时间,以及做很多的代码判断来实现。
现在我们的报表系统仅在IE7 和IE 8下面显示完全正常
2. Ajax跨域的访问资源
众所周知,对于浏览器跨域访问其他服务器下面的信息是存在安全控制的,主要分两类情况:
一、基于同一父域的子域之间页面的访问
1、taobao.com
2、jipiao.taobao.com
3、promotion.taobao.com
它们有相同的父域 taobao.com
二、基于不同父域页面之间的访问
1、taobao.com
2、baidu.com
3、sina.com.cn
它们具有不同的父域。
那么这两种情况都有不同的解决方法,比如嵌入iframe,jsonp什么的,现在报表系统不支持跨域。
3. 窗口自适应
窗口的高度自适应使用了javaScript 来控制的,从而达到在有数据的时候可以拉伸,没有数据的时候高度固定的目的。
4. 界面缓存
在加载XML数据文件的时候,如果重复加载会出现无法获得更新的数据问题,所以我在每个地址的后面加入了时间参数,以规避地址重复的问题,骗过浏览器进行数据更新
5. 使用了 jQuery 库
为了方便操作,我使用了jQuery库