给定如下XML文档:
<?xml version="1.0" encoding="utf-8"?>
<table border="1" id="books">
<tr bgcolor="green">
<th id="ISBN">书号</th>
<th id="title">书名</th>
<th id="price">价格</th>
</tr>
<tr id="add_update_XML">
<td>
<input type="text"/>
</td>
<td>
<input type="text"/>
</td>
<td>
<input type="text"/>
</td>
</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>
现提出如下设计需求:
测试用户期望功能如下:
功能模块中的核心业务是:删除特定图书信息并保存XML源文件。
核心业务流程描述如下:
基于三层架构视角的文件包及文件设计如表18.1所述。
序号 | 包设计 | 文件设计 |
---|---|---|
1 | 设计表示层包(包名:UI),抽象表示层文件容器。 |
|
2 | 设计业务逻辑层包(包名:server),抽象业务层文件容器。 |
|
3 | 设计数据层包(包名:data),抽象数据层文件容器。 |
|
基于XML格式数据的操作往往集成在一起,因此,XML文档的设计与改进应与前面章节一样。
具体创新改进后的XML文档如下:
<?xml version="1.0" encoding="utf-8"?>
<table border="1" id="books">
<tr bgcolor="green">
<th id="ISBN">书号</th>
<th id="title">书名</th>
<th id="price">价格</th>
</tr>
</tr><tr id="old_data">
</tr>
<tr id="add_update_XML">
<td>
<input class="edit_data" style="color:blue" type="text"/>
</td>
<td>
<input class="edit_data" style="color:blue" type="text"/>
</td>
<td>
<input class="edit_data" style="color:blue" type="text"/>
</td>
<td>
<input type="button" value="提交新数据" onclick="post_new_XMLdata()"/>
<input type="button" value="取消" onclick="$('tr').hide()"/>
</td>
</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>
由于id="add_update_XML"的<tr>已事先设定在XML文档中,可从后台读取到前端并在网页中可视化,该<tr>标记中所定义的用户输入接口,既可用于添加数据,也可用于修改数据。
文件功能说明见表18.2所述。
序号 | 文件(夹)名 | 作用 |
---|---|---|
1 | books.xml | 用于测试的XML基础数据 |
2 | Server.js | NodeJS后台服务通用逻辑 |
3 | Server_17.js | 服务当前应用的后台核心代码 |
4 | jquery-1.11.1.js | 加载JQuery函数库 |
5 | main.html | 用户界面主页 |
6 | Data | 存放XML数据文件的文件夹 |
7 | server | 存放业务逻辑层文件的文件夹 |
8 | UI | 存放表示层文件的文件夹 |
9 | xmldom | 安装xmldom模块产生的文件夹 |
10 | xpath | 安装xpath模块产生的文件夹 |
11 | Z_doc | 辅助文档,不参与代码运行 |
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h2>标记数据删除测试</h2>
<hr />
请输入书名<input type="text" id="title_input" />
<input type="button" value="模糊查询图书" onclick="select_TagData()" />
<hr />
<input type="button" value="恢复数据为初始状态" onclick="restore_TagData()" />
<hr />
<div id="outer_div">
</div>
</body>
</html>
<script type="text/javascript" src="jquery-1.11.1.js"></script>
<script type="text/javascript">
//基于XPath的标记数据模糊查询
function select_TagData() {
var book_name = $("#title_input").val();
var xhttp = new XMLHttpRequest();
xhttp.open("post", "http://localhost:1017/mhFind_18?param=" + encodeURIComponent(book_name), true);
xhttp.onreadystatechange = function () {
if (xhttp.status == 200 && xhttp.readyState == 4) {
$("#outer_div").html("<table border='1'>" + xhttp.responseText + "</table>");
$("#old_data").hide();
$("#add_update_XML").hide();
var trs = $("tr");
for (var k = 3; k < trs.length; k++) {
trs[k].innerHTML = trs[k].innerHTML + '<td><input type="button" value="删除" onclick="exe_delete(this)" /></td>';
}
}
}
xhttp.send();
}
//执行删除
function exe_delete(obj) {
//获取关键字
var cur_tr = $(obj).parent().parent();
var key_isbn = cur_tr.find("td")[0].innerHTML;
if (confirm("确认要删除书号为" + key_isbn+"的图书信息吗?")) {
//提交关键字到后台
var xhttp = new XMLHttpRequest();
xhttp.open("post", "http://localhost:1017/postDelete_18?param1=" + encodeURIComponent(key_isbn), true);
xhttp.onreadystatechange = function () {
if (xhttp.status == 200 && xhttp.readyState == 4) {
alert(xhttp.responseText);
}
}
xhttp.send();
}
}
//恢复数据
function restore_TagData() {
if (confirm("确定要将数据恢复到最初状态?")) {
var xhttp = new XMLHttpRequest();
xhttp.open("post", "http://localhost:1017/restoreData_18", true);
xhttp.onreadystatechange = function () {
if (xhttp.status == 200 && xhttp.readyState == 4) {
alert(xhttp.responseText);
}
}
xhttp.send();
}
}
</script>
// 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("./18/server/server_18.js")(request, response, req_head, Q_obj, fs_obj);
//%%%%%%%%%%%%%-------------end your code
});
server.listen(1017);
console.log("Server is running at port 1017...");
function server_18(request, response, req_head, Q_obj, fs_obj) {
//%%%%%%%%%%%%%------------begin your code
if (req_head == "/mhFind_18") {
//模糊查询
var b_title = Q_obj["param"];
var b_xpath = "/table/tr[position()<4] | /table/tr[contains(td[2],'" + b_title + "')]";
var select = require("./xpath");//获取查询函数
var dom = require("./xmldom").DOMParser;//获取DOMParser类
fs_obj.readFile("./18/data/books.xml", "utf-8", function (err, data) {
if (err) { response.end(err); }
else {
var xmldom = new dom().parseFromString(data);
var nodes = select(xmldom, b_xpath);
if (nodes.length < 4) { response.end("未找到相关数据!"); }
else { response.end(nodes.toString()); }
}
});
return;
}
//以下删除XML文档片断
if (req_head == "/postDelete_18") {
var old_isbn = Q_obj["param1"];
fs_obj.readFile("./18/data/books.xml", "utf-8", function (err, data) {
if (err) { response.end(err); }
else {
var dom = require("./xmldom").DOMParser;
var XMLdom = new dom().parseFromString(data);
var tr_doms = XMLdom.getElementsByTagName("tr");
for (var k = 2; k < tr_doms.length; k++) {
var temp_isbn = tr_doms[k].getElementsByTagName("td")[0].textContent;
if (temp_isbn == old_isbn) {
tr_doms[k].parentNode.removeChild(tr_doms[k]);
var new_XMLtext = '<?xml version="1.0" encoding="utf-8"?>\n';
new_XMLtext += '<table border="1" id="books">\n';
new_XMLtext += tr_doms.toString() + "\n</table>";
fs_obj.writeFile("./18/data/books.xml", new_XMLtext, function (err) {
if (err) { response.end(err); }
else { response.end("成功删除数据"); }
});
break;
}
}
}
});
return;
}
if (req_head == "/restoreData_18") {
fs_obj.readFile("./18/data/books_bak.xml", "utf-8", function (err, data) {
if (err) { response.end(err.toString()); }
else {
fs_obj.writeFile("./18/data/books.xml", data, function (err) {
if (err) { response.end(err.toString()); }
else { response.end("成功恢复数据"); }
});
}
});
return;
}
//%%%%%%%%%%%%%-------------end your code
}
module.exports=server_18
数据删除前模糊查询如图18.2所示。
数据删除进行中如图18.3所示。
问题提出:删除XML节点的主要技术要点是什么?
问题思考:
给定如下XML文档:
<?xml version="1.0" encoding="utf-8"?>
<table border="1" id="books">
<tr style="background-color:greenyellow">
<th id="s_id">学号</th>
<th id="name">姓名</th>
<th id="age">年龄</th>
</tr>
<tr id="add_update_XML">
<td>
<input type="text"/>
</td>
<td>
<input type="text"/>
</td>
<td>
<input type="text"/>
</td>
</tr>
<tr>
<td>5744885</td>
<td>Max</td>
<td>18</td>
</tr>
<tr>
<td>2323885</td>
<td>Jack</td>
<td>17</td>
</tr>
<tr>
<td>8888</td>
<td>Roseg</td>
<td>18</td>
</tr>
<tr>
<td>8767885</td>
<td>Json</td>
<td>19</td>
</tr>
<tr>
<td>64547565647689</td>
<td>张三</td>
<td>16</td>
</tr>
<tr>
<td>45634748758478</td>
<td>李四</td>
<td>19</td>
</tr>
<tr>
<td>675665647689</td>
<td>王五</td>
<td>18</td>
</tr>
<tr>
<td>2342353758478</td>
<td>刘六</td>
<td>20</td>
</tr>
</table>
现提出如下设计需求: