13. 练习题 IMPOTS 配合 XML
在这个我们已经研究过多次的练习中,服务器以 XML 流的形式将结果返回给客户端。
13.1. 服务器(impots_05B_web)
之前编写的税款计算 Web 服务采用分层架构:
![]() |
在前面的示例中,Web 服务会向其客户端发送以下两行中的任意一行:
这并非一个格式正确的 XML 文档,因为它缺少根标签。新的 Web 服务将以以下形式发送响应:
或
在这两种情况下,响应都是格式正确的 XML 文档,可由 [simpleXML] 模块进行处理。
在三层架构中,仅需修改 [web] 层。其代码 [impots_05B_web] 将变为:
<?php
// 业务层
require_once "impots_05_metier.php";
// 错误管理
ini_set("display_errors", "off");
// 头部UTF-8
header("Content-Type: text/plain; charset=utf-8");
// ------------------------------------------------------------------------------
// 税务网络服务
// 常量定义
$HOTE = "localhost";
$PORT = 3306;
$BASE = "dbimpots";
$USER = "root";
$PWD = "";
// 计算税款所需的数据已放入表 mysqL $TABLE
// 该表属于数据库 $BASE。该表的结构如下
// 范围 decimal(10,2),coeffR decimal(6,2),coeffN decimal(10,2)
// 纳税人的参数(婚姻状况、子女数量、年薪)
// 由客户以 params=婚姻状况, 子女数量, 年薪 的形式发送
// 结果(婚姻状况、子女数量、年薪、应缴税款)将返回给客户端
// 以 <税款>税款</税款> 的形式
// 或以 <错误>错误</错误> 的形式返回,如果参数无效
// 在会话中检索 [métier] 层
session_start();
if (!isset($_SESSION['metier'])) {
// 实例化 [dao] 层和 [métier] 层
try {
$_SESSION['metier'] = new ImpotsMetier(new ImpotsDaoWithMySQL($HOTE, $PORT, $BASE, $USER, $PWD));
} catch (ImpotsException $ie) {
print "<reponse><erreur>Erreur : " . utf8_encode($ie->getMessage() . "</erreur></reponse>");
exit;
}
}
$metier = $_SESSION['metier'];
// 获取客户端发送的行
$params = utf8_encode(htmlspecialchars(strtolower(trim($_POST['params']))));
//print "接收到的参数 --> $params\n";
$items = explode(",", $params);
// 参数数量应仅为 3 个
if (count($items) != 3) {
print "<reponse><erreur>[$params] : nombre de paramètres invalides</erreur></reponse>\n";
exit;
}//if
// 第一个参数(婚姻状况)必须为是/否
$marié = trim($items[0]);
if ($marié != "oui" and $marié != "non") {
print "<reponse><erreur>[$params] : 1er paramètre invalide</erreur></reponse>\n";
exit;
}//if
// 第二个参数(子女数)必须是整数
if (!preg_match("/^\s*(\d+)\s*$/", $items[1], $champs)) {
print "<reponse><erreur>[$params] : 2ième paramètre invalide</erreur></reponse>\n";
exit;
}//if
$enfants = $champs[1];
// 第三个参数(工资)必须为整数
if (!preg_match("/^\s*(\d+)\s*$/", $items[2], $champs)) {
print "<reponse><erreur>[$params] : 3ième paramètre invalide</erreur></reponse>\n";
exit;
}//if
$salaire = $champs[1];
// 计算税额
$impôt = $metier->calculerImpot($marié, $enfants, $salaire);
// 返回结果
print "<reponse><impot>$impôt</impot></reponse>\n";
// 结束
exit;
Web 服务的响应格式在第 35、47、53、58、64 和 71 行进行了修改。
13.2. 客户端(client_impots_05b_web)
客户端已进行修改以适应新的响应格式。使用 [simpleXML] 来处理该响应:
<?php
// 税务客户
// 错误处理
ini_set("display_errors", "off");
// ---------------------------------------------------------------------------------
// 一个实用函数类
class Utilitaires {
...
}
// main -----------------------------------------------------
// 常量定义
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
// 服务器数据
$HOTE = "localhost";
$PORT = 80;
$urlServeur = "/exemples-web/impots_05B_web.php";
...
exit;
function calculerImpot($HOTE, $PORT, $urlServeur, &$cookie, $params) {
// 将客户端连接到 ($HOTE,$PORT,$urlServeur)
// 如果 $cookie 不为空,则发送该 Cookie。$cookie 通过引用传递
// 将 $params 发送至服务器
// 处理结果行
...
// 读取结果行
$ligne = fgets($connexion, 1000);
// 关闭连接
fclose($connexion);
// 计算结果
$xml = new SimpleXMLElement($ligne);
$erreur = isset($xml->erreur) ? $xml->erreur : "";
$impôt = isset($xml->impot) ? $xml->impot : "";
// 返回
return array($erreur, $impôt);
}
- 第 32 行:读取服务器的响应。这是一个 XML 文档。
- 第 36 行:根据接收到的 XML 文档构建 SimpleXML 对象。
- 第 37 行:可能的错误消息
- 第 38 行:可能的税额
