在HTML,JSP当中使用XML与XSL展示部分数据
需求分析:
通常项目当中有一些固化或不经常变化的内容,且这些内容通常是使用XML保存。
但在前台页面上需要使用到这些数据,而且有可能会将其中的内容做为网页的一部分用来展示给用户。通常的做法是使用JavaScript读取这个XML进行解释,然后再创建相应的HTML标签,并将内容插入相应的位置上。这种做法不但需要编写大量的JS,而且会影响页面加载速度。如果利用XML+XSL进行数据的格式转化,再利用JS动态加载XML与XSL,便可以很方便的获取所需的数据,而且调用不同的XSL,可以展示不同的格式。
所牵涉到的基本技术:
1:XML
2:XPATH
3:JavaScript
先看一个示例:
如图
- <root>
- <!-- i_ID,n_名称,p_上一级ID,s_是否有下级 -->
- <a i="107" n="安徽省" p="0" s="false"/>
- <a i="93" n="北京市" p="0" s="false"/>
- <a i="103" n="北京市" p="93" s="false"/>
- <a i="77" n="长宁区" p="67" s="true"/>
- <a i="105" n="朝阳区" p="103" s="false"/>
- <a i="91" n="崇明县" p="67" s="true"/>
- <a i="89" n="奉贤区" p="67" s="true"/>
- <a i="108" n="福建省" p="0" s="false"/>
- <a i="109" n="甘肃省" p="0" s="false"/>
- <a i="110" n="广东省" p="0" s="false"/>
- <a i="101" n="广西区" p="0" s="false"/>
- <a i="111" n="贵州省" p="0" s="false"/>
- <a i="112" n="海南省" p="0" s="false"/>
- <a i="130" n="合肥市" p="107" s="false"/>
- <a i="113" n="河北省" p="0" s="false"/>
- <a i="114" n="河南省" p="0" s="false"/>
- <a i="102" n="黑龙江" p="0" s="false"/>
- <a i="80" n="虹口区" p="67" s="true"/>
- <a i="97" n="湖北省" p="0" s="false"/>
- <a i="96" n="湖南省" p="0" s="false"/>
- <a i="75" n="黄浦区" p="67" s="true"/>
- <a i="115" n="吉林省" p="0" s="false"/>
- <a i="85" n="嘉定区" p="67" s="true"/>
- <a i="116" n="江苏省" p="0" s="false"/>
- <a i="117" n="江西省" p="0" s="false"/>
- <a i="86" n="金山区" p="67" s="true"/>
- </root> <!-- 演示数据,与图片所示有所不同-->
以上是一个地区的XML文档,其中包含了三级省市区数据,通过属性"p"来寻找上一级,如果p=0,则代表当值数据为省份(顶级)
- <?xml version="1.0" encoding="UTF-8"?>
- <!--定义当前XML文档为xsl格式-->
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <!--math表示匹配当前XML所有内容,也可以指定具体的某些值,取值方式参考XPATH语法-->
- <xsl:template match="/">
- <!--在此可以编写HTML代码-->
- <h2>地区下拉表</h2>
- <div>
- <div>省市:</div>
- <div>
- <select>
- <!--读取root下所有属性p=0的a标签,进行循环-->
- <xsl:for-each select="root/a[@p='0']">
- <!--对于需要给HTML标签赋值时,只能使用{}来取值,
- 不可以使用<xsl:value-of>的形式取值。这里取的是当前标签的i属性的值,
- 因为是在循环里,所以每次取值都不同-->
- <option value="{@i}">
- <!--如果是在HTML内,或外面赋值,则只能使用<xsl:value-of>的形式取值,
- 这里取的是当前标签的n属性的值-->
- <xsl:value-of select="@n"/>
- </option>
- </xsl:for-each>
- </select>
- </div>
- </div>
- </xsl:template>
- </xsl:stylesheet>
三、在准备好了XML,XSL之后,剩下的事就是如何在页面上根据需要调用此XML文档来显示了,这里我们需要使用JS来加载XML与XSL并对其进行解析。由于IE与FF解析XML与XSL的方法及加载XML的方法不同,所以这里采用jquery框架进行判断,也可以自行写相关的方法以区别IE/FF的不同。
用到的两个最主要的方法
1:load(xmlPath) 所有方法都有部分代码基于jquery
- //兼容大部分浏览器 读取外部XML文档返回xmlDoc对象
- function load(x) {
- var xmlDoc;
- if ($.browser.msie) {
- xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
- xmlDoc.async = false;
- xmlDoc.load(x);
- return xmlDoc;
- } else if ($.browser.safari) {
- xmlDoc = getxml(x).responseXML;
- return xmlDoc;
- } else if ($.browser.mozilla) {
- xmlDoc = document.implementation.createDocument('', '', null);
- xmlDoc.async = false;
- xmlDoc.load(x);
- return xmlDoc;
- } else {
- xmlDoc = getxml(x).responseXML;
- return xmlDoc;
- }
- }
- //供load方法调用
- function getXmlHttp() {
- var xmlhttp;
- if (window.ActiveXObject) {
- try {
- xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
- }
- catch (e) {
- xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- return xmlhttp;
- } else if (window.XMLHttpRequest) {
- xmlhttp = new XMLHttpRequest();
- return xmlhttp;
- }
- return xmlhttp;
- }
- //供load方法调用
- function getxml(x) {
- var xmlhttp = getXmlHttp();
- if (xmlhttp != null) {
- xmlhttp.open("GET", x, false);
- xmlhttp.send(null);
- return(xmlhttp);
- } else {
- alert("对不起,您的浏览器不支持 XMLHTTP.11");
- return false;
- }
- }
2:showXML() 在网页上显示XML内容,并使用相应的XSL进行解析
<!--EndFragment-->
- /**
- * 加载XML及对应的XSL文档,直接在页面上进行显示
- * @param xml XML路径
- * @param xsl XML样式文件
- */
- function showXML(xml, xsl) {
- // Load XML 这里的load方法调用的是上面的laod方法
- var xmlDoc = load(xml);
- // Load XSL
- var xslDoc = load(xsl);
- // 如果是非IE浏览器,则对解析器进行重写
- if (!$.browser.msie) {
- Node.prototype.transformNode = function (oXslDom) {
- var oProcessor = new XSLTProcessor();
- oProcessor.importStylesheet(oXslDom);
- var oResultDom = oProcessor.transformToDocument(this);
- var xmls = new XMLSerializer();
- var sResult = xmls.serializeToString(oResultDom);
- if (sResult.indexOf(" <transformiix:result") > -1) {
- sResult = sResult.substring(sResult.indexOf(">") + 1, sResult.lastIndexOf(" <"));
- }
- return sResult;
- };
- }
- document.write(xmlDoc.transformNode(xslDoc));
- }
四、到此所有准备工作已完成,可以开始编写 HTML代码,当前你也可以将这此内容放入其它的页面当中如JSP/ASP
<!--EndFragment-->
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>Simple jsp page</title></head>
- <script type="text/javascript" src="/js/serv/comm/jquery.js"></script>
- //这个JS包含有上面的laod等方法
- <script type="text/javascript" src="/js/public/comm.js"></script>
- <body>
- <script type="text/javascript">
- showXML("/x/comm/area.xml","/test/xml/area.xsl");
- </script>
- </body>
- </html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Simple jsp page</title></head>
<script type="text/javascript" src="/js/serv/comm/jquery.js"></script>
//这个JS包含有上面的laod等方法
<script type="text/javascript" src="/js/public/comm.js"></script>
<body>
<script type="text/javascript">
showXML("/x/comm/area.xml","/test/xml/area.xsl");
</script>
</body>
</html>
<!--EndFragment-->
<!--EndFragment-->
以下附件为整个文章涉及到的内容,但不能直接在本地打开浏览,原因是load方法不能直接读取本地文件,需要部署到项目当中。
有问题或有好的建议,欢迎大家一起探讨
<!--EndFragment-->
<!--EndFragment-->
<!--EndFragment-->
二、XSL文档
这是一个使用XML+XSL生成的地区下拉列表。
整个演示所需文档如下:
一、地区信息来自XML文档
Area.xml