使用 XML 和 PHP 创建一个更具适应性的电话簿和通讯录

使用 XML 为您的电话提供一个一致的通讯录

Colin Beckingham

2011 年 5 月 09 日发布

您需要与联系人随时保持联系 — 即使在出差途中。在办公室,可以使用您的桌面 VoIP 电话;出差途中,可以使用智能电话。但每台设备都要求其电话列表采用一种特殊格式,每台设备都有自己的、格式与众不同的通讯录或电话簿。如果有必要,可能需要输入您的所有联系人两次 — 每个通讯录一次 — 每次变更联系人时,都需要同时在两个列表中进行更改。毫无疑问,您肯定希望这两部电话从同一个后端数据源获取数据,这样您就只需在一个地方编辑姓名和电话号码。这不成问题:只要能访问互联网或内联网。在本文中,了解如何使用一个 MySQL 数据库中的数据向两个完全不同的设备提供联系信息:一部通过 snom 300 系列设备标识的 VoIP 电话和一个采用 Nokia E71 设备形状的智能电话(参见 参考资料 中的链接)。

桌面设备:snom 300 系列

常用缩略词HTML:超文本标记语言

HTTP:超文本传输协议

LAN:局域网

LDAP:轻量级目录访问协议

SQL:结构化查询语言

VoIP:IP 语音传输

XML:可扩展标记语言

snom 300 系列提供优质稳定的 VoIP 电话,这些电话拥有广泛的办公功能,比如等待、转接和电话会议。这类电话的确拥有对来自 LDAP 服务器的数据提要的原生支持,它还拥有一个能阅读 HTML 的微型浏览器(参见 参考资料)。它甚至能以一种能够触发电话呼叫的格式在电话屏幕上显示文本。

清单 1 展示 snom 微型浏览器需要(特别是在电话簿上下文中)的 XML 格式的示例。

清单 1. snom XML 微型浏览器示例<?xml version="1.0" encoding="UTF-8"?>

PhoneList - Snom

Friend, First

555-456-7890

Person, Second

555-654-0987

F1

Dial

F_ENTER

在这段代码中,根元素 SnomIPPhoneDirectory 拥有 3 个不同子元素:Title、DirectoryEntry 和 SoftKeyItem。标题位于电话显示的顶部,滚动过程中不间断显示。标题下方是目录条目 — 每行一个条目 — 且能够滚动。这些软键项目关联到显示下方的 4 个按钮。这些能执行一些功能,比如对当前突出显示的目录条目发起一个呼叫。这个示例中的数据包含两个电话号码条目:一个显示姓名和一个用于拨号的号码。它只激活一个按钮:按下 F1 按钮,电话就开始拨号。

旅行设备:Nokia E71 智能电话

Nokia E71 设备是一个典型现代智能电话示例。它能够连接无线 WAN 或移动电话服务,拥有一个 Session Initiation Protocol (SIP) 客户端,能使用自己的本机浏览器浏览 Internet,并以移动方式管理语音通信。

E71 设备支持 Wireless Application Protocol (WAP) 版本 2.0(WAP2 — 参见 参考资料)— 不要与 Wi-Fi Protected Access II (WPA2) 功能混淆。这意味着它能阅读 XML 格式文件,这类文件在电话内部与各种专业功能通信,比如打开一个窗口来发起一次呼叫。

清单 2 展示了这种智能电话需要的 WAP2/XML 格式内容示例。这个示例使用 清单 1 中显示的那两个虚构条目。

清单 2. WAP2 XML 示例<?xml version="1.0"?>

/p>

"http://www.wapforum.org/DTD/wml_1.1.xml" >

Tel (WTAI): Friend, First

Tel (WTAI): Person, Second

WAP2 要求以卡片组的形式显示数据。根元素 拥有一个子元素 (或页面),该子元素有两行,通过一个换行符分隔。这个页面的标题在这个根元素的一个属性中列示。这些电话号码在一些锚点元素(即 )中列示,有一个 属性使用 Wireless Telephony Applications Interface(WTAI — 参见 参考资料)。当您打开电话的浏览器中的页面并单击一个电话链接时,一个窗口将弹出并询问您是否要呼叫这个号码,这时电话找到一条路径来路由呼叫 — 无论是通过一条无线 LAN 还是使用另一个电话订阅。

由于智能电话没有处理 LDAP 的原生能力且桌面电话不能处理 WAP2,它们似乎没有什么共同点。但是,编写脚本通过使用 XML 的适应性提供了一种解决方案。您可能会找到一种方法,通过智能电话同步您的联系人和 LDAP 服务器,但这种方法可能不如直接访问信息那么简捷。幸运的是,尽管 XML 的格式在这两种架构之间可能会更改,但数据在根本上是相同的。

解决方案

鉴于这两种设备均可随时随地访问 Internet,实现一个通用电话簿的解决方案是将所有数据放置在一个数据库中,然后使用一个脚本引擎生成一个 XML 文件,并将其传递给您认为最方便的设备浏览器。另外,这个脚本能根据需要控制访问权并过滤要交付的信息。

数据库

数据可以存储为各种格式并根据需要提取,包括 PostgreSQL、XML、纯文本、IBM® DB2® 等。清单 3 展示了一个 MySQL 样例架构。

清单 3. 示例数据库架构CREATE TABLE IF NOT EXISTS 'mycontacts' (

'id' int(11) NOT NULL auto_increment,

'firstName' varchar(30) default NULL,

'lastName' varchar(30) default NULL,

'number' varchar(20) default NULL,

PRIMARY KEY ('id')

) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;

这个表只包含 4 个字段 — 一个 ID、姓名、电话号码 — 以及一个索引。该架构显示了所需要信息的关键组成部分。可以根据需要进一步添加字段和索引。可以根据需要采用您选择的 LibreOffice Base 或 phpMyEdit(参见 参考资料)编辑器编辑数据内容。

PHP 生成器

清单 4 展示了一个从后端获取数据并以纯文本格式显示输出的基本脚本。此时,您只是测试脚本,确保它返回合理的数据。

清单 4. 基本数据库生成器<?php

$dev = "";

$db_host = "your.database.server";

$db_user = "your_user";

$db_pass = "your_password";

$db_name = "your_database";

$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);

if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");

$query = "SELECT * FROM mycontacts order by lastName asc";

$result = $mysqli->query($query);

$num = $result->num_rows;

$i = 0;

while ($row = $result->fetch_array()) {

$myarr[$i]['first']=$row["firstName"];

$myarr[$i]['last']=$row["lastName"];

$myarr[$i]['phone']=$row["number"];

$i++;

}

$mysqli->close();

switch ($dev) {

case 'snom':

echo mysnom($myarr);

break;

case 'noki':

echo mynoki($myarr);

break;

default:

echo mytest($myarr);

break;

}

function mytest($myarr) {

$cont = "Header\n";

foreach ($myarr as $a) {

$cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n";

}

$cont .= "Footer\n";

return $cont;

}

function show_err($dev,$msg) {

die($msg);

}

?>

这段代码首先定义用于访问数据库的变量,打开一个连接,返回一个结果集或一条错误消息(如果不能连接到数据库的话)。然后,一个 while 循环迭代数据集,在一个方便的数组中存储信息以便将来进行显示。由于设备变量 $dev 被初始化为一个长度为零的字符串,因此,当 switch 执行时,它将切换到默认值并调用 mytest() 函数。这个函数将显示一个简单的标题,写出数组内容,然后打印一个页脚 — 全部采用纯文本格式。

这个脚本只处理一个可能的错误:数据库连接故障。您应计划处理其他情况,比如成功连接到数据库但发现一个空表。您可以使用 show_err()

函数调用之类的调用捕获并处理这些情况。

大多数组件都已就绪,可以泛化这个脚本,处理其他设备类型。switch 拥有针对这两种电话的情况,但它们的功能还不存在。现在的问题是如何使输出与其他目标设备相关,根据需要添加 XML 格式的细节。

桌面微型浏览器

对照 清单 1 中的示例,您将看到,清单 5 中的函数添加了必要的组件来处理桌面 VoIP 电话。

清单 5. 处理桌面微型浏览器的函数function mysnom($myarr) {

$cont = "<?xml version=\"1.0\"?>

MySQL Directory";

foreach ($myarr as $a) {

$cont .= "

".$a['first']." ".$a['last']."

".$a['phone']."

\n";

}

$cont .= "\n";

return $cont;

}

function show_err($dev,$msg) {

switch ($dev) {

case 'snom':

echo "<?xml version=\"1.0\"?>

$msg

";

break;

default:

echo $msg;

break;

}

die();

}

对比 清单 5 和 清单 4,您会发现,这些新函数并不回显纯文本,而是回显微型浏览器预期的元素中封装的数据。mysnom() 函数是脚本的一个新增函数,show_err() 函数是一个替代函数。

微型浏览器不能显示纯文本:它什么也不做。因此,常规和异常输出都需要 XML 输出。由于您正在使用电话,因此电话也是错误消息必须显示的地方。如果出现数据库连接故障,脚本将向电话报告错误。如果成功连接,则在 while 循环开始之前,脚本应声明根元素。循环进行时,每条记录都被封装到记录自己的目录条目标记中;循环完成后,按钮的设置就开始了。由于只有 4 个按钮,是否也需要在数据库中对其进行编码还存在疑问。最后,代码结束了根元素。

上述函数要正常工作,必须在代码开头按如下方式正确设置变量 $dev:$dev = "snom";

智能电话 WAP2

如果是 Nokia 电话,则需要提供一些输出细节,它们通过 WTAI 引用以 WAP2 格式向智能电话提供 XML。清单 6 显示了相关代码。

清单 6. 处理智能电话 WAP2 的函数function mynoki($myarr) {

$cont = "<?xml version=\"1.0\"?>

"-//WAPFORUM//DTD WML 1.1//EN\"

\"http://www.wapforum.org/DTD/wml_1.1.xml\" >

\n

\n";

foreach ($myarr as $a) {

$cont .= "\nTel (WTAI):

".$a['last']." ".$a['first']."
";

}

$cont .= "\n";

return $cont;

}

同样,这段代码向 Nokia 电话提供必要的 XML。如果出现数据库连接错误,文本输出不需要封装到任何标记中,因为简单输出无需任何标记即可在此电话上正确显示。当电话簿条目被显示时,在循环开始之前,脚本发送 XML 和 DOCTYPE 信息,然后是 根元素和 元素的开始标记。然后,循环开始,显示封装在 WTAI 信息中的每条记录。最后,代码结束 card 元素和 根元素。

上述函数要正常工作,必须在代码开头按如下方式正确设置变量 $dev:$dev = "noki";

请注意,Nokia E71 通讯录的解决方案建议并不打算完全替代原有联系人应用程序,后者作为电话系统的一部分,肯定有一定优点,因此能与其他应用程序形成紧密的内部连接。但是,原有通讯录可以使用同一流程从同一 MySQL 数据库生成,但生成 vCard (VCF) 文件格式(参见 参考资料)的中间输出,这样便于导入电话。

检测设备

这个问题的最后部分是让脚本在运行时了解需要哪种设备输出。可以通过几种方法完成此任务,其中一种方法是在 HTTP 请求查询字符串中发送 GET 信息。假设您发送以下请求,显式声明一个设备和一个用户:http://www.myserver.tld/phonebook/myscript.php?device=snom&user=jim

然后,清单 7 中的最终脚本解析查询字符串并在运行时将信息插入脚本。

清单 7. 检测设备<?php

if ($_GET['user'] != 'jim') show_err($dev,'Unauthorised access');

$dev = $_GET['device'];

$db_host = "your.database.server";

$db_user = "your_user";

$db_pass = "your_password";

$db_name = "your_database";

$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);

if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");

$query = "SELECT * FROM mycontacts order by lastName asc";

$result = $mysqli->query($query);

$num = $result->num_rows;

$i = 0;

while ($row = $result->fetch_array()) {

$myarr[$i]['first']=$row["firstName"];

$myarr[$i]['last']=$row["lastName"];

$myarr[$i]['phone']=$row["number"];

$i++;

}

$mysqli->close();

switch ($dev) {

case 'snom':

echo mysnom($myarr);

break;

case 'noki':

echo mynoki($myarr);

break;

default:

echo mytest($myarr);

break;

}

function mytest($myarr) {

$cont = "Header\n";

foreach ($myarr as $a) {

$cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n";

}

$cont .= "Footer\n";

return $cont;

}

function mynoki($myarr) {

$cont = "<?xml version=\"1.0\"?>

"-//WAPFORUM//DTD WML 1.1//EN\"

\"http://www.wapforum.org/DTD/wml_1.1.xml\" >

\n

\n";

foreach ($myarr as $a) {

$cont .= "\nTel (WTAI):

".$a['last']." ".$a['first']."
";

}

$cont .= "\n";

return $cont;

}

function mysnom($myarr) {

$cont = "<?xml version=\"1.0\"?>

MySQL Directory";

foreach ($myarr as $a) {

$cont .= "

".$a['first']." ".$a['last']."

".$a['phone']."

\n";

}

$cont .= "\n";

return $cont;

}

function show_err($dev,$msg) {

switch ($dev) {

case 'snom':

echo "<?xml version=\"1.0\"?>

$msg

";

break;

default:

echo $msg;

break;

}

die();

}

?>

这段代码基本上是 清单 4 的重复,只是添加了 清单 5 和 清单 6 中的函数。代码首先进行一个简单检查,了解用户是谁,如果错误的用户企图访问信息,代码将在控制条件下停止。然后,代码从查询字符串获取设备,并根据指示完成输出。

由于每部电话都向数据库显示自己的请求和查询字符串,因此它们以设备可显示的格式轻松快速地接收输出。

结束语

您可以通过修改 XML 输出在其他平台上使用来自一个公共源的通讯录。针对 Nokia 的函数应该适用于任何遵守 WAP 2.0 的电话。针对其他电话改编 snom 函数可能更加复杂,但如果使用 XML,那么您需要的只是正确的架构。您可以使用任何方便的脚本语言、根据需要轻松维护和扩展这个脚本。

相关主题snom VoIP 电话概览:了解关于 snom 系列 VoIP 电话的更多信息。

snom 微型浏览器:了解 snom370、snom360、snom320、snom300 上的 V7 固件以及 snom820 和 snom870 上的 V8 固件支持的 XML 对象。

Nokia E71 智能电话:查看这种拥有 QWERTY 键盘的电话。

无线应用程序协议(Wikipedia):阅读一个关于用于移动电话等小型移动设备的常用 web 浏览器的优秀条目。

用 PHP 编写脚本:了解这种通用脚本语言的更多相关信息,这种语言尤其适合 web 开发,可以嵌入到 HTML 中。

VCF 和 vCard 文件格式:了解用于电子商务卡的 vCard 文件格式标准的更多信息。

LibreOffice:了解这个面向 Windows、Macintosh 和 Linux 的 OpenSource 个人生产力套件。试用下面 6 个用于文档生产和数据处理的应用程序:Writer、Calc、Impress、Draw、Math 和 Base。

phpMyEdit:使用这个工具编写一个简单的调用程序,生成一些 PHP 代码,以 HTML 格式显示或编辑的 MySQL 表。

developerWorks XML 专区:在 XML 专区获取提高您的专业技能所需的资源。

XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书,并阅读关于 XML 技巧 的更多信息。

developerWorks 技术活动 和 网络广播:随时关注这些活动中的技术。

IBM 产品评估版:下载或 在线试用 IBM SOA Sandbox,并开始使用来自 DB2®、Lotus®、Rational®

、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

用php编写室友通讯录_使用 XML 和 PHP 创建一个更具适应性的电话簿和通讯录相关推荐

  1. java反射访问室友属性_如何与家人,室友和客人共享HomeKit访问权限

    java反射访问室友属性 What's the point of having a house of the future if your family members, roommates, or ...

  2. python编写赛车游戏单机版_使用Python中OrderedDict模拟一个简单的竞速游戏排名

    上一篇,我们梳理了Python中关于字典排序的一些常用方法(杂乱无章的数据结构如何进行排序,简明讲述Python字典排序那些事).其中,我们讲到了Python的collections模块中的Order ...

  3. unity双击打不开脚本_游戏对象和脚本 (创建一个时钟)

    该文章是一篇译文,附上原文链接 Game Objects and Scripts​catlikecoding.com 使用简单对象构建一个时钟 编写一个C#脚本 转动时钟的指针来显示时间 创建指针动画 ...

  4. Java乐谱_如何在java中创建一个简单但结构良好的乐谱表(乐谱)?

    我正在使用非常基本的声音合成在我的游戏中创建音频和效果.基本上,我有一些方法可以发出一个频率和频率的声音.幅度和幅度持续时间. 对于短语和旋律,我想提出一个基本的符号,这样我就可以轻松地重写或添加新的 ...

  5. 怎么在云服务器上建网站_怎么使用云服务器创建一个网站?

    创建一个网站,需要三样东西,分别是域名.服务器和程度(代码),题主的需求是为了让作业的逼格更高,那么我们来看看网站所需的三样东西都怎么来: 1.域名:国内目前主要的域名注册商是阿里云和腾讯云,分别对应 ...

  6. java单链表通讯录_[源码和文档分享]C++实现的基于链表的通讯录管理系统

    摘 要 随着计算机应用技术的快速发展和日益普及,网络也遍及到我们生活的每个角落,为我们的学习和工作带来极大的方便.很多人都使用过传统的纸质通讯录,与之不同的另外一种管理方式--程序通讯录管理.程序通讯 ...

  7. python编写exe程序教程_使用Py2Exe for Python3创建自己的exe程序示例

    最近使用Python 3.5写了一个GUI小程序,于是想将该写好的程序发布成一个exe文件,供自己单独使用.至于通过安装的方式使用该程序,我没有探索,感兴趣的读者可以自己摸索. 1 介绍 我使用的开发 ...

  8. java创建临时文件夹_如何在Java中创建一个临时目录/文件夹?

    有没有在Java应用程序内部创建临时目录的标准可靠方法? Java的问题数据库中有一个条目,注释中包含一些代码,但是我想知道在一个常用的库(Apache Commons等)中是否找到标准解决方案? # ...

  9. mysql 中修改对象_在MySQL中,创建一个数据库后,还可以对象其进行修改,不过这里的修改是指可以修改被创建数据库的相关参数,也可以修改数据库名。...

    [多选题]注射时,在(  )情况下,采用较高的注射速率. [单选题]通常,所设置的模具温度是指和制品接触的模腔内表面在(   ). [单选题]反映某一事件发生强度的指标应选用 [判断题]当试样制备之后 ...

  10. mysql auto_increment建表_在mysql表中创建一个ID auto_increment(在事实之后)

    小编典典 例如,这是一个具有主键但不是的表AUTO_INCREMENT: mysql> CREATE TABLE foo ( id INT NOT NULL, PRIMARY KEY (id) ...

最新文章

  1. 行走在台北·之二·九份(转载)
  2. 使用SQL语句创建数据库2——创建多个数据库文件和多个日志文件
  3. linux 环境下配置ftp服务器
  4. 关于如何能够快速找到某个文本在所有文件中的出现位置
  5. JavaScript-Iterable迭代
  6. [leetcode]求数组的第k个最大值,python快排解法
  7. Oracle→简介、用户、数据字典、表空间及其文件
  8. jquery日历插件 途牛_为开发者准备的10款最好的jQuery日历插件
  9. Vue获取手机设备信息
  10. 方正璞华研发的社保股权管理系统初见成效
  11. Vacuum tube 真空管/电子管
  12. python中split什么意思_python中split的意思是什么(python中字符串的意思)
  13. Opencv中的颜色检测
  14. 直饮净水器什么牌子好,净水器评测
  15. 学习CALCULATE函数(六)丨帕累托之累计求和
  16. php微信手机端上传图片,手机Wap微信端上传单图和上传多图的DEMO
  17. 如何从后面截取字符串 String.slice()
  18. python制作微信小程序_python搭建微信小程序
  19. Python爬虫示例:爬取 13 个旅游城市,看看大家放假了都爱去哪玩
  20. 使用华为云跑自己的深度学习模型教程

热门文章

  1. 微信读书 iOS 性能优化总结
  2. 李雅普诺夫(第二方法)稳定性分析+例题
  3. 中国大学MOOC 视频字幕获取及处理方法
  4. MergeSort(C++)
  5. 4月1日起支付宝、微信扫码支付单日限额500元,够用吗?
  6. 大数据工程师简历怎么写,更受到HR青睐?
  7. 专业音频测试软件应用比对,(精品文献)专业音频测试软件应用比对(升级版)_汤磊.pdf...
  8. AE效果:3D 通道
  9. 幅频特性曲线protues_【2017年整理】幅频相频特性multisim11.ppt
  10. 计算机图形学 全局光照及方法,实时全局光照渲染研究