手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表2009年01月的文章

xml?xsl?css?xhtml

虽然,我写页面代码都是editplus写的,从来不用DW或者其他所见所得编辑器,但并不代码我的CSS就写的特别好,其实我一直很有疑问。CSs是否就是王道?

然后我看到这篇文章,觉得也是我心里想的东西。就贴出来了。。。

其实去年年底,jQuery 1.3尚未发布的时候就已经盘算着将中文文档以xml的形式发布了。这样有个好处,就是页面结构可以用xsl随便换。各位同学想做不同的发行版可以随便换 着玩~实际上我现在愈发觉得css的局限性了,很多时候所谓的css为了后期维护方便,可以任意修改布局而无需动页面结构之类的话语已经觉得难以置信了。 我就不信有多少同学遇到过改版的时候只改css而不改html的。当然也有可能是我的局限性而非css的局限性。

所谓的圣杯布局双飞翼布局确实在很大程度上能解决布局(Layout)上的问题,但别忘了,开发工作可不只是布局,还有排版(Typography),数据结构和页面表现结构交织在一起的时候,想崩溃都觉得老板会从地域里拖你起来。

xml+xslt这种手段其实我几年前就看到过,当时也曾为之心动,无奈当时技术水平有限无法体会其中精妙。然借此jQuery 1.3文档大改之际便又萌发了尝试的冲动。

xml+xslt好吗?很好!居然ie 5就开始支持了,ie 6支持的程度也很不错,基本上没有遇到什么兼容性问题,比起万恶的ie6对css的支持度好多了。目前我除了发现document()函数在ie中表现的跟其他浏览器不一致之外,以及Firefox居然不支持disable-output-escaping=”yes”,并且争论长达7年多尚未有解决的迹象。除此之外似乎没发现更多问题。

实际上让一部分处理页面的逻辑放到了前端来做,后台只负责输出数据,这种数据(XML),结构(XSLT),表现(CSS),行为(JS)4者相对 分离的状态是十分有利于这个前端产业工业化发展的。随着前端工种的进一步细分,我觉得这里大有可挖。好处显而易见,如果要大面积改版(即便是小范围),由 于后台只负责输出数据而没有HTML格式,高度分离的情况下,基本上只需要前端小组改一下即可。即便是对后台语言完全不了解都可以(我承认这不好)。
此外,xslt支持include/import等语句,包括上面提到的document(),可以很方便的实现页面各个部分的模块化。

但随之带来的问题也显而易见,数据过于结构化,页面内容轻易被人抓取而后分析(都不用分析……直接解析……)
此外,很多pda,手机之类的可能对xslt无法解析,但我估计屏幕阅读器应该没问题,因为很多屏幕阅读器都是基于现有浏览器的,也就是说现有浏览器支持,他也就支持。
还有上面提到的模块化问题,一不小心就可能导致连接数过多。每个模块的粒度得把握好。

解决这些问题的一个简单途径是,xml+xslt在服务器端解析生成。服务器端可以通过检测浏览器来判断直接输出xml+xslt还是输出生成的页面。这对于pda和手机之类的能提高很大兼容性。而对于一般浏览器又无需消耗服务器资源。
网上有篇流传甚广的文章XML在B/S架构开发中的应用,正是描述了此类情景。我考据下来可能是原著地址(我找到个更早的地址但上面的写的作者也是他,请宽恕我的网络考古情结)。

其中也提到了http://xml.apache.org/cocoon/ 似乎可以直接使用,没深究。

好了,得回到正题了。jQuer现在弄了个专门是放api的地址:http://api.jquery.com。 说实话,我一直很不喜欢他现在弄的样子,当我需要在不同的方法之间切换的时候很不方便。有喜欢的可以自己尝试。另外,分析代码发现原来这个api也是从 wiki里扣出来的xml进行解析得来的。另有air版,喜欢的可以自己下。扣的程序是Python 2.4写的,遗憾我这里只有Py3k环境,执行失败,且自己道行过浅,无法改成3.0版以供自己用。忘有此能力的同学能帮我改一下,可直接从jq的svn 里拿到,点击下载。没有达人帮忙其实也没事,见到还有地址可以在线生成,前面在线生成的地址如果不加参数则可以直接查看这个生成器的文档。用urllib.request.urlretrieve(url,path)直接下载真的是很惬意的事情,Python真的是很强悍啊……
我随便写了个xslt,可以直接浏览jQuery 的英文文档。暂不提供下载,喜欢的就自己另存为吧……不喜欢的就自己写一套吧……
暂时计划是将中文文档转换成xml(这步已经在前天完成,转的我残念……请原谅我能力有限只能用这么离奇的办法转 格式……)。不过之前写这个的时候还没有看到上面那个wiki2xml生成器(其实早就见过了,被我无视了而已……),所以对应的标签以及格式还不是很对 上号。改天整整。另外,单个xml拆分成散件的xml的py脚本也写完了,实验成功,现在生成chm版的文档只差单文件xml的校对和chm文件的目录以 及索引之类的编辑工作了。不用太期待……一揪回家了……新年饭局又多……饿……大半夜的吐槽可真不好……睡去了……
原文:http://shawphy.com/2009/01/about-jquery-xml-doc.html

————————END————————

到底什么是最好,什么是最方便?我也一直很犹豫,也很苦恼。。

随手转贴的:我为什么要使用google的CDN

 

看到这篇文章,就随手转贴了一下,因为我自己也在使用这样的功能,而且,现在的网站几乎都有google的广告。所以从yahoo的14条军规来说,这并不违反这个规则:使用CDN,尽量不要有超过4个域名的链接。所以你想呀,有一些google广告和yahoo的统计再加上1至2个其他的链接,肯定是没有超过4个域名了。CDN,有现成的,使用了,也算是完成了14条军规中的一些了。不是吗?所以。。。。。。

原文:http://shawphy.com/2009/01/why-google-cdn.html

自从之前jQuery 1.3版起,就已经没有提供pack版了,而我也十分赞成使用Google CDN进行代码托管。

这样做有以下几个好处:
1,更小下载量。
都知道jQuery 1.3 pack后有38k之多,如果当然可以删除版权注释以获得更小的代码,遗憾的是这不仅无耻且只节约1个k都不到。而同样利用Google APIs 提供的GZip过的Min版,只有18k,对用户来说下载量更小。

2,减轻服务器压力。
虽然现代浏览器都有了缓存,但以前我看到过资料说某大型网站发现他们70%的访客缓存都是空的(哪位同学能帮忙找到资料请下面留言,不胜感激~)。所以,让Google为我们提供服务,而不用自己操心自己的流量~少个库可以少个连接数,何乐而不为。

3,多个网站共享缓存。

如果用户访问的多家网站都使用Google提供的jQuery,那么对于用户来说,只需要缓存一次后即可只读取缓存中的数据!而不是每个网站都要重新下载一份。对此进一步加快用户访问速度。

4,更快执行速度。
jQuery 1.3.1发布的发布信息中, 为jQuery不提供pack版给出了官方的解释。除了不易debug,在Adobe AIR和Caja-capable等环境下无法使用之外,更重要的是因为执行速度问题。随着jQuery逐渐变“胖”,用pack压缩后在浏览器端“解压 缩”所需要的资源越来越大。想象一个超大的字符串多次replace后再eval的情景……这不比直接读取一个不需要解压缩的min版来得快。John给 出了一些数据,有兴趣的同学可以看看。

反对的声音:
“不安全”、“没安全感”、“放别人的机器太危险了”、“他们服务器倒了呢?”、“以前刚开始的时候就down过”

我认为(晕……怎么我觉得我在写四六级作文……)Google服务器down的几率与我们自己服务器down的几率不会有显著性差异(抱歉,我又空 口无凭说话了……不过如果哪位同学能给出数据来拒绝我的零假设,认可备选假设的,欢迎提供,再次不胜感激~)。所以就放他们那边吧,挺安全的。

另外我还听到关于不能让整个世界为着Google转,Google阴谋论,Google威胁论的声音。实际上Google确实正朝这个方向发展,让 整个互联网围着他转。可以看他提供的一些服务,什么云计算,什么App Engine之类的,都企图让人们的应用都建立在Google至上,当Google成为了空气的时候,他已经无处不在了。这点来说,值得担忧。

Tags: cdn, google, yahoo

SVN知识

trunk:表示开发时版本存放的目录,即在开发阶段的代码都提交到该目录上。
branches:表示发布的版本存放的目录,即项目上线时发布的稳定版本存放在该目录中。
tags:表示标签存放的目录。

在这需要说明下分三个目录的原因,如果项目分为一期、二期、三期等,那么一期上线时的稳定版本就应该在一期完成时将代码copy到branches 上,这样二期开发的代码就对一期的代码没有影响,如新增的模块就不会部署到生产环境上。而branches上的稳定的版本就是发布到生产环境上的代码,如 果用户使用的过程中发现有bug,则只要在branches上修改该bug,修改完bug后再编译branches上最新的代码发布到生产环境即可。 tags的作用是将在branches上修改的bug的代码合并到trank上时创建个版本标识,以后branches上修改的bug代码再合并到 trunk上时就从tags的version到branches最新的version合并到trunk,以保证前期修改的bug代码不会在合并。

branches其实也就是分支,它究竟是干什么用的呢?

分支用于解决什么样的问题?

在手机游戏开发过程中,经常会遇到多种机型移植的问题。通常开发人员都说以一种机型作为 release 基础版本的目标,然后再此基础上进行相关的适配工作,如,键值修改,屏幕大小的修改单等。

然而同时维护多个版本是异常头疼的事情,因为很少有人能保证在移植之前,基础版本是没有 bug 的,特别是在工期很紧的情况下。这样一来,基础版本中出现了 bug ,就需要手动的“ Ctrl+C/Ctrl+V ”到其他的所有版本,各种版本的管理非常混乱,经常一不小心就会出现这样那样的问题。

 

而 SVN 的分支 (branch) 虽然不能做到自动将基础版本中的修改复制到其他版本中,却可以对各种版本的管理提供更有效和更规范的支持,避免了很多人为造成的问题。使用 SVN 来管理,可以将基础版本作为主干 (trunk) ,并从项目启动到 alpha 版本的推出,都可以在主干上进行开发。 alpha 版本发布以后,对于其他版本可以分别建立分支,如: branch_moto , branch_s603 等

 

如何创建分支?

创建分支非常简单,只需在需要创建分支的工作目录上,使用TortoiseSVN → Branch/Tag命令,在 "To URL" 项指定待创建的分支 url 即可。具体 可查看TortoiseSVN的帮助文档中的“ Braching/Taging ”一节

 

 

如何在分支下工作?

假设我们的主干名为 trunk ,分支目录名为 branch branch 实际上是 trunk 目录在 branch 创建时的 copy ,而创建以后, branch trunk 实际就是互不干扰的工作了, branch 上的修改不会影响到 trunk ,反之亦然。

 

如何合并分支?

事实上,我们并没有解决本文开头所提出的问题,即, trunk 有了修改之后,并不会自动提交到 branch 中(不知道有没有其他的版本管理工具可以做到),这一切都需要手动来实现,而这个过程在 SVN 中称为“合并 (merge) ”。

SVN 合并与原始的“ Ctrl+C/Ctrl+V ”相比,有以下几点好处(假设是将 trunk 合并到 branch 中):

1 trunk 中新增的文件可以自动合并到 branch

2 、提示 trunk branch 中的同名文件的冲突内容,便于用于编辑冲突

 

合并操作步骤

TortoiseSVN 中提供便捷的合并功能。在待合并的工作目录上(如: branch ),使用TortoiseSVN → Merge命令,在“ From:(start URL and revision of the range to merge) ”中选择希望合并的目录 ( 如: trunk) ,并指定希望合并的开始 revision 编号,在“ To:(end URL and revision of the range to merge) ”中选择结束 revision 编号。然后点击“ merge ”完成合并操作,剩下的工作就是编辑冲突了,当然运气好的话是不需要这个过程滴。

值得注意的是,“ From: ”和“ To: ”中的 URL 通常是相同的,切记不要与创建分支时的含义混淆。

与合并相关的操作可查看TortoiseSVN的帮助文档中的“ Merging ”一节

 

本文为两篇摘录编辑而文,原文博客为:http://www.phpweblog.net/fuyongjie/

Tags: svn, 资料

小孩会叫papa了

今天有点激动,回到家和小孩玩的时候,小孩憋了半天,叫了papa,我也就很激动的在说:叫爸爸,叫爸爸。然后他又憋了半天,终于又叫了一声papa,然后害羞的头撇过去了。

哈哈

记下今天的日子:2009年1月21日。小孩会叫papa了。

等下次会发b音的时候,我再贴上来

Tags: baby, papa

语言包?

本文也是转摘,不过看到它的时候,我想起了discuz的URL解析,discuz在做rewrite的时候,并没有主动都对模版中的链接进行更换,而是在输出前,对于符合规则的那些链接使用rewrite的规范进行了一次批量替换。

这次我转摘的文章也是用了类似的方法,只是他又是.NET处理的,我也不翻译了。知道了原理就行了(和discuz一样,不过这种方法应该只适合做语言包)

原文:

一直以来多语言问题都是个让人头疼的问题,不是这个问题有多难,而是很繁琐,而我们目前的这个项目有点特殊,我希望最大限度的化繁为简,以下是我解决这个问题的方案。
我们的项目有这样两个前提:
1、要支持多语言但最多三种语言,一般情况下就两种语言,所以并没有随时切换语言的要求。
2、我们希望有一种可以初期不用管语言问题,之后统一翻译的方案
基于这么两点,我们提出了这样的方案:
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、在数据库中Chinese会设置为唯一约束
3、所有的翻译工作会在BasePage中的Render方法中作
4、所有的页面会继承BasePage
5、翻译时会根据当前的语言设置构建以language表中Chinese做key,相应的语言为value的字典,然后查找需要翻译的字符串是不是在字典中,如果不在就生成这一行。

 
数据库设计四个字段

ID,Chinese,English,Other

BasePage源码:

C#代码
  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Linq;  
  5. using System.Web;  
  6. using System.Web.Security;  
  7. using System.Web.UI;  
  8. using System.Web.UI.HtmlControls;  
  9. using System.Web.UI.WebControls;  
  10. using System.Web.UI.WebControls.WebParts;  
  11. using System.Xml.Linq;  
  12. using System.Text.RegularExpressions;  
  13. using System.Text;  
  14. using System.Collections;  
  15. using System.Collections.Generic;  
  16. using System.IO;  
  17. using System.Diagnostics;  
  18.   
  19. /// <summary>  
  20. ///BasePage 的摘要说明  
  21. /// </summary>  
  22. public class BasePage : System.Web.UI.Page  
  23. {  
  24.     //利用Dictionary来筛选所有的多语言标签,然后做替换,可以缓存  
  25.     Dictionary<stringstring> dic;  
  26.     public BasePage()  
  27.     {  
  28.   
  29.     }  
  30.     //需要替换的标签,标签头为数字字母下划线汉字  
  31.   
  32.     static readonly Regex re = new Regex  
  33.         (@"((\{)|(\%7B))[\w\-\+\|u4e00-\u9fa5]+?((\})|(\%7D))",  
  34.         RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);  
  35.   
  36.     //不需要替换的标签  
  37.     static readonly Regex re_nr = new  
  38.         Regex(@"<NOREPLACE>[\w\W]*?</NOREPLACE>", RegexOptions.Multiline | RegexOptions.IgnoreCase);  
  39.   
  40.     private string RenderTag(ref string content)  
  41.     {  
  42.         if (re_nr.IsMatch(content))//不需要替换标签  
  43.         {  
  44.             StringBuilder sb = new StringBuilder();  
  45.   
  46.             MatchCollection grouplist = re_nr.Matches(content);  
  47.             string[] reList = re_nr.Split(content);  
  48.   
  49.             for (int i = 0; i < grouplist.Count; i++)  
  50.             {  
  51.                 sb.Append(ReplaceTag(ref reList[i]));  
  52.                 sb.Append(grouplist[i].Value);  
  53.                 sb.Append(ReplaceTag(ref reList[i + 1]));  
  54.             }  
  55.   
  56.             content = sb.ToString();  
  57.         }  
  58.         else  
  59.         {  
  60.             content = ReplaceTag(ref content);  
  61.         }  
  62.         return content;  
  63.     }  
  64.   
  65.     private string ReplaceTag(ref string content)  
  66.     {  
  67.         //模板标签{yes},{no},{search}  
  68.         MatchCollection mc = re.Matches(content);  
  69.   
  70.         if (dic == null)  
  71.         {  
  72.             dic = LanguageManager.GetResource();  
  73.         }  
  74.   
  75.         for (int i = 0; i < mc.Count; i++)  
  76.         {  
  77.             //如果数据库中还没有此字符串  
  78.             if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))  
  79.             {  
  80.                  content = content.Replace(mc[i].Value, mc[i].Value.TrimStart('{').TrimEnd('}'));  
  81.   
  82.                 if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))  
  83.                 {  
  84.                     LanguageManager.AddLanguageString(mc[i].Value.TrimStart('{').TrimEnd('}'));  
  85.                 }  
  86.             }  
  87.             else if (dic[mc[i].Value.TrimStart('{').TrimEnd('}')] == null)  
  88.             {  
  89.                 content = content.Replace(mc[i].Value, "$$$$");  
  90.             }  
  91.             else  
  92.             {  
  93.   
  94.                 content = content.Replace(mc[i].Value, dic[mc[i].Value.TrimStart('{').TrimEnd('}')].ToString());  
  95.   
  96.   
  97.             }  
  98.         }  
  99.           
  100.         return content;  
  101.     }  
  102.     protected override void Render(HtmlTextWriter writer)  
  103.     {  
  104.   
  105.         Stopwatch stopwatch = new Stopwatch();  
  106.         stopwatch.Reset();  
  107.         stopwatch.Start();  
  108.         try  
  109.         {  
  110.             //会把页面的输出结果存储在这个StringBuilder中  
  111.             StringBuilder sb = new StringBuilder();  
  112.             StringWriter sw = new StringWriter(sb);  
  113.             HtmlTextWriter htw = new HtmlTextWriter(sw);  
  114.             base.Render(htw);  
  115.             string content = sb.ToString();  
  116.   
  117.             content = RenderTag(ref content);  
  118.   
  119.             //重新写入页面  
  120.             writer.Write(content);  
  121.   
  122.         }  
  123.         catch (Exception ex)  
  124.         {  
  125.             Response.Write(ex.ToString());  
  126.             Response.End();  
  127.         }  
  128.         finally  
  129.         {  
  130.             stopwatch.Stop();  
  131.             Response.Write("runtime:" + stopwatch.ElapsedMilliseconds.ToString() + "ms");  
  132.         }  
  133.   
  134.     }  
  135. }  
这样设计的
优点
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、省去了大量命名相应文字的工作
3、直接用中文标示要显示到页面的文字,容易理解

缺点
1、如果中文是一样的翻译,而其他语言翻译却不一样时不好解决,但这种情况似乎不常见

————————END————————

缺点就是我说的,只能用来做语言包,呵呵。

Tags: web, 语言包, 数据库

Records:44123456789