给定如下XML文档:
现提出如下设计需求:
测试用户期望功能如下:
用户测试功能用例建模如图12.1所示。
XML文档分页浏览的核心业务描述如下:
核心业务数据流建模如图12.2所示。
基于三层架构视角的文件包及文件设计如表12.1所述。
序号 | 包设计 | 文件设计 |
---|---|---|
1 | 设计表示层包(包名:UI),抽象表示层文件容器。 |
|
2 | 设计业务逻辑层包(包名:server),抽象业务层文件容器。 |
|
3 | 设计数据层包(包名:data),抽象数据层文件容器。 |
|
文件包设计及文件关系如图12.3所示。
文件架构如图12.4所示。
文件(夹)功能说明见表12.3所述。
序号 | 文件(夹)名 | 作用 |
---|---|---|
1 | books.xml | 存放在后台用于测试的XML基础数据文件 |
2 | main.html | 实现人机交互的用户界面主页 |
3 | Server.js | NodeJS后台通用逻辑服务程序,动态引入Server_12.js模块。 |
4 | XML_page.js | 包含XML文档数据分页函数。 |
5 | jquery.js | JQuery函数库,辅助表示层数据可视化。 |
6 | D.xslt、A.xslt | 包含"降序"及"升序"逻辑的XSLT文件 |
7 | UI | 存放表示层文件的文件夹 |
8 | Server | 存放业务逻辑层文件的文件夹 |
9 | Data | 存放XML数据文件的文件夹 |
10 | Server_12.js | 当前模块后台服务专用逻辑 |
对应文件:main.html
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <style> .order_span{ cursor:pointer; font-size:8pt; font-weight:400; padding:3px; } </style> </head> <body> <h3>XML数据浏览测试</h3> <hr /> 【<span style="background-color:black;color:white">页面大小(每页显示记录</span> <select id="p_size" disabled="disabled" onchange='pagesize_change(xmldom, "p_size", "p_count","p_current", "result" )'> <option>3</option> <option>6</option> <option>9</option> </select><span style="background-color:black;color:white">条);</span> 共<input readonly="readonly" id="p_count" type="text" style="width:60px" />页; 当前是第<input readonly="readonly" id="p_current" type="text" value="1" style="width:60px"/>页】 <hr /> <input class="op_but" disabled="disabled" type="button" value="最前页" onclick='first_page(xmldom, "p_size", "p_count","p_current", "result" )' /> <input class="op_but" disabled="disabled" type="button" value="上一页" onclick='prior_page(xmldom, "p_size", "p_count","p_current", "result" )' /> <input class="op_but" disabled="disabled" type="button" value="下一页" onclick='next_page(xmldom, "p_size", "p_count","p_current", "result" )' /> <input class="op_but" disabled="disabled" type="button" value="最后页" onclick='last_page(xmldom, "p_size", "p_count","p_current", "result" )' /> <hr /> <div id="result"> </div> </body> </html> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="XML_page.js"></script> <script type="text/javascript" src="XSLT.js"></script> <script type="text/javascript" > //初始化,按默认参数显示图书信息 var xmldom; $(document).ready(function () { var xhr = new XMLHttpRequest(); xhr.open("post", "http://localhost:1017/viewAllbooks_12", true); xhr.onreadystatechange = function () { if (xhr.status == 200 && xhr.readyState == 4) { xmldom = $.parseXML(xhr.responseText); var book_count = xmldom.getElementsByTagName("tr").length - 1; var page_size = parseInt($("#p_size option:selected").text()); var page_count = Math.ceil(book_count / page_size); $("#p_count").val(page_count); $("#p_size").attr("disabled", false); $(".op_but").attr("disabled", false); display_cur_page(xmldom, "p_size", "p_count", "p_current", "result"); } } xhr.send(); }); //价格降序 function dd_view() { $.get("D.xslt", function (xsldom) { var cur_XMLtext = $("#result").html().replace("<tbody>", "").replace("</tbody>", ""); var cur_xmldom = $.parseXML(cur_XMLtext); displayXML(cur_xmldom, xsldom, "result"); }, "xml"); } //价格降序 function aa_view() { $.get("A.xslt", function (xsldom) { var cur_XMLtext = $("#result").html().replace("<tbody>", "").replace("</tbody>", ""); var cur_xmldom = $.parseXML(cur_XMLtext); displayXML(cur_xmldom, xsldom, "result"); }, "xml"); } </script>
对应文件:XML_page.js
//xmldom:XML文档对象 // page_size_id:调整页面大小的下拉列表 //page_count_id:显示页面总数 //page_current_id:当前正在浏览的页面号 // result_div_id:输出结果的div //显示当前页数据 function display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { var page_size = parseInt($("#" + page_size_id).val()); var cur_page = parseInt($("#" + page_current_id).val()); var begin_pos = (cur_page - 1) * page_size + 1; var end_pos = cur_page * page_size; var max_page = parseInt($("#" + page_count_id).val()); var trs = xmldom.getElementsByTagName("tr"); if (cur_page == max_page) { end_pos = trs.length - 1; } var table_str = "<table border='1'>"; table_str += trs[0].outerHTML; for (var k = begin_pos; k <= end_pos; k++) { table_str += trs[k].outerHTML; } table_str += "</table>"; $("#" + result_div_id).html(table_str); } //页面大小变化时 function pagesize_change(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { var book_count = xmldom.getElementsByTagName("tr").length - 1; var page_size = parseInt($("#" + page_size_id + " option:selected").text()); var page_count = Math.ceil(book_count / page_size); $("#" + page_count_id).val(page_count); $("#" + page_current_id).val("1"); display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id); } //下一页 function next_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { var page_count = parseInt($("#" + page_count_id).val()); var cu_page = parseInt($("#" + page_current_id).val()); cu_page++; if (cu_page > page_count) { alert("已到最后一页"); return; } else { $("#" + page_current_id).val(cu_page); display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id); } } //上一页 function prior_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { var cu_page = parseInt($("#" + page_current_id).val()); cu_page--; if (cu_page == 0) { alert("已到最前一页"); return; } else { $("#" + page_current_id).val(cu_page); display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id); } } //最前一页 function first_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { $("#" + page_current_id).val("1"); display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id); } //最后一页 function last_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id) { var page_count = parseInt($("#" + page_count_id).val()); $("#" + page_current_id).val(page_count); display_cur_page(xmldom, page_size_id, page_count_id, page_current_id, result_div_id); }
对应文件:XSLT.js
//以下是xsl格式化XML并输出结果到div function displayXML(xml, xsl, div_id) { // code for IE if (window.ActiveXObject) { ex = xml.transformNode(xsl); document.getElementById(div_id).innerHTML = ""; document.getElementById(div_id).innerHTML = ex; } // code for Chrome, Firefox, Opera, etc. else if (document.implementation && document.implementation.createDocument) { xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xsl); resultDocument = xsltProcessor.transformToFragment(xml, document); document.getElementById(div_id).innerHTML = ""; document.getElementById(div_id).appendChild(resultDocument); } }
对应文件:server.js
// JavaScript source code //------------请将这个文件保存为Unicode格式,否则麻烦大大的-------------- const http_obj = require("http");//用于产生服务对象 const fs_obj = require("fs");//读写后台文件 const url_tran_obj = require("url");//解释URL const server = http_obj.createServer(function (request, response) { //请求路径处理 var req_str = decodeURI(request.url); var req_head; var POS = req_str.indexOf("?"); if (POS == -1) { req_head = req_str; } else { req_head = req_str.substring(0, POS); } //设置查询对象 var url_obj = url_tran_obj.parse(req_str, true); var Q_obj = url_obj.query; //响应头设置 response.setHeader("Content-Type", "text/plain;charset=utf-8"); response.setHeader("Access-Control-Allow-Origin", "*");//实现跨域访问 response.writeHead(200); //%%%%%%%%%%%%%-----------begin your code require("./12/server/server_12.js")(request, response, req_head, Q_obj, fs_obj); //%%%%%%%%%%%%%------------end your code }); server.listen(1007); console.log("Server is running at port 1007...");
文件server_12.js实现代码:
function server_12(request, response, req_head, Q_obj, fs_obj) { if (req_head == "/viewAllbooks_12") { //代码1 fs_obj.readFile("./12/data/books.xml", "utf-8", function (err, data) { if (err) { response.end(err); } else { response.end(data); } }); } } module.exports = server_12
对应文件:D.xslt
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:template match="/"> <table border="1" id="books"> <tr style="background-color:greenyellow"> <th id="ISBN">书号</th> <th id="title">书名</th> <th id="price"> 价格 <span class="order_span" onclick="dd_view()">降序</span> <span class="order_span" onclick="aa_view()">升序</span> </th> </tr> <xsl:for-each select="table/tr[position()>1]"> <xsl:sort select="td[3]" order="descending" data-type="number"/> <tr> <td> <xsl:value-of select="td[1]"/> </td> <td> <xsl:value-of select="td[2]"/> </td> <td> <xsl:value-of select="td[3]"/> </td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
对应文件:A.xslt
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:template match="/"> <table border="1" id="books"> <tr style="background-color:greenyellow"> <th id="ISBN">书号</th> <th id="title">书名</th> <th id="price"> 价格 <span class="order_span" onclick="dd_view()">降序</span> <span class="order_span" onclick="aa_view()">升序</span> </th> </tr> <xsl:for-each select="table/tr[position()>1]"> <xsl:sort select="td[3]" order="ascending" data-type="number"/> <tr> <td> <xsl:value-of select="td[1]"/> </td> <td> <xsl:value-of select="td[2]"/> </td> <td> <xsl:value-of select="td[3]"/> </td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
对应文件:books.xml
<?xml version="1.0" encoding="utf-8"?> <table border="1" id="books"> <tr style="background-color:greenyellow"> <th id="ISBN">书号</th> <th id="title">书名</th> <th id="price"> 价格 <span class="order_span" onclick="dd_view()">降序</span> <span class="order_span" onclick="aa_view()">升序</span> </th> </tr> <tr> <td>5744885</td> <td>Java programming</td> <td>80</td> </tr> <tr> <td>2323885</td> <td>C# programming</td> <td>87</td> </tr> <tr> <td>8888</td> <td>Python programming</td> <td>68</td> </tr> <tr> <td>8767885</td> <td>NodeJS</td> <td>90</td> </tr> <tr> <td>r64547565647689</td> <td>C++ programming</td> <td>68</td> </tr> <tr> <td>45634748758478</td> <td>MongoDB</td> <td>90</td> </tr> <tr> <td>675665647689</td> <td>operation system</td> <td>68</td> </tr> <tr> <td>2342353758478</td> <td>XML技术</td> <td>90</td> </tr> </table>
降序实现效果如图12.5所示。
序升实现效果如图12.6所示。
问题:通过以上实例演示,在基于三层架构分页浏览XML数据时,动态调用XSLT模板格式化XML数据实现表格内嵌式排序的技术要点是什么?
思考(知识归纳):
给定如下XML文档:
现提出如下设计需求:
仿照本章案例完成相关设计并实现相关功能。