<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>程序员实验室</title>
	<atom:link href="http://www.prglab.com/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.prglab.com/blog</link>
	<description>多读书，读好书</description>
	<lastBuildDate>Thu, 08 Oct 2009 21:01:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.3</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>房贷还款的计算</title>
		<link>http://www.prglab.com/blog/p/165</link>
		<comments>http://www.prglab.com/blog/p/165#comments</comments>
		<pubDate>Thu, 08 Oct 2009 21:01:18 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[站长杂谈]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/?p=165</guid>
		<description><![CDATA[怎么样才能付最少的利息是俺准房奴最关心的事儿，到底是拿浮动利率好，还是固定利率好，3年固定还是5年固定好，除了个人对利率走向的预测，还得知道利息是怎样计算的。最近刚刚研究了一下，跟大家分享一下心得吧。
房贷还款其实就是分期还款 (amortization)，每期还款金额相同，银行从还款中先扣利息，再算本金。(一般也允许每期多付一点，多付的部分全都算还的本金，因为影响银行的利息收入，一般有限额，这个后面再另说，这里先考虑只老老实实按时还，不多付的情况。）
计算还款金额分两步走，一算周期利率，二算分期金额。
首先说周期利率。通常银行给的那个百分数(4%啊，6%啊什么的）都说是年利率，而付款周期可以是按月付(monthly)，半月付(semi-monthly)，按周付(weekly)，或者双周付(Bi-weekly)。计算利息的时候需要计算周期利率，计息周期和付款周期的选择是会影响最终的实际利息的。一般计息周期和付款周期是相同的，这种情况下计息周期的利率等于年利率除以一年的期数，比如年利率是6%，按月付一年12期，周期利率就是6%/12=0.5%。但是有些情况下，比如加拿大的房贷有些是半年计息的，也就是说一年计两次，而还款还是可以选不同周期，这样计息周期与还款周期不同，周期利率就与前面的计算稍有不同。
周其利率的计算公式是： 
其中 是银行给的年利率，c是每年的计息周期数，p是每年还款周期数。
比如还是年利率6%，每半年计息（在很多加拿大银行的网站经常会看到一句 Rate calculated semi-annually, not in advance就是这个意思），每年的计息周期就是2，还是按月还款，每年的还款周期是12, 那么周期利率就是 (1-6%/2)^(2/12)-1=0.494%，看到不同了吧。（不过注意一般只有固定利率的房贷是半年计的，浮动利率的一般还是按还款周期计）。
有了周期利率就可以算每期还款额了，公式如下：

未完待续。。。
参考： Amortization Calculator &#8211; Wikipedia
]]></description>
			<content:encoded><![CDATA[<p>怎么样才能付最少的利息是俺准房奴最关心的事儿，到底是拿浮动利率好，还是固定利率好，3年固定还是5年固定好，除了个人对利率走向的预测，还得知道利息是怎样计算的。最近刚刚研究了一下，跟大家分享一下心得吧。</p>
<p>房贷还款其实就是分期还款 (amortization)，每期还款金额相同，银行从还款中先扣利息，再算本金。(一般也允许每期多付一点，多付的部分全都算还的本金，因为影响银行的利息收入，一般有限额，这个后面再另说，这里先考虑只老老实实按时还，不多付的情况。）</p>
<p>计算还款金额分两步走，一算周期利率，二算分期金额。</p>
<p>首先说周期利率。通常银行给的那个百分数(4%啊，6%啊什么的）都说是年利率，而付款周期可以是按月付(monthly)，半月付(semi-monthly)，按周付(weekly)，或者双周付(Bi-weekly)。计算利息的时候需要计算周期利率，计息周期和付款周期的选择是会影响最终的实际利息的。一般计息周期和付款周期是相同的，这种情况下计息周期的利率等于年利率除以一年的期数，比如年利率是6%，按月付一年12期，周期利率就是6%/12=0.5%。但是有些情况下，比如加拿大的房贷有些是半年计息的，也就是说一年计两次，而还款还是可以选不同周期，这样计息周期与还款周期不同，周期利率就与前面的计算稍有不同。</p>
<p>周其利率的计算公式是： <img class="alignnone" src="http://upload.wikimedia.org/math/4/0/3/403a6ee6e669fe86808a380b801b334f.png" alt="" width="204" height="54" /></p>
<p>其中 <img class="alignnone" src="http://upload.wikimedia.org/math/7/c/a/7ca811e322b6a8b8632100075a2af94d.png" alt="" width="48" height="17" />是银行给的年利率，<em>c</em>是每年的计息周期数，<em>p</em>是每年还款周期数。</p>
<p>比如还是年利率6%，每半年计息（在很多加拿大银行的网站经常会看到<span>一句 Rate calculated semi-annually, not in advance就是这个意思），每年的计息周期就是2，还是按月还款，每年的还款周期是12, 那么周期利率就是 (1-6%/2)^(2/12</span>)-1=0.494%，看到不同了吧。（不过注意一般只有固定利率的房贷是半年计的，浮动利率的一般还是按还款周期计）。</p>
<p>有了周期利率就可以算每期还款额了，公式如下：</p>
<p><img class="alignnone" src="http://upload.wikimedia.org/math/c/e/7/ce75fe20841bd1a80febafb4c8adcb04.png" alt="" width="298" height="48" /></p>
<p>未完待续。。。</p>
<p>参考： <a href="http://en.wikipedia.org/wiki/Amortization_calculator" target="_blank">Amortization Calculator &#8211; Wikipedia</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/165/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>怎样在Eclipse上安装PHP插件</title>
		<link>http://www.prglab.com/blog/p/106</link>
		<comments>http://www.prglab.com/blog/p/106#comments</comments>
		<pubDate>Mon, 03 Aug 2009 20:36:17 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[建站交流]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/?p=106</guid>
		<description><![CDATA[首先你要有已安装好的Eclipse平台，如果没有，可以去这里下载一款合适的版本进行安装。
这里介绍的安装方法是基于Eclipse平台版本3.3.2的，其他版本的安装也大同小异。
PHP插件安装步骤：
1、启动Eclipse，到菜单项 &#8220;帮助(Help) -&#62; 软件更新(Software Update) -&#62; 查找和安装(Find and Install&#8230;)&#8221;
2、选择寻找安装新组件(Search for new feature to install)，然后点下一步(next)按钮。

3、在安装对话框中点“新增远程站点(New Remote Site&#8230;)”按钮。
4、输入PHPEclipse下载站点的名称和URL：
名称： PHPEclipse Nightly Builds
URL: http://update.phpeclipse.net/update/nightly/
然后点OK按钮。
5、返回安装对话框，选择以下三个站点：Europa Discovery Site、 PHPEclipse Nightly Builds、和 The Eclipse Project Updates，然后点击完成(Finish)按钮。
6、选择完成后，系统会自动进行搜索。搜索过程中可能会出现如下对话框提示你为每一个所选站点选择镜像服务器，选一个离你最近的站点就好。
7、在搜索结果对话框中选上必要的安装和更新项目，最少应该选上PHPEclipse Nightly Builds。如果只选上该项后，你看到对话框顶部出现如下错误信息：　JessDE(7.0.0) requires plug-in “org.eclispe.pde.ui”，这说明你的Ｅｃｌｉｐｓｅ插件开发环境需要更新。
消除这个错误的方法很简单，继续展开选项The Eclipse Project Updates -&#62; Eclipse 3.3.2，找到最低部的插件开发环境选项（Ｅｃｌｉｐｓｅ　Ｐｌｕｇ-in Development Environment），选上这一项就可以了，然后选择下一步(next)按钮。
8、接受license条款，然后下一步。
9、完成
10、等待下载插件。下载完成后系统会逐一提示安装所选插件。你可以逐一选择安装(Install)每一个插件，也可以一次性选择安装所有下载的插件(Install All)。
11、最后重启Eclipse。
恭喜你，现在你已经在Eclipse平台上成功安装了PHP插件，可以开始开发你的PHP项目了！
]]></description>
			<content:encoded><![CDATA[<p>首先你要有已安装好的Eclipse平台，如果没有，可以去<a title="Eclipse下载" href="http://www.eclipse.org/downloads/" target="_blank">这里</a>下载一款合适的版本进行安装。<br />
这里介绍的安装方法是基于Eclipse平台版本3.3.2的，其他版本的安装也大同小异。</p>
<h2>PHP插件安装步骤：</h2>
<p>1、启动Eclipse，到菜单项 &#8220;帮助(Help) -&gt; 软件更新(Software Update) -&gt; 查找和安装(Find and Install&#8230;)&#8221;</p>
<div id="attachment_107" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.prglab.com/blog/wp-content/uploads/step1.jpg"><img class="size-medium wp-image-107" title="step1" src="http://www.prglab.com/blog/wp-content/uploads/step1-300x124.jpg" alt="Eclipse安装PHP插件第一步" width="300" height="124" /></a><p class="wp-caption-text">Eclipse安装PHP插件第一步</p></div>
<p>2、选择寻找安装新组件(Search for new feature to install)，然后点下一步(next)按钮。</p>
<div id="attachment_109" class="wp-caption aligncenter" style="width: 606px"><a href="http://www.prglab.com/blog/wp-content/uploads/step2.jpg"><img class="size-full wp-image-109" title="step2" src="http://www.prglab.com/blog/wp-content/uploads/step2.jpg" alt="Eclipse安装PHP插件第二步" width="596" height="556" /></a><p class="wp-caption-text">Eclipse安装PHP插件第二步</p></div>
<p><span id="more-106"></span></p>
<p>3、在安装对话框中点“新增远程站点(New Remote Site&#8230;)”按钮。</p>
<div id="attachment_110" class="wp-caption aligncenter" style="width: 610px"><a href="http://www.prglab.com/blog/wp-content/uploads/step3.jpg"><img class="size-full wp-image-110" title="step3" src="http://www.prglab.com/blog/wp-content/uploads/step3.jpg" alt="Eclipse安装PHP插件第三步" width="600" height="560" /></a><p class="wp-caption-text">Eclipse安装PHP插件第三步</p></div>
<p>4、输入PHPEclipse下载站点的名称和URL：</p>
<p>名称： PHPEclipse Nightly Builds</p>
<p>URL: <a href="http://update.phpeclipse.net/update/nightly/">http://update.phpeclipse.net/update/nightly/</a></p>
<p>然后点OK按钮。</p>
<div id="attachment_111" class="wp-caption aligncenter" style="width: 364px"><a href="http://www.prglab.com/blog/wp-content/uploads/step4.jpg"><img class="size-full wp-image-111" title="step4" src="http://www.prglab.com/blog/wp-content/uploads/step4.jpg" alt="Eclipse安装PHP插件第四步" width="354" height="152" /></a><p class="wp-caption-text">Eclipse安装PHP插件第四步</p></div>
<p>5、返回安装对话框，选择以下三个站点：Europa Discovery Site、 PHPEclipse Nightly Builds、和 The Eclipse Project Updates，然后点击完成(Finish)按钮。</p>
<div id="attachment_112" class="wp-caption aligncenter" style="width: 609px"><a href="http://www.prglab.com/blog/wp-content/uploads/step5.jpg"><img class="size-full wp-image-112" title="step5" src="http://www.prglab.com/blog/wp-content/uploads/step5.jpg" alt="Eclipse安装PHP插件第五步" width="599" height="555" /></a><p class="wp-caption-text">Eclipse安装PHP插件第五步</p></div>
<p>6、选择完成后，系统会自动进行搜索。搜索过程中可能会出现如下对话框提示你为每一个所选站点选择镜像服务器，选一个离你最近的站点就好。</p>
<div id="attachment_113" class="wp-caption aligncenter" style="width: 466px"><a href="http://www.prglab.com/blog/wp-content/uploads/step6.jpg"><img class="size-full wp-image-113" title="step6" src="http://www.prglab.com/blog/wp-content/uploads/step6.jpg" alt="Eclipse安装PHP插件第六步" width="456" height="380" /></a><p class="wp-caption-text">Eclipse安装PHP插件第六步</p></div>
<p>7、在搜索结果对话框中选上必要的安装和更新项目，最少应该选上PHPEclipse Nightly Builds。如果只选上该项后，你看到对话框顶部出现如下错误信息：　JessDE(7.0.0) requires plug-in “org.eclispe.pde.ui”，这说明你的Ｅｃｌｉｐｓｅ插件开发环境需要更新。</p>
<div id="attachment_115" class="wp-caption aligncenter" style="width: 607px"><a href="http://www.prglab.com/blog/wp-content/uploads/step8.jpg"><img class="size-full wp-image-115" title="step8" src="http://www.prglab.com/blog/wp-content/uploads/step8.jpg" alt="Eclipse安装PHP插件第七步" width="597" height="519" /></a><p class="wp-caption-text">Eclipse安装PHP插件第七步</p></div>
<p>消除这个错误的方法很简单，继续展开选项The Eclipse Project Updates -&gt; Eclipse 3.3.2，找到最低部的插件开发环境选项（Ｅｃｌｉｐｓｅ　Ｐｌｕｇ-in Development Environment），选上这一项就可以了，然后选择下一步(next)按钮。</p>
<div id="attachment_116" class="wp-caption aligncenter" style="width: 606px"><a href="http://www.prglab.com/blog/wp-content/uploads/step9.jpg"><img class="size-full wp-image-116" title="step7-2" src="http://www.prglab.com/blog/wp-content/uploads/step9.jpg" alt="Eclipse安装PHP插件第七步-2" width="596" height="354" /></a><p class="wp-caption-text">Eclipse安装PHP插件第七步-2</p></div>
<div id="attachment_117" class="wp-caption aligncenter" style="width: 610px"><a href="http://www.prglab.com/blog/wp-content/uploads/step10.jpg"><img class="size-full wp-image-117" title="step7-3" src="http://www.prglab.com/blog/wp-content/uploads/step10.jpg" alt="Eclipse安装PHP插件第七步-3" width="600" height="521" /></a><p class="wp-caption-text">Eclipse安装PHP插件第七步-3</p></div>
<p>8、接受license条款，然后下一步。</p>
<div id="attachment_118" class="wp-caption aligncenter" style="width: 608px"><a href="http://www.prglab.com/blog/wp-content/uploads/step11.jpg"><img class="size-full wp-image-118" title="step8" src="http://www.prglab.com/blog/wp-content/uploads/step11.jpg" alt="Eclipse安装PHP插件第八步" width="598" height="521" /></a><p class="wp-caption-text">Eclipse安装PHP插件第八步</p></div>
<p>9、完成</p>
<div id="attachment_119" class="wp-caption aligncenter" style="width: 610px"><a href="http://www.prglab.com/blog/wp-content/uploads/step12.jpg"><img class="size-full wp-image-119" title="step9" src="http://www.prglab.com/blog/wp-content/uploads/step12.jpg" alt="Eclipse安装PHP插件第九步" width="600" height="520" /></a><p class="wp-caption-text">Eclipse安装PHP插件第九步</p></div>
<p>10、等待下载插件。下载完成后系统会逐一提示安装所选插件。你可以逐一选择安装(Install)每一个插件，也可以一次性选择安装所有下载的插件(Install All)。</p>
<div id="attachment_120" class="wp-caption aligncenter" style="width: 606px"><a href="http://www.prglab.com/blog/wp-content/uploads/step13.jpg"><img class="size-full wp-image-120" title="step10" src="http://www.prglab.com/blog/wp-content/uploads/step13.jpg" alt="Eclipse安装PHP插件第十步" width="596" height="497" /></a><p class="wp-caption-text">Eclipse安装PHP插件第十步</p></div>
<p>11、最后重启Eclipse。</p>
<div id="attachment_108" class="wp-caption aligncenter" style="width: 453px"><a href="http://www.prglab.com/blog/wp-content/uploads/step16.jpg"><img class="size-full wp-image-108" title="step11" src="http://www.prglab.com/blog/wp-content/uploads/step16.jpg" alt="Eclipse安装PHP插件第十一步" width="443" height="152" /></a><p class="wp-caption-text">Eclipse安装PHP插件第十一步</p></div>
<p>恭喜你，现在你已经在Eclipse平台上成功安装了PHP插件，可以开始开发你的PHP项目了！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/106/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Website Baker中文插件</title>
		<link>http://www.prglab.com/blog/p/101</link>
		<comments>http://www.prglab.com/blog/p/101#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:26:45 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[建站交流]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/?p=101</guid>
		<description><![CDATA[编码格式： utf-8
适用版本： Website Baker 2.7.x
如果使用有任何问题，欢迎留言，我会尽快更正。
点击下载 
]]></description>
			<content:encoded><![CDATA[<p>编码格式： utf-8<br />
适用版本： Website Baker 2.7.x</p>
<p>如果使用有任何问题，欢迎留言，我会尽快更正。</p>
<p><a href="http://www.prglab.com/bbs/attachment.php?aid=13">点击下载 </a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/101/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>服务器端包含SSI(Server Side Include)简介</title>
		<link>http://www.prglab.com/blog/p/83</link>
		<comments>http://www.prglab.com/blog/p/83#comments</comments>
		<pubDate>Sat, 11 Apr 2009 03:07:57 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[建站交流]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/?p=83</guid>
		<description><![CDATA[服务器端包含 SSI，是英文 Server Side Includes的简写。SSI是一种可以指挥服务器动态声称网页内容的HTML指令。
通常SSI可以用来确保网页中的一些通用内容，比如版权信息、联系方式、或导航信息在全站所有网页中保持一致。使用SSI显示这些通用内容还可以减轻网站维护的工作量，因为当需要修改这些通用信息的时候，只需要改一个地方就可以了，而不需要逐个修改每一个网页。
各个服务器对SSI命令的支持各有不同，但 #include 和 #exec 是通用的。使用 SSI 的页面文件通常都使用扩展名.shtml，而不是.html 或 .htm，这样以便服务器能够辨认出哪些页面包含SSI指令，这些页面需要先经过服务器处理，翻译执行其中的SSI指令，然后才发送给客户端浏览器。  (当然有些服务器还是支持.html,.htm文件中有SSI指令的)。


如何辨别你的服务器是否支持 SSI?
多数网站寄存服务都支持 SSI &#8211; 但是也有一些不支持，特别是一些免费的网站寄存服务。你可以联系你的网站寄存公司询问他们是否支持SSI，也可以通过以下方式来自己测试一下你的服务器是否支持SSI:
1. 拷贝以下HTML内容，保存为文件名test.shtml
&#60;html&#62;&#60;head&#62;&#60;/head&#62;
&#60;body&#62;&#60;!&#8211;#echo var=&#8221;DATE_LOCAL&#8221; &#8211;&#62;&#60;/body&#62;
&#60;/html&#62;

2. 将这个文件上载到你的服务器上，然后用浏览器浏览服务器上的这个网页。
3. 如果看到网页显示当前日期，则你的服务器支持 SSI。否则，多半可能你的服务器不支持SSI。你可以尝试与你的网站寄存公司联系看他们是否可以为你开通SSI服务。
练习1: 显示版权信息
1. 拷贝以下内容并存为copyright.html文件名 （你可以把链接和网站名称修改为你的网站）：

&#38;copy;2007 &#60;a href=&#8221;http://www.prglab.com&#8221;&#62; 程序员实验室&#60;/a&#62; 版权所有。 

在浏览器中它应该显示为

©2007 程序员实验室 版权所有。

注意：在这个文件代码中不能够出现 &#60;html&#62;, &#60;head&#62; 和 &#60;body&#62; 这些标签，否则包含它的页面会出错。
2. 将这个文件copyright.html上传到你的服务器上。
3. 在要显示版权信息的页面底部&#60;/body&#62;标签之前插入以下代码：
 

&#60;!&#8211;#include virtual=&#8221;/copyright.html&#8221;             [...]]]></description>
			<content:encoded><![CDATA[<p class="margin">服务器端包含 SSI，是英文 Server Side Includes的简写。SSI是一种可以指挥服务器动态声称网页内容的HTML指令。</p>
<p class="margin">通常SSI可以用来确保网页中的一些通用内容，比如版权信息、联系方式、或导航信息在全站所有网页中保持一致。使用SSI显示这些通用内容还可以减轻网站维护的工作量，因为当需要修改这些通用信息的时候，只需要改一个地方就可以了，而不需要逐个修改每一个网页。</p>
<p class="margin">各个服务器对SSI命令的支持各有不同，但 #include 和 #exec 是通用的。使用 SSI 的页面文件通常都使用扩展名.shtml，而不是.html 或 .htm，这样以便服务器能够辨认出哪些页面包含SSI指令，这些页面需要先经过服务器处理，翻译执行其中的SSI指令，然后才发送给客户端浏览器。  (当然有些服务器还是支持.html,.htm文件中有SSI指令的)。</p>
<p class="margin"><span id="more-83"></span></p>
<p class="margin">
<p><strong>如何辨别你的服务器是否支持 SSI?</strong></p>
<p class="margin">多数网站寄存服务都支持 SSI &#8211; 但是也有一些不支持，特别是一些免费的网站寄存服务。你可以联系你的网站寄存公司询问他们是否支持SSI，也可以通过以下方式来自己测试一下你的服务器是否支持SSI:</p>
<p>1. 拷贝以下HTML内容，保存为文件名test.shtml</p>
<p><strong><span style="color: #ff6633;">&lt;html&gt;&lt;head&gt;&lt;/head&gt;</span></strong></p>
<p><strong><span style="color: #ff6633;">&lt;body&gt;&lt;!&#8211;#echo var=&#8221;DATE_LOCAL&#8221; &#8211;&gt;&lt;/body&gt;</span></strong></p>
<p><strong><span style="color: #ff6633;">&lt;/html&gt;<br />
</span></strong></p>
<p class="margin">2. 将这个文件上载到你的服务器上，然后用浏览器浏览服务器上的这个网页。</p>
<p>3. 如果看到网页显示当前日期，则你的服务器支持 SSI。否则，多半可能你的服务器不支持SSI。你可以尝试与你的网站寄存公司联系看他们是否可以为你开通SSI服务。</p>
<p class="margin"><strong>练习1: 显示版权信息</strong></p>
<p class="margin">1. 拷贝以下内容并存为copyright.html文件名 （你可以把链接和网站名称修改为你的网站）：</p>
<blockquote>
<p class="margin"><strong><span style="color: #ff6600;">&amp;copy;2007 &lt;a href=&#8221;http://www.prglab.com&#8221;&gt; 程序员实验室&lt;/a&gt; 版权所有。 </span></strong></p>
</blockquote>
<p class="margin" style="padding-left: 30px;">在浏览器中它应该显示为</p>
<blockquote>
<p class="margin"><strong><span style="color: #6699cc;">©2007 <a href="http://www.prglab.com">程序员实验室</a> 版权所有。<br />
</span></strong></p></blockquote>
<p class="margin" style="padding-left: 30px;"><strong>注意：</strong>在这个文件代码中不能够出现 &lt;html&gt;, &lt;head&gt; 和 &lt;body&gt; 这些标签，否则包含它的页面会出错。</p>
<p class="margin">2. 将这个文件copyright.html上传到你的服务器上。</p>
<p class="margin">3. 在要显示版权信息的页面底部&lt;/body&gt;标签之前插入以下代码：<br />
<strong> </strong></p>
<blockquote>
<p class="margin"><strong><span style="color: #ff6600;">&lt;!&#8211;#include virtual=&#8221;/copyright.html&#8221;                          &#8211;&gt;</span></strong></p>
</blockquote>
<p class="margin">4.将修改后的文件上传到服务器上，然后用浏览器打开服务器上的文件，你应该看到页面的底部显示版权信息。</p>
<p class="margin" style="padding-left: 30px;"><strong>注意：</strong> 写有包含指令(#include)代码的文件可能要保存为扩展名为.shtml的文件名，代码才能生效。</p>
<p class="margin">
<p class="margin"><strong>练习 2: 简单的导航条</strong></p>
<p class="margin">1. 比如我们要写一个如下所示的导航条<br />
<strong> </strong></p>
<p class="margin" style="padding-left: 30px;"><strong>主页| 联系方式 | 产品介绍 | 订单<br />
</strong></p>
<p class="margin" style="padding-left: 30px;">可以用以下HTML代码来实现：</p>
<blockquote>
<p class="margin"><strong><span style="color: #ff6600;">&lt;p align=&#8221;center&#8221;&gt;&lt;font                            face=&#8221;Geneva, Arial, Helvetica, sans-serif&#8221;                            size=&#8221;2&#8243;&gt;</span></strong></p>
<p class="margin"><strong><span style="color: #ff6600;">&lt;a href=&#8221;home.htm&#8221;&gt;主页&lt;/a&gt;</span></strong></p>
<p class="margin"><strong><span style="color: #ff6600;">| &lt;a href=&#8221;mailto:myemail@address.com&#8221;&gt;联系方式&lt;/a&gt;</span></strong></p>
<p class="margin"><strong><span style="color: #ff6600;"> | &lt;a href=&#8221;ｐｒｏｄｕｃｔｓ.htm&#8221;&gt;产品介绍</span></strong><strong><span style="color: #ff6600;">&lt;/a&gt;</span></strong></p>
<p class="margin"><strong><span style="color: #ff6600;">| &lt;a href=&#8221;orders.htm&#8221;&gt;订单&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;</span></strong></p>
</blockquote>
<p class="margin"><span style="color: #6699cc;"><strong> </strong></span></p>
<p class="margin">２.　保存这些代码为文件 navigation.shtml 或 navigation.shtm.</p>
<p class="margin">３.　打开要插入导航条的页面，在要显示导航条的位置插入以下代码：</p>
<blockquote>
<p class="margin"><strong><span style="color: #ff6600;">&lt;!&#8211;#include virtual=&#8221;/navigation.shtml&#8221;                          &#8211;&gt;</span></strong></p>
</blockquote>
<p class="margin">４.　将所有文件上载到服务器上，并用浏览器检查导航条是否如你所设想的显示。</p>
<p class="margin">以上只是两个很简单的SSI使用的例子，你还可以自由发挥写出更复杂的网页。如果需要修改SSI包含的内容，只需要打开写有通用内容的网页，比如上面的copyright.html或navigation.shtml，修改其中的内容，那么所有包含这个文件的网页相应内容都会被自动修改。</p>
<p class="margin">SSI 相对来说比较容易掌握，并能提高网站维护效率，不妨一试。</p>
<p class="margin">参考文章： <a href="http://www.thetemplatestore.com/tutorials/ssi.asp" target="_blank">Server Side Includes Tutorial (From The Template Store)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/83/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>如何将一个HTML页面嵌套在另一个页面中</title>
		<link>http://www.prglab.com/blog/p/81</link>
		<comments>http://www.prglab.com/blog/p/81#comments</comments>
		<pubDate>Thu, 19 Feb 2009 15:04:29 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[建站交流]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/81</guid>
		<description><![CDATA[这个在做网页中常要用到，有些通用的内容可集中放在一个页面文件中，其它要用到这些内容的页面只需要包含（引用）这个通用文件即可。这样便于维护，如果有很多网页，当通用内容需要修改时，只改一个文件就可以了，不需要每个文件单独修改。
最典型的应用比如页脚的版权信息等内容可以放在一个叫做footer.html文件里， 然后其他页面文件在页面内容的最后包含这个文件就可以了，具体例子下面有。
要html文件嵌套，最简单的办法是使用SSI（Server Side Include)技术，也就是在服务器端两个文件就被合并了。除了少数免费网页寄存服务外，几乎所有的网页寄存服务器都支持 SSI。这也是一个比较推荐的方法，它与ASP和ASP.NET网页使用的语法一模一样。如果网站管理员偏向使用PHP或JSP的话，语法会稍有不同。
对于不能使用SSI、ASP、ASP.NET、PHP和JSP等服务器端动态页面语言的情况，这里还将介绍两种客户端镶嵌的办法：JavaScript和iframe的方法。当这两种客户端的方法都有很大的弊病，一般不推荐使用。
下面对各种方法单独具体介绍。

1、SSI (Server Side Include)
SSI是一种简单的动态网页制作技术，但是有些服务器要求网页文件扩展名为.shtml才能识别文件中SSI命令。所以如果你的SSI命令看起来不工作，先别放弃，试着把文件扩展名改为.shtml，也许会成功。如果知道自己的服务器是否支持SSI，请看另一篇文章。
使用SSI一个局限性是页面一定要放在网页服务器上才能看到效果，在本地是不好调试的。当然，如果非要在本地调试，就本地装一个Apache服务器好了。
比如你想在每个网页的底部加上同样的版权信息，像
© 2009 程序员实验室 版权所有
可以把这行信息放到一个叫做footer.html的文件里，footer.html的内容为：
&#60;center&#62; &#38;copy; 程序员实验室 版权所有&#60;/center&#62;;
这样同一路径下的其他页面文件要包含footer.html的SSI命令是：
&#60;!--#include virtual="footer.html" --&#62; （常用）
或者
&#60;!--#include file="footer.html" --&#62;
这两者的几乎是一样的，不同之处在于include virtual后面取的是一个URL形式的路径，甚至还可以执行一个CGI程序并包含其输出结果，如果你的服务器支持CGI的话。而include file后面取的是一个文件系统路径，并且不能执行CGI程序。两者都可以接受相对路径，所以对上面这个简单例子，两者的效果是一样的。如果你不知道URL路径与文件系统路径两者的区别的话，就用include virtual
更多关于SSI的介绍，请看这篇SSI的介绍文章。
2、PHP
如果你的服务器支持PHP的话，用PHP引用footer.html文件的写法如下：
&#60;?php include("footer.html"); ?&#62;
这句命令所在的文件扩展名必须被为.php。
除了引用本服务器上的文件，PHP的include命令还可以用来引用其它网站上的html文件，比如：
&#60;?php include("http://www.prglab.com/examples/footer.html"); ?&#62; 
当然你要得到其它网站的允许才能引用别人的文件。
3、ASP和ASP.NET
如果你使用的是老式的ASP，则语法是与上面SSI一样的，不需要任何修改，只要把命令所在文件的扩展名改为.asp即可。
对于ASP.NET，也是类似，不同之处在于，因为SSI命令是在ASP命令运行之前被首先编译，所以文件名中不能够使用ASP.NET的变量。如果一定要用的话，就用ASP.NET的命令来做文件嵌套吧。
比如：
        &#60;%

          Response.WriteFile ("footer.html")

        %&#62;
更多关于怎样在ASP.NET中实现动态文件嵌套，请参考微软的这篇文章。
4、JSP （Java Server Page)

JSP文件需要在基于Java的服务器上运行，比如Apache [...]]]></description>
			<content:encoded><![CDATA[<p>这个在做网页中常要用到，有些通用的内容可集中放在一个页面文件中，其它要用到这些内容的页面只需要包含（引用）这个通用文件即可。这样便于维护，如果有很多网页，当通用内容需要修改时，只改一个文件就可以了，不需要每个文件单独修改。</p>
<p>最典型的应用比如页脚的版权信息等内容可以放在一个叫做footer.html文件里， 然后其他页面文件在页面内容的最后包含这个文件就可以了，具体例子下面有。</p>
<p>要html文件嵌套，最简单的办法是使用SSI（Server Side Include)技术，也就是在服务器端两个文件就被合并了。除了少数免费网页寄存服务外，几乎所有的网页寄存服务器都支持 SSI。这也是一个比较推荐的方法，它与ASP和ASP.NET网页使用的语法一模一样。如果网站管理员偏向使用PHP或JSP的话，语法会稍有不同。</p>
<p>对于不能使用SSI、ASP、ASP.NET、PHP和JSP等服务器端动态页面语言的情况，这里还将介绍两种客户端镶嵌的办法：JavaScript和iframe的方法。当这两种客户端的方法都有很大的弊病，一般不推荐使用。</p>
<p>下面对各种方法单独具体介绍。</p>
<p><span id="more-81"></span></p>
<p><strong>1、SSI (Server Side Include)</strong></p>
<p>SSI是一种简单的动态网页制作技术，但是有些服务器要求网页文件扩展名为.shtml才能识别文件中SSI命令。所以如果你的SSI命令看起来不工作，先别放弃，试着把文件扩展名改为.shtml，也许会成功。如果知道自己的服务器是否支持SSI，请看另一篇文章。</p>
<p>使用SSI一个局限性是页面一定要放在网页服务器上才能看到效果，在本地是不好调试的。当然，如果非要在本地调试，就本地装一个Apache服务器好了。</p>
<p>比如你想在每个网页的底部加上同样的版权信息，像</p>
<blockquote><p>© 2009 程序员实验室 版权所有</p></blockquote>
<p>可以把这行信息放到一个叫做footer.html的文件里，footer.html的内容为：</p>
<blockquote><p>&lt;center&gt; &amp;copy; 程序员实验室 版权所有&lt;/center&gt;;</p></blockquote>
<p>这样同一路径下的其他页面文件要包含footer.html的SSI命令是：</p>
<p><tt>&lt;!--#include virtual="footer.html" --&gt;</tt> （常用）</p>
<p>或者</p>
<p><tt>&lt;!--#include file="footer.html" --&gt;</tt></p>
<p>这两者的几乎是一样的，不同之处在于include virtual后面取的是一个URL形式的路径，甚至还可以执行一个CGI程序并包含其输出结果，如果你的服务器支持CGI的话。而include file后面取的是一个文件系统路径，并且不能执行CGI程序。两者都可以接受相对路径，所以对上面这个简单例子，两者的效果是一样的。如果你不知道URL路径与文件系统路径两者的区别的话，就用include virtual</p>
<p>更多关于SSI的介绍，请看<a href="http://www.prglab.com/blog/p/83" target="_self">这篇SSI的介绍文章</a>。</p>
<p><strong>2、PHP</strong></p>
<p>如果你的服务器支持PHP的话，用PHP引用footer.html文件的写法如下：</p>
<p><tt>&lt;?php include("footer.html"); ?&gt;</tt></p>
<p>这句命令所在的文件扩展名必须被为.php。</p>
<p>除了引用本服务器上的文件，PHP的include命令还可以用来引用其它网站上的html文件，比如：</p>
<p><tt>&lt;?php include("http://www.prglab.com/examples/footer.html"); ?&gt; </tt></p>
<p>当然你要得到其它网站的允许才能引用别人的文件。</p>
<p><strong>3、ASP和ASP.NET</strong></p>
<p>如果你使用的是老式的ASP，则语法是与上面SSI一样的，不需要任何修改，只要把命令所在文件的扩展名改为.asp即可。</p>
<p>对于ASP.NET，也是类似，不同之处在于，因为SSI命令是在ASP命令运行之前被首先编译，所以文件名中不能够使用ASP.NET的变量。如果一定要用的话，就用ASP.NET的命令来做文件嵌套吧。</p>
<p>比如：</p>
<pre class="code">        &lt;%

          Response.WriteFile ("footer.html")

        %&gt;</pre>
<p>更多关于怎样在ASP.NET中实现动态文件嵌套，请参考<a title="How To Dynamically Include Files in ASP.NET" href="http://support.microsoft.com/kb/306575/EN-US/" target="_blank">微软的这篇文章</a>。</p>
<p><strong>4、JSP （Java Server Page)<br />
</strong></p>
<p>JSP文件需要在基于Java的服务器上运行，比如<a title="Apache Tomcat Homepage" href="http://tomcat.apache.org/" target="_blank">Apache Tomcat</a>。JSP包含文件的语法是：</p>
<p><tt>&lt;%@ include file="footer.html"%&gt;</tt></p>
<p><strong>5、客户端包含</strong></p>
<p><strong>5。1 </strong><strong>客户端包含</strong><strong>的利弊</strong></p>
<p>客户端包含有两种方式：Ｊａｖａｓｃｒｉｐｔ和iframe。让我们先看看两种方法各有什么利弊。</p>
<p>两种方法中Javascript生成的页面格式比较好，Javascript可以从一个URL取到页面片断然后镶嵌在另一个页面的任何位置 。其结果与服务器端包含的结果基本上一样，但弊端是客户端必须开启Javascript功能（目前大多数人是选择开启的，但也有少数出于安全方面的考虑不开启）。另一个弊端是搜索引擎是看不到由Javascript包含的页面的内容的，这对你的网站推广比较不利。</p>
<p>使用iframe比较简单，它可以强制一个HTML页面镶嵌在另一个页面中，类似于是用 object控件将Flash电影、录像、或者MP3播放器嵌入一个页面中。使用iframe，用户端不需要开启Javascript功能。但不利的方面是iframe有固定的高度和宽度，不能随着被嵌入页面的大小而改变。当被嵌入页面大于给定高宽度时，会显示滚动条(当然你也可以使用 scrolling = &#8220;no&#8221; 来强制滚动条不显示，但这样页面内容会显示不完整)，影响页面美观。另外就是搜索引擎可能不收录iframe引用的页面，不利网站推广。</p>
<p><strong> 5。2 使用JavaScript的客户端包含</strong></p>
<p>这个方法主要适用于Firefox浏览器(任何操作系统)、IE5以上(Windows)、苹果的<span id="KonaBody">Safari浏览器(</span><span id="KonaBody">MacOS X），可以使用一项叫做</span><a title="XMLHTTP wikipedia" href="http://en.wikipedia.org/wiki/XMLHttpRequest" target="_blank">XMLHTTP</a> 的API技术来通过Javascript程序读取一个动态读取一个XML文件。这种方法也可以用来读取一个HTML文件，并放到当前网页文件的指定位置。</p>
<blockquote><p><strong>专业网站设计者：不要用这个！</strong> 也许在某些情况下你不得不用JavaScript来实现网页嵌套，但是这只是一种转弯抹角的替代方法。当你的服务器可以支持前面讲的服务器端嵌套方法时，尤其是专业人士，应尽可能避免使用这种方法，因为你的客户可能会投诉你做的网页内容无法被Google搜索到，或不能在某些浏览器中正常显示。</p></blockquote>
<p>记住这种方法做的网页只能在Firefox，Safari,和IE5以上版本的浏览器中正常显示。大部分人都是用这几种浏览器的，但是不是所有人，而且有些用户因为安全因素考虑会关闭Javascript功能。</p>
<blockquote><p><strong>重要提示：</strong>如果你是在本地电脑上调试网页而不是在服务器上浏览，最新版本的ＩＥ浏览器会自动屏蔽Ｊａｖａｓｃｒｉｐｔ动态生成的部分，并显示警告信息，你必须选择&#8221;允许显示动态内容&#8221;网页才能正常显示。当你把这些网页文件放到服务器上去的时候这个问题就会自动消失的，因为IE会辨别出主页和被包含的网页内容都来自同一个服务器。</p></blockquote>
<p>好了，说了够多了，下面是具体怎么做。把以下代码放在网页的&lt;head&gt;里面：</p>
<p>&lt;script&gt;<br />
function clientSideInclude(id, url) {<br />
var req = false;</p>
<p>// Safari, Firefox, 及其他非微软浏览器<br />
if (window.XMLHttpRequest) {<br />
try {<br />
req = new XMLHttpRequest();<br />
} catch (e) {<br />
req = false;<br />
}<br />
} else if (window.ActiveXObject) {</p>
<p>// For Internet Explorer on Windows<br />
try {<br />
req = new ActiveXObject(&#8221;Msxml2.XMLHTTP&#8221;);<br />
} catch (e) {<br />
try {<br />
req = new ActiveXObject(&#8221;Microsoft.XMLHTTP&#8221;);<br />
} catch (e) {<br />
req = false;<br />
}<br />
}<br />
}<br />
var element = document.getElementById(id);<br />
if (!element) {<br />
alert(&#8221;函数clientSideInclude无法找到id &#8221; + id + &#8220;。&#8221; +<br />
&#8220;你的网页中必须有一个含有这个id的div 或 span 标签。&#8221;);<br />
return;<br />
}<br />
if (req) {<br />
// 同步请求，等待收到全部内容<br />
req.open(&#8217;GET&#8217;, url, false);<br />
req.send(null);<br />
element.innerHTML = req.responseText;<br />
} else {<br />
element.innerHTML =<br />
&#8220;对不起，你的浏览器不支持 &#8221; +<br />
&#8220;XMLHTTPRequest 对象。这个网页的显示要求 &#8221; +<br />
&#8220;Internet Explorer 5 以上版本, &#8221; +<br />
&#8220;或 Firefox 或 Safari 浏览器，也可能会有其他可兼容的浏览器存在。&#8221;;<br />
}<br />
}<br />
&lt;/script&gt;<br />
有了这段代码我们就可以在网页的任何位置插入另一个页面了。首先我们要生成一个作为&#8221;容器&#8221;的HTML控件，比如&lt;span&gt;，并给这个&#8221;容器&#8221;控件一个ID，比如includefooter，然后把这个ID和要包含的页面的URL地址传递给前面写的这个js函数clientSideInclude就可以了。</p>
<p>一个需要注意的地方是函数clientSideInclude只有在页面被完全加载后才能工作，所以我们需要在&lt;body&gt;标签的onload事件上来调用这个函数，这是最保险的调用时机，因为这个事件触发的时候浏览器肯定已经完全解析了页面中所有HTML了。</p>
<p>所以，具体代码是：</p>
<p>在需要插入另一页面的地方写：<br />
&lt;span id=&#8221;includefooter&#8221;&gt; &lt;/span&gt;</p>
<p>在页面开始处标签里写：<br />
&lt;body onLoad=&#8221;clientSideInclude(&#8217;includefooter&#8217;, &#8216;footer.html&#8217;);&gt;</p>
<p>当然，你也可以把函数clientSideInclude放在一个单独的文件里面，比如命名为clientSideInclude.js，然后在你的页面&lt;head&gt;标签中插入下面这&lt;script&gt;标签以便可以调用这个函数：<br />
&lt;script src=&#8221;clientSideInclude.js&#8221; language=&#8221;JavaScript&#8221;&gt; &lt;/script&gt;</p>
<p><strong> 5。3 使用iframe的客户端包含</strong></p>
<p>客户端页面嵌套还可以使用iframe的方法，弊端是必须事先想好被嵌套的页面在首页中要占多大的位置。如果被嵌套页面太大，超过事先定义的宽度或高度，则首页会出现滚动条。这也许正是你所需要的，但也许会完全破坏主页的设计。</p>
<p>iframe的使用很简单，下面的例子会在你的页面中嵌入另一个叫做include.html的页面：</p>
<p>&lt;iframe src=&#8221;included.html&#8221; width=&#8221;450&#8243; height=&#8221;400&#8243;&gt;</p>
<p>&lt;a href=&#8221;included.html&#8221;&gt;你的浏览器不支持iframe页面嵌套，请点击这里访问页面内容。&lt;/a&gt;</p>
<p>&lt;/iframe&gt;</p>
<p>这里主页中定义了要插入的页面将显示的高度为400的像素，宽度为450个像素。</p>
<p>我们为什么要在 iframe的里面插入一个普通的超级链接元素&lt;a&gt;呢？这是因为老版本的浏览器和搜索引擎不支持iframe，虽然现在已经很少有人还会使用Netscape 4这样老的浏览器了，但是几乎所有人都会使用象Google这样的搜索引擎。在iframe里面加上超级链接可以帮助搜索引擎找到网页的内容。</p>
<p>另外我们可以定义iframe的一些属性来控制网页的显示效果 ，除了前面用到的最常用宽度(width)和高度(height)的定义外，如果在任何情况下都不希望出现滚动条的话，可以定义iframe的scrolling属性等于“no”。如果不希望镶嵌页面的周围出现边框的话，可以将frameborder属性设置为0。下面这个例子显示了scrolling和frameborder属性的使用：</p>
<p>&lt;iframe src=&#8221;included.html&#8221; width=&#8221;450&#8243; height=&#8221;400&#8243; <span id="KonaBody"><tt>frameborder="0" scrolling="no"</tt></span>&gt;</p>
<p>&lt;a href=&#8221;included.html&#8221;&gt;你的浏览器不支持iframe页面嵌套，请点击这里访问页面内容。&lt;/a&gt;</p>
<p>&lt;/iframe&gt;<br />
参考文章：</p>
<p><a href="http://www.boutell.com/newfaq/creating/include.html" target="_blank">WWW FAQs: How do I include one HTML file in another?(fromBoutell.com)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/81/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[JAVA]怎样验证XML文件是否符合schema定义</title>
		<link>http://www.prglab.com/blog/p/78</link>
		<comments>http://www.prglab.com/blog/p/78#comments</comments>
		<pubDate>Mon, 05 May 2008 18:21:34 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/78</guid>
		<description><![CDATA[两种方法：
1。 使用SAX解析：

/***
* @param xmlPath - XML文件路径
* @param schemaPath - Schema文件路径
*/
public void saxValidation(String xmlPath, String schemaPath){
try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
saxParserFactory.setValidating(true);
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.setProperty(&#34;http://java.sun.com/xml/jaxp/properties/schemaLanguage&#34;, &#34;http://www.w3.org/2001/XMLSchema&#34;);
saxParser.setProperty(&#34;http://java.sun.com/xml/jaxp/properties/schemaSource&#34;, schemaPath);
DefaultHandler handler = new DefaultHandler();
saxParser.parse(xmlPath, handler);
} catch(SAXException exc) {
exc.printStackTrace();
}
}

2。 使用DOM解析：

/***
* @param xmlPath - XML文件路径
* @param schemaPath - Schema文件路径
*/
public void domValidation(String xmlPath, String schemaPath){
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
docBuilderFactory.setValidating(true);
docBuilderFactory.setAttribute(&#34;http://java.sun.com/xml/jaxp/properties/schemaLanguage&#34;, &#34;http://www.w3.org/2001/XMLSchema&#34;);
docBuilderFactory.setAttribute(&#34;http://java.sun.com/xml/jaxp/properties/schemaSource&#34;, schemaPath);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document [...]]]></description>
			<content:encoded><![CDATA[<p>两种方法：</p>
<p>1。 使用SAX解析：</p>
<pre class="brush: java">
/***
* @param xmlPath - XML文件路径
* @param schemaPath - Schema文件路径
*/
public void saxValidation(String xmlPath, String schemaPath){
try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
saxParserFactory.setValidating(true);
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.setProperty(&quot;http://java.sun.com/xml/jaxp/properties/schemaLanguage&quot;, &quot;http://www.w3.org/2001/XMLSchema&quot;);
saxParser.setProperty(&quot;http://java.sun.com/xml/jaxp/properties/schemaSource&quot;, schemaPath);
DefaultHandler handler = new DefaultHandler();
saxParser.parse(xmlPath, handler);
} catch(SAXException exc) {
exc.printStackTrace();
}
}
</pre>
<p>2。 使用DOM解析：</p>
<pre class="brush: java">
/***
* @param xmlPath - XML文件路径
* @param schemaPath - Schema文件路径
*/
public void domValidation(String xmlPath, String schemaPath){
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
docBuilderFactory.setValidating(true);
docBuilderFactory.setAttribute(&quot;http://java.sun.com/xml/jaxp/properties/schemaLanguage&quot;, &quot;http://www.w3.org/2001/XMLSchema&quot;);
docBuilderFactory.setAttribute(&quot;http://java.sun.com/xml/jaxp/properties/schemaSource&quot;, schemaPath);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(xmlPath);
} catch(DOMException exc) {
exc.printStackTrace();
}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/78/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用JAVA将彩色图片变为1bit黑白图片</title>
		<link>http://www.prglab.com/blog/p/73</link>
		<comments>http://www.prglab.com/blog/p/73#comments</comments>
		<pubDate>Thu, 01 May 2008 21:05:31 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/73</guid>
		<description><![CDATA[最近做的project需要涉及到对扫描图片的文字识别，需要将扫描得到的彩色图片变为1bit的黑白图片。
搜索到很多解决方案，基本的归纳为两个步骤，首先要将彩色图片变为8bit灰度图片(grayscale image)，然后再进一步变为1bit的单色图片(1bit monochrome)。
方案一：使用ColorConvert和Dithering操作
1、代码
目前JAVA最新的图片处理包应该是JAI(Java Advanced Imaging)，在JAI API的FAQ页面上，找到了下面的方法来完成这两步工作：



将彩色图片转换为8bit灰度图片(使用ColorConvert颜色转换操作)




public RenderedImage convertTo8BitGray(RenderedImage colorImage){
ParameterBlock pb = new ParameterBlock();
pb.addSource(colorImage);
ColorModel cm = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_GRAY),
new int[]{8},
false,
false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
pb.add(cm);
RenderedImage grayImage = JAI.create(&#34;ColorConvert&#34;, pb);
return grayImage;
}







将8bit灰度图片转换为1bit黑白图片 (使用errordiffusion或ordereddither操作)




public  RenderedImage applyDithering(RenderedImage grayImage, boolean isErrorDiffusion){
// Load the ParameterBlock for the dithering operation
// and set the operation name.
ParameterBlock pb = new ParameterBlock();
pb.addSource(grayImage);
String opName = null;
if(isErrorDiffusion) {
opName = &#34;errordiffusion&#34;;
LookupTableJAI lut = new [...]]]></description>
			<content:encoded><![CDATA[<p>最近做的project需要涉及到对扫描图片的文字识别，需要将扫描得到的彩色图片变为1bit的黑白图片。</p>
<p>搜索到很多解决方案，基本的归纳为两个步骤，首先要将彩色图片变为8bit灰度图片(grayscale image)，然后再进一步变为1bit的单色图片(1bit monochrome)。</p>
<h3>方案一：使用ColorConvert和Dithering操作</h3>
<h4>1、代码</h4>
<p>目前JAVA最新的图片处理包应该是JAI(Java Advanced Imaging)，在<a href="http://java.sun.com/products/java-media/jai/forDevelopers/jaifaq.html#1bit" target="_blank">JAI API的FAQ页面</a>上，找到了下面的方法来完成这两步工作：</p>
<table style="border-color: #aaaaaa; border-width: 1px; height: 237px;" border="0" width="566">
<tbody>
<tr>
<td style="border: 1px solid #cccccc; background-color: #eeeeee">将彩色图片转换为8bit灰度图片(使用ColorConvert颜色转换操作)</td>
</tr>
<tr>
<td style="border: 1px solid #cccccc">
<pre class="brush: java">
public RenderedImage convertTo8BitGray(RenderedImage colorImage){
ParameterBlock pb = new ParameterBlock();
pb.addSource(colorImage);
ColorModel cm = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_GRAY),
new int[]{8},
false,
false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
pb.add(cm);
RenderedImage grayImage = JAI.create(&quot;ColorConvert&quot;, pb);
return grayImage;
}</pre>
</td>
</tr>
</tbody>
</table>
<table style="border-color: #aaaaaa; border-width: 1px; height: 40px;" border="0" width="566">
<tbody>
<tr>
<td style="border: 1px solid #cccccc; background-color: #eeeeee">将8bit灰度图片转换为1bit黑白图片 (使用errordiffusion或ordereddither操作)</td>
</tr>
<tr>
<td style="border: 1px solid #cccccc">
<pre class="brush: java">
public  RenderedImage applyDithering(RenderedImage grayImage, boolean isErrorDiffusion){
// Load the ParameterBlock for the dithering operation
// and set the operation name.
ParameterBlock pb = new ParameterBlock();
pb.addSource(grayImage);
String opName = null;
if(isErrorDiffusion) {
opName = &quot;errordiffusion&quot;;
LookupTableJAI lut = new LookupTableJAI(new byte[] {(byte)0x00, (byte)0xff});
pb.add(lut);
pb.add(KernelJAI.ERROR_FILTER_FLOYD_STEINBERG);
} else {
opName = &quot;ordereddither&quot;;
ColorCube cube = ColorCube.createColorCube(DataBuffer.TYPE_BYTE,
0, new int[] {2}); //尝试改变2为其它值，可以得到不同效果
pb.add(cube);
pb.add(KernelJAI.DITHER_MASK_441);
}
// Create a layout containing an IndexColorModel which maps
// zero to zero and unity to 255.
ImageLayout layout = new ImageLayout();
byte[] map = new byte[] {(byte)0x00, (byte)0xff};
ColorModel cm = new IndexColorModel(1, 2, map, map, map);
layout.setColorModel(cm);
// Create a hint containing the layout.
RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
// Dither the image.
bwImage = JAI.create(opName, pb, hints);
return bwImage;
}
</pre>
</td>
</tr>
</tbody>
</table>
<h4>2、问题</h4>
<p>这段sample code在很多地方都被提到过，我不知道别人是否能够让它顺利执行，但是在我的机器上是不行的。</p>
<p>问题主要出在第一个convertTo8BitGray()函数里的ColorConvert操作上。在执行完ColorConvert之后，图片的ColorModel的numberOfComponents变为1。我的理解是因为变为灰度图片，只有一个色了。</p>
<p>然而不知为什么，图片的SampleModel的numberOfBands却仍然保持了3，这就造成了SampleModel和ColorModel 不兼容，所以程序总是抛出<span style="color: #ff0000;">java.lang.IllegalArgumentException: The specified ColorModel is incompatible with the image SampleModel&#8230;</span>的错误。</p>
<p><span id="more-73"></span></p>
<h3>方案二：使用重画到灰度图片上的方法</h3>
<p>后来我在Code Beach看到了<a href="http://blog.codebeach.com/2008/03/convert-color-image-to-gray-scale-image.html" target="_blank">这篇文章</a>，试用了里面的第二个方法 &#8212; 将彩色图片画到一个灰度图片上的方法，终于可以成功将彩色图片转化为8bit的灰度图片。代码如下：</p>
<pre class="brush: java">
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Graphics g = image.getGraphics();
g.drawImage(colorImage, 0, 0, null);
g.dispose();
</pre>
<p>转换的效果如下图所示：</p>
<table style="height: 22px;" border="0" width="24">
<tbody>
<tr>
<td>转换前：彩色图片<br />
<a title="rose.jpg" rel="attachment wp-att-74" href="http://www.prglab.com/blog/p/73/rosejpg"><br />
<img src="http://www.prglab.com/blog/wp-content/uploads/rose.jpg" alt="rose.jpg" width="250" /></a></td>
<td>转换后：灰度图片<br />
<a title="rose_gray.jpg" rel="attachment wp-att-77" href="http://www.prglab.com/blog/p/73/rose_grayjpg"><br />
<img src="http://www.prglab.com/blog/wp-content/uploads/rose_gray.jpg" alt="rose_gray.jpg" width="250" /></a></td>
</tr>
</tbody>
</table>
<p><!--more--></p>
<h3>使用Binarize将8bit灰度图片转换为1bit黑白图片</h3>
<p>将彩色图片转换为灰度图片后，仍然可以用前面程序例子中的applyDithering()方法来将8bit灰度图片进一步转换为1bit黑白图片，得到的效果比较象报纸上的黑白图片，保留了很多灰度的层次。<br />
为了能够更进一步得到版画效果的图片，可以使用Binarize操作。改变Binarize操作的域值(threshold)也可以得到不同效果。<br />
<strong>代码：</strong></p>
<pre class="brush: java">
/***
* Binarize image (convert image to 1 bit black and white)
* 输入图片必须为灰度图片，否则会出错。
*/
public RenderedImage applyBinarize(RenderedImage grayImage) {
// Generate a histogram.
Histogram histogram =
(Histogram)JAI.create(&quot;histogram&quot;, grayImage).getProperty(&quot;histogram&quot;);
// Get a threshold equal to the median.
double[] threshold = histogram.getPTileThreshold(0.4); //改变域值可以得到不同效果
// Binarize the image.
RenderedImage bwImage =
JAI.create(&quot;binarize&quot;, grayImage, new Double(threshold[0]));
return bwImage;
}//function applyBinarize
</pre>
<p><strong>效果：</strong></p>
<table border="0">
<tbody>
<tr>
<td>使用Dithering的效果</td>
<td>使用Binarizing的效果</td>
</tr>
<tr>
<td><a title="rose_dithering.jpg" rel="attachment wp-att-76" href="http://www.prglab.com/blog/p/73/rose_ditheringjpg"><img src="http://www.prglab.com/blog/wp-content/uploads/rose_dithering.jpg" alt="rose_dithering.jpg" width="250" /></a></td>
<td><a title="rose_bw.jpg" rel="attachment wp-att-75" href="http://www.prglab.com/blog/p/73/rose_bwjpg"><img src="http://www.prglab.com/blog/wp-content/uploads/rose_bw.jpg" alt="rose_bw.jpg" width="250" /></a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/73/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ABAP中如何检查字母数字类型(alpha numeric)的变量</title>
		<link>http://www.prglab.com/blog/p/72</link>
		<comments>http://www.prglab.com/blog/p/72#comments</comments>
		<pubDate>Sat, 12 Apr 2008 03:02:50 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[ABAP]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/72</guid>
		<description><![CDATA[Business requirment经常要求某个ID的值只能包含26个字母和10个数字字符，这就要求ABAP程序能够检查相应变量内容，辨别特殊字符。sap-img上的一个例子提供了这样的功能：
REPORT ZCHECK_ALPHA_NUMERIC.
* Declare the variable
* For Length 
data: serial_length type i.
* For Alpha numeric 
data: str type string.
data: valid_characters type string.
* Fill in those valid characters you need to check 
concatenate &#8216;0123456789&#8242; &#8216;ABCDEFGHIJKLMNOPQRSTUVWXYZ&#8217;
&#8216;abcdefghijklmnopqrstuvwxyz&#8217; into valid_characters.
* User Input 
parameters testchar(10) default &#8216;12345abc&#8217;.
* Get User Input 
str = testchar.
* The Checks 
if str co valid_characters.
write: / [...]]]></description>
			<content:encoded><![CDATA[<p>Business requirment经常要求某个ID的值只能包含26个字母和10个数字字符，这就要求ABAP程序能够检查相应变量内容，辨别特殊字符。<a href="http://www.sap-img.com/abap/check-length-and-alpha-numeric-variable.htm" target="_blank">sap-img上的一个例子</a>提供了这样的功能：</p>
<p>REPORT ZCHECK_ALPHA_NUMERIC.</p>
<p><font color="#3366ff">* Declare the variable</font></p>
<p><font color="#3366ff">* For Length </font><br />
data: serial_length type i.</p>
<p><font color="#3366ff">* For Alpha numeric </font><br />
data: str type string.<br />
data: valid_characters type string.</p>
<p><font color="#3366ff">* Fill in those valid characters you need to check </font><br />
concatenate &#8216;0123456789&#8242; &#8216;ABCDEFGHIJKLMNOPQRSTUVWXYZ&#8217;<br />
&#8216;abcdefghijklmnopqrstuvwxyz&#8217; into valid_characters.</p>
<p><font color="#3366ff">* User Input </font><br />
parameters testchar(10) default &#8216;12345abc&#8217;.</p>
<p><font color="#3366ff">* Get User Input </font><br />
str = testchar.</p>
<p><font color="#3366ff">* The Checks </font><br />
if str co valid_characters.<br />
write: / str, &#8216;Characters are OK&#8217;.<br />
else.<br />
write: / str, &#8216;Characters are NOT OK&#8217;.<br />
endif.</p>
<p>*&#8211; End Program</p>
<p>基于同样的原理，下面这个subroutine可以去掉一个字符串中的所有特殊字符</p>
<p><font color="#3366ff">*&amp;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*<br />
*&amp;      Form  convert_character_entities<br />
*&amp;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;*<br />
*  This form removes all non-alpha-numeric characters from a string<br />
*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-*<br />
*      &lt;&#8211;<br />
*&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-*</font><br />
FORM remove_non_alpha_numeric_char.<br />
DATA: l_teststr       TYPE string,<br />
l_alpha_numeric TYPE string.<br />
DATA: l_strlen TYPE i.</p>
<p>DATA: l_char TYPE c.</p>
<p>l_teststr = &#8216;ref0 0@2$45*8&#8242;.<br />
l_strlen = strlen( l_teststr ).<br />
WRITE: / l_teststr, &#8216;length:&#8217;, l_strlen.</p>
<p>l_alpha_numeric = &#8216;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&#8217;.</p>
<p>WHILE l_strlen &lt;&gt; 0.<br />
l_strlen = l_strlen &#8211; 1.<br />
l_char = l_teststr+l_strlen(1).<br />
IF l_alpha_numeric NA l_char.<br />
REPLACE SECTION OFFSET l_strlen LENGTH 1 OF l_teststr WITH &#8221;.<br />
ENDIF.<br />
ENDWHILE.<br />
l_strlen = strlen( l_teststr ).<br />
WRITE: / l_teststr, &#8216;length:&#8217;, l_strlen.</p>
<p>ENDFORM.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/72/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SAP中国家代码和国家名称对应查询</title>
		<link>http://www.prglab.com/blog/p/71</link>
		<comments>http://www.prglab.com/blog/p/71#comments</comments>
		<pubDate>Fri, 28 Mar 2008 18:17:16 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[ABAP]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/71</guid>
		<description><![CDATA[SAP中的国家代码表是T005T.
另外 ADRC表的COUNTRY字段的帮助视图(Help View)，也可以看到country code 和 country name的对应表。
]]></description>
			<content:encoded><![CDATA[<p>SAP中的国家代码表是T005T.</p>
<p>另外 ADRC表的COUNTRY字段的帮助视图(Help View)，也可以看到country code 和 country name的对应表。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/71/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ABAP字符串比较操作中空格的影响</title>
		<link>http://www.prglab.com/blog/p/70</link>
		<comments>http://www.prglab.com/blog/p/70#comments</comments>
		<pubDate>Wed, 26 Mar 2008 17:50:34 +0000</pubDate>
		<dc:creator>Aqua</dc:creator>
				<category><![CDATA[ABAP]]></category>

		<guid isPermaLink="false">http://www.prglab.com/blog/p/70</guid>
		<description><![CDATA[ABAP对字符串有很多隐形的操作，有时更方便程序员，有时又比较容易使人困惑。
比如在比较字符串的值时，ABAP会自动忽视有效字符后面的空格，而如果在字符前面有空格，则会影响比较的结果。
比如： &#8216;X&#8217; 和 &#8216;X__&#8217; 比较的结果是相等；而&#8217;X'和&#8217;__X&#8217;比较的结果则是不相等。 （这里下划线__代表空格）
运行下面的程序可以看到效果：
DATA: l_string1 TYPE string,
l_string2 TYPE string,
l_string3 TYPE string.
l_string1 = &#8216;X&#8217;. &#8220;No space
l_string2 = &#8216;X &#8216;. &#8220;Space after X
l_string3 = &#8216; X&#8217;. &#8220;Space before X
IF l_string1 EQ l_string2.
WRITE: / &#8216;String 1 and String 2 are identical.&#8217;.
ELSE.
WRITE: / &#8216;String 1 and String 2 are NOT identical.&#8217;.
ENDIF.
IF l_string1 EQ l_string3.
WRITE: / &#8216;String 1 [...]]]></description>
			<content:encoded><![CDATA[<p>ABAP对字符串有很多隐形的操作，有时更方便程序员，有时又比较容易使人困惑。</p>
<p>比如在比较字符串的值时，ABAP会自动忽视有效字符后面的空格，而如果在字符前面有空格，则会影响比较的结果。</p>
<p>比如： &#8216;X&#8217; 和 &#8216;X__&#8217; 比较的结果是相等；而&#8217;X'和&#8217;__X&#8217;比较的结果则是不相等。 （这里下划线__代表空格）</p>
<p>运行下面的程序可以看到效果：</p>
<p>DATA: l_string1 TYPE string,<br />
l_string2 TYPE string,<br />
l_string3 TYPE string.<br />
l_string1 = &#8216;X&#8217;. &#8220;No space<br />
l_string2 = &#8216;X &#8216;. &#8220;Space after X<br />
l_string3 = &#8216; X&#8217;. &#8220;Space before X<br />
IF l_string1 EQ l_string2.<br />
WRITE: / &#8216;String 1 and String 2 are identical.&#8217;.<br />
ELSE.<br />
WRITE: / &#8216;String 1 and String 2 are NOT identical.&#8217;.<br />
ENDIF.<br />
IF l_string1 EQ l_string3.<br />
WRITE: / &#8216;String 1 and String 3 are identical.&#8217;.<br />
ELSE.<br />
WRITE: / &#8216;String 1 and String 3 are NOT identical.&#8217;.<br />
ENDIF.</p>
<p>运行结果是输出:</p>
<blockquote><p>String 1 and String 2 are identical.</p>
<p>String 1 and String 3 are NOT identical.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.prglab.com/blog/p/70/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
