PHP生成图文混排的Word XML试卷

PHP生成图文混排的Word XML试卷

 

         作者:李永中     甘肃省成县城关中学     联系: [email protected]

 

摘要:本文介绍不借助任何插件及COM组件,通过借鉴Word XML基本代码,采用移花接木思想,直接由PHP生成图文及特殊符号混排的Word XML文档。

 

关键词:图文混排;试卷;Word XML

 

随着网络技术的发展,无纸化的网络办公已逐渐成为一种时尚。但在服务端生成图文混排的Word文档一直困挠着网络技术工作者,一直制约着网络技术在各个领域的发展,在教育领域显得尤为突出。目前利用网络技术生成图文并茂的纸质卷,仍然是影响网络技术在教育领域发展的拦路虎。

但铁捧磨锈针,工夫不负有心人,今天这个问题可以迎刃而解。                    

一.实现思想——移花接木

目前,并不能直接生成图文混排的Word文档,但可直接生成Word XML文件, 这个文件就如同HTML页一样,由PHP生成不存在什么问题。问题关键在于生成的文件必须兼容WordWPS?考虑到XML语言的特点,只认数据,不认格式。要生成兼容于WordXML文件,就必须符合微软的XML规范,而这个规范由于技术的壁垒,不为外人所知,因此只有借助微软自身的XML代码来生成试卷,这样兼容性问题就解决了。

下面如何分离Word XML功能代码。

二.提取并分离Word XML功能代码

(一)制作标准试卷XML模板

在模板中,按标准试卷的格式,设计好这个信息:卷头部分,试卷标题样式,大题号样式,选择型试题表格定位样式,图片样式,页码样式,试卷版面样式等。设计好后,反复修改,直到形成一个固定的版面。

(二)提取并分离功能代码

1.试卷标题及卷头代码块

用记事本打开XML模板,按以下信息块进行分析,你可以看到,试卷标题及卷头部分可以划归到个代码块,这一块的代码存入first.txt。在存入前将试卷标题用自编的长字串替换,此字串切忌不要与模板中的某此关键字符相冲突,first.txt文件的编码方式为UTF-8 (以下的.txt文件均与此同)。

2.大题标题段落和一般的正文段落

大题标题段落存入 p1.txt,段落内容字串biaotimsg,整段代码为:

<w:p><w:pPr><w:pStyle w:val="a8"/><w:ind w:left="0" w:first-line-chars="200"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr><w:t> biaotimsg</w:t></w:r></w:p>

一般的五号字正文段落存入p2.txt,段落内容字串xiaotihaomsg,整段代码为:

<w:p><w:pPr><w:pStyle w:val="a8"/><w:ind w:left="0" w:first-line-chars="0"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="fareast"/></w:rPr><w:t>xiaotihaomsg

</w:t></w:r></w:p>

3

(  )1. 以下是FLASH源文件格式的是:

(A) .fla

 

(B) .swf

(C) .doc

 

(D) .wps

 

表格设计成不打印,仅在编辑时可见,一个选择题就是一个表格,将题干和选项全部放进表格中。将制作好的word试卷转换为XML格式,然后用记事本打开,分析其代码大致组成及原理。经过研究发现,生成XML文件还是有规律可循的。

XML文件的规律:XML文件跟HTML语言一样,将代码按重复可编辑部分进行划分,可将一个完整XML试卷代码分成12个小段。将这12段代码分割成功后分别放到网站目录下的word-example文件夹中,用时程控读取并写入生成新的XML试卷文件,其XML文件生成的就跟生成HTML文件没有什么区别了。这12段代码将在程序中给出解释,这里暂不说明。

(二)生成纸质试卷

事先设计一个页面,用来输入试卷标题等卷头信息,并设计四个题型的复选框,让用户选择生成试卷的题型,当用户点击生成试卷时,会按选定的题型搜索AB组卷表的ID号,按ID号从原始试题库读出试题生成XML试卷。

其过程核心代码如下,下面代码中,除生成XML格式试卷外,同时生成试卷答案.txt文件。

<?php

session_start();

$_SESSION['duoxuanstart']=0; $_SESSION['duoxuanend']=-1;//多选题的开始点结束点

$_SESSION['fenshu']=0; $_SESSION['danxuantishu']=0;//总分和单选题数

$_SESSION['panduanstart']=0;$_SESSION['panduantishu']=0;//判断题的开始点和结束点

$_SESSION['itemnum']=0; $_SESSION['tiankongnum']=0;//大题数和填空数

$_SESSION['optnum']=0 ;//所有小题数:包括填空题、选择题、判断题小题数的总和

$answer=array();$tiankonganswer=array();$item=array();$_SESSION['answer']=$answer ;

$_SESSION['tiankonganswer']=$tiankonganswer;$item=@$_GET["item"];$kemu=$_SESSION['kemu'];

$shijuanid=$_GET["shijuanid"];//试卷类型:AB

$id=$_GET["id"];//AB组卷表中组卷记录ID

$_SESSION["path"]=$_SERVER['DOCUMENT_ROOT']."/test/";

$n=count($item);//$n为题型数,即实际大题数,并按次序赋值给tablename

$_session["datishu"]=$n;

if($n==0){echo "<script type='text/javascript'>alert('没有选择任何生成试卷的题型,页面将跳转到系统主页面!');self.location.href='/test/make_test.php';</script>";exit();

}

if($n !=0){

//以下十多行代码为XML试卷代码固定部分,$testname纸质试卷文件名,$testanswer为答案文件名

$testname=$_SESSION["path"]."wordtest/".session_id()."_".$_GET["shijuanid"].".xml";

$testanswer=$_SESSION["path"]."wordtest/".session_id()."_".$_GET["shijuanid"]."_answer.txt";

file_put_contents($testanswer,"---------------------".$_SESSION["testname"]."(答案)----------------------"."\r\n\r\n\r\n");

//分析word试卷的XML代码,将可编辑部分提出来,为程控写入代码作准备。

$xml1=file_get_contents($_SESSION["path"]."word-example/xml1.txt");

$xml2=file_get_contents($_SESSION["path"]."word-example/xml2.txt");

//$xml1$xml2为试卷标题前后代码,下面是写入XML试卷试卷标题

file_put_contents($testname,$xml1.$_SESSION["testname"].$xml2);

//$xml3$xml4为每道大题标题前后代码

$xml3="<w:p></w:p> <w:p><w:r><w:rPr><w:rFonts w:hint='fareast'/><wx:font wx:val='宋体'/><w:sz w:val='24'/><w:sz-cs w:val='24'/></w:rPr> <w:t>";

$xml4="</w:t></w:r></w:p>";

//xml5XML6为一般的段落前和段落后代码,如填空题的每一小题

$xml5="<w:p><w:pPr><w:pStyle w:val='a8'/><w:ind w:left='420' w:hanging='420'/></w:pPr><w:r><w:rPr><w:rFonts w:hint='fareast'/><wx:font wx:val='宋体'/></w:rPr><w:t>";

$xml6="</w:t></w:r></w:p>";

//$xml7是选择题的表格控制代码,在每个选择题小题前必须写入此代码一次。

$xml7=file_get_contents($_SESSION["path"]."word-example/xml7.txt");

//$xml8$xml9为表格第一行题干行前后控制代码。

$xml8="<w:tr><w:trPr><w:trHeight w:val='327'/></w:trPr>\<w:tc><w:tcPr><w:tcW w:w='8540' w:type='dxa'/><w:gridSpan w:val='3'/></w:tcPr><w:p><w:pPr><w:rPr><w:sz w:val='23'/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint='fareast'/><wx:font wx:val='宋体'/><w:sz w:val='23'/></w:rPr><w:t>";

$xml9="</w:t></w:r></w:p></w:tc></w:tr>";

//$xml10$xml11A选项和   C选项前后代码,$xml12B选项和D选项后代码。

$xml10=file_get_contents($_SESSION["path"]."word-example/xml10.txt");;

$xml11=file_get_contents($_SESSION["path"]."word-example/xml11.txt");;

$xml12=file_get_contents($_SESSION["path"]."word-example/xml12.txt");

//表格与表格之间的分隔行,若不分隔,两小题的表格会粘在一些,加入这段代码便于后期编辑。

$p_height="<w:p><w:pPr><w:pStylew:val='a8'/><w:spacing w:line='100' w:line-rule='exact'/><w:ind w:left='420' w:hanging='420'/></w:pPr></w:p>";

}

//自定义打开数据库函数

function opendatabase($sql,$flag){

   $con=mysql_connect("localhost","root",""); $f=mysql_select_db($_SESSION["kemu"],$con);

   $res=mysql_query($sql,$con);if($flag==1){return($res);} mysql_close($con);

       }

//针对abshijuanku数据库的自定义函数,从中快速组卷信息表搜索出试题信息

function openselitemid($sql,$flag){

   $con=mysql_connect("localhost","root","");$f=mysql_select_db("abshijuanku",$con);

   if(! $f){

          echo "<script type='text/javascript'>alert('打开test数据库失败,请确定该数据库是否存在!');</script>";mysql_close($con);exit();}

   $res=mysql_query($sql,$con);$res=mysql_query($sql,$con); if($flag==1){return($res);} mysql_close($con);

       }

       //若用户所选试题类型数不为0,从AB试卷信息表中得到试题的ID号,并在试题库读出试题

if($n !=0){$mainstr="<div id='main'>";

for($i=0;$i<$n;$i++){

       $sql="select ".$item[$i]." from ".$kemu." where id='".$_GET["id"]."'";

       $res=openselitemid($sql,1);$row=mysql_fetch_array($res);$idstr=$row[$item[$i]];

       if(!$idstr){echo "手动抽题-快速组卷表中".$item[$i]."题型为空,请检查后再试!";break;}

switch($item[$i]){

       case "tiankong":

    $itemtitle[$i]="填空题";

       funtiankong($testname,$testanswer,$xml3,$xml4,$xml5,$xml6,$itemtitle[$i],$idstr);break;

       case "danxuan":

       $itemtitle[$i]="单选题";

       fundanxuan($testname,$testanswer,$xml3,$xml4,$xml7,$xml8,$xml9,$xml10,$xml11,$xml12,$p_height,$itemtitle[$i],$idstr);break;

    case "duoxuan":

       $itemtitle[$i]="多选题";

       funduoxuan($testname,$testanswer,$xml3,$xml4,$xml7,$xml8,$xml9,$xml10,$xml11,$xml12,$p_height,$itemtitle[$i],$idstr);       break;

       case "panduan":

       $itemtitle[$i]="判断题";

       funpanduan($testname,$testanswer,$xml3,$xml4,$xml5,$xml6,$itemtitle[$i],$idstr);break;

       }

}

$_SESSION["zongfen"]=$_SESSION["fenshu"];

//最后写入XML试卷结束代码:end.txt

$filestr=file_get_contents($_SESSION["path"]."word-example/end.txt");

file_put_contents($testname,$filestr,FILE_APPEND);

$_SESSION["itemnum"]=$_SESSION["itemnum"]+$_SESSION["optnum"];

//试卷生成后的提示信息

$end3="  <div><h2>试卷编辑者须知</h2>

              <li><b>试卷总分:</b>试题实际总分为<b>".$_SESSION['fenshu']."</b>,请注意看与预设总分是否相符。不相符请返回继续添加试题或修改预设总分。</li><br />

              <li><b>纸质试卷下载:</b></li><br />

              <form id='downloadfrm' action='/test/download.php' method='get' >

              <input type='hidden' name='filename' />

              <table border='thin' width='760px' align='center' cellspacing='0' >

              <tr><td colspan='2' align='center'><b>下载纸质试卷和参考答案(生成的试卷只能用word打开)</b></td></tr>

              <tr align='center'><td><input type='submit' name='testbtn'  value='下载纸质试卷' onclick='btnclick(this.name)' /></td><td><input type='submit' name='answerbtn' value='下载试卷答案' onclick='btnclick(this.name)' /></td></tr>

</table></form><br/>

<script type='text/javascript' >

function btnclick(name){

if(name=='answerbtn'){ obj=document.getElementById('downloadfrm'); obj.filename.value='".$testanswer."'; }

if(name=='testbtn'){ obj=document.getElementById('downloadfrm'); obj.filename.value='".$testname."'; }

}

</script></div>";

echo $end3; echo "<script type='text/javascript' >";

echo "alert('当前实际总分为".$_SESSION["fenshu"].",测试卷实际总分可能跟设计值不同,请继续添加试题或修改卷头总分!另外生成的纸质试卷在页后,请注意下载。');";

echo "</script>"; echo "</div>"; echo "</form>";

//输出填空题,不是重点,代码参照单选题,以下输出单选题

function fundanxuan($testname,$testanswer,$xml3,$xml4,$xml7,$xml8,$xml9,$xml10,$xml11,$xml12,$p_height,$title,$idstr){

    $answerstr=""; $tiganstr="";$idarray=explode(",",$idstr); $rows=count($idarray); $i=0;$datizongfen=0;

if($rows<=0){echo "<p style='margin-left:50px;'>该题型试题库为空</p>"."</div>";}

    if($rows>0){ $_SESSION['kong']=0; $n=0;

         for($i=0;$i<$rows;$i++){

                $res=opendatabase("select * from danxuan where id=".$idarray[$i],1);

                $row=mysql_fetch_array($res);$id=$idarray[$i];$tigan=$row["tigan"];

             $opta=$row["opta"];$optb=$row["optb"];$optc=$row["optc"];$optd=$row["optd"];

             $fenzhi=$row["fenzhi"];$n++;

         $_SESSION["answer"][$n]=$row["answer"];$datizongfen=$datizongfen+$fenzhi;

         //记录纸质试卷的答案和题干

         $answerstr= $answerstr."(".($i+1).")".$_SESSION["answer"][$n]."  ";

         //将所有选择题XML代码放于题干字符串

         $tiganstr= $tiganstr.$xml7.$xml8."(  )".($i+1).". ".$tigan."".$xml9.$xml10."(A) ".$opta.$xml11."(B) ".$optb.$xml12.$xml10."(C) ".$optc.$xml11."(D) ".$optd.$xml12."</w:tbl>".$p_height;

    }

       $answerstr= $answerstr."\r\n";$_SESSION["fenshu"]=$_SESSION["fenshu"]+$datizongfen ;

       $_SESSION["optnum"]=$n ;$_SESSION["danxuantishu"]=($i+1) ;$_SESSION['duoxuanstart']=$n+1 ;

       $_SESSION["duoxuanend"]=$n+1;    

       //写入纸质试卷答案选择题标题

       file_put_contents($testanswer,".  选择题(每小题:".$fenzhi."分,总小题数:".($i+1).",共:".$datizongfen."分)"."\r\n\r\n",FILE_APPEND);

       //以下3行代码生成纸质试卷

       file_put_contents($testanswer,$answerstr."\r\n",FILE_APPEND);

       file_put_contents($testname,$xml3.".  选择题(每小题:".$fenzhi."分,(总小题数:".($i+1).",共:".$datizongfen."分)".$xml4,FILE_APPEND);

file_put_contents($testname,$tiganstr,FILE_APPEND);

}}

//输出多选题,判断题跟单选题基本类似,略

?>

生成的试卷文件名分别用session_id()._A.XMLsession_id()._B.XML来表示。

(三)Download.php 文件下载页

实现强制下载,消除答案文件在下载时,被浏览器打开而造成的乱码现象。此段代码可以从http://www.hackbase.com去下载。

三.参阅文献资料

1. 有关技术知识点参阅了   W3school  WEB技术教程网:http://www.w3school.com.cn/ ,在设计过程中给了很朋的帮助,在此表示真心的感谢!

2. 还有个别的技术知识点,来自于百度热心提示,在这里一并表示感谢!

. 作者简介

作者:李永中,生于1973年,19997月毕业于甘肃省西北师范大学电化教育系,现工作于甘肃省成县城关中学,致力于网络教学研究。

联系方式:QQ :1184373398  [email protected]

 

你可能感兴趣的:(PHP生成图文混排的Word XML试卷)