2005年1月20日星期四

Delphi的SOAP Header问题

对于我的程序,服务器要求的Header是这样(只是要添加两个简单的元素):


BigLuo
111


但Delphi中的SOAPHeader只能通过继承TSOAPHeader来实现,但这样就会把派生类的名字添加上去,变成了这样:



4
2005-01-06T15:01:26.531Z



怎么办?




1.Delphi给了一个SOAP Header的示例



4
2005-01-06T15:01:26.531Z




实现方法是:
1.先定义一个TSOAPHeader的继承类,要在SOAP包中出现的字段以property方式出现

AuthHeader = class(TSOAPHeader)
private
FAccNumber: Integer;
FTimeStamp: TXSDateTime;
public
destructor Destroy; override; //用于释放FTimeStamp,别无它用
published
property AccNumber: Integer read FAccNumber write FAccNumber;
property TimeStamp: TXSDateTime read FTimeStamp write FTimeStamp;
end;

2.在initialization中注册

InvRegistry.RegisterHeaderClass(TypeInfo(IBankAccount), AuthHeader, 'AuthHeader', 'urn:BankAccountIntf');
RemClassRegistry.RegisterXSClass(AuthHeader, 'urn:BankAccountIntf', 'AuthHeader');

3.使用:

var
H: AuthHeader;
svc: IBankAccount;
begin
svc := HTTPRIO1 as IBankAccount;

H := AuthHeader.Create;
try
H.AccNumber := FAuthKey;
H.TimeStamp := DateTimeToXSDateTime(FTimeStamp, True);
if UseHeader then
(svc as ISOAPHeaders).send(H);
svc.some_method(...)
finally
H.Free;
end


2. 我的要求和问题
对于我的程序,服务器要求的Header是这样


BigLuo
111


与上面的不同是Header下直接是两个元素,没有一个NS1:AuthHeader的外包层

仔细查看了一下Delphi的帮助,在Defining and using SOAP headers一节淘到如下一段

Handling scalar-type headers

Some Web Services define and use headers that are simple types (such as an integer or string) rather than a complex structure that corresponds to a remotable type. However, Delphi's support for SOAP headers requires that you use a TSOAPHeader descendant to represent header types. You can define header classes for simple types by treating the TSOAPHeader class as a holder class. That is, the TSOAPHeader descendant has a single published property, which is the type of the actual header. To signal that the SOAP representation does not need to include a node for the TSOAPHeader descendant, call the remotable type registry's RegisterSerializeOptions method (after registering the header type) and give your header type an option of xoSimpleTypeWrapper.


从最后一句看,我只要这样定义:

HdrUsername = class(TSOAPHeader)
private
FUsername: String;
published
property Username: String read FUsername write FUsername;
end;

然后按如下方式注册

InvRegistry.RegisterHeaderClass(TypeInfo(ezMsgServer), HdrUsername, 'Username', ');
RemClassRegistry.RegisterSerializeOptions(TypeInfo(HdrUsername), [xoSimpleTypeWrapper]);

(Password一项也类似处理)
应该就可以了。

但运行一下发现文档里面说的根本就不对,而是这样:



y19451


mypass



看样子xoSimpleTypeWrapper根本没有任何作用(不加那一句也是这个结果)

3. 问题的解决


在帮助文件里面来回折腾了半天,看到RegisterSerializeOptions的帮助里提到这样一个选项

xoHolderClass
The remotable object corresponds to a "holder" class. That is, the SOAP representation does not include a node for the class itself, just for its members. This is used when a type that would otherwise not require a remotable class uses a feature only available on remotable classes (such as attributes).

这个选项倒好像跟我的需求比较接近哦,试试!
结果又是失望。“希望,失望,希望,失望”,麦兜抱怨到。

在google上搜索了半天没有发现什么有用的结果,在无望之余回来又来看Delphi提供的例子,注意到它的例子中将AuthHeader这个类注册了一下:
RemClassRegistry.RegisterXSClass(AuthHeader, 'urn:BankAccountIntf', 'AuthHeader');
对啊,这个类应该在Remote Class Registry里面注册,于是加上HdrUsername和HdrPassword的注册语句, 再试,搞定!

总结一下:
帮助里面说的应该是纯常量作为Header的情况,对于我这种......的情况,应该按如下方式处理:
1. 按上面所说,声明HdrUsername和HdrPassword
2. 在initialization时按如下方式注册

InvRegistry.RegisterHeaderClass(TypeInfo(ezMsgServer), HdrUsername, 'Username', ');
RemClassRegistry.RegisterXSClass(HdrUsername, ', 'Username', 'Username');
RemClassRegistry.RegisterSerializeOptions(TypeInfo(HdrUsername), [xoHolderClass]);

InvRegistry.RegisterHeaderClass(TypeInfo(ezMsgServer), HdrPassword, 'Password', ');
RemClassRegistry.RegisterXSClass(HdrPassword, ', 'Password', 'Password');
RemClassRegistry.RegisterSerializeOptions(HdrPassword, [xoHolderClass]);


其实这样也可以(而且简单一点):
1. 将Username和Password声明在一个Header内
以下内容为程序代码:

TezMsgHdr = class(TSOAPHeader)
private
FUsername: String;
FPassword: String;
published
property Username: String read FUsername write FUsername;
property Password: String read FPassword write FPassword;
end;

2.将TMsgHdr注册:

InvRegistry.RegisterHeaderClass(TypeInfo(ezMsgServer), TezMsgHdr, 'Username', ', hmtRequest);
RemClassRegistry.RegisterXSInfo(TypeInfo(TezMsgHdr), ', 'Username', 'Username');
RemClassRegistry.RegisterSerializeOptions(TypeInfo(TezMsgHdr), [xoSimpleTypeWrapper, xoHolderClass]);

总的来说,还是看E文水平不够啊

4. 其他

细心的话,可以注意到后面一种方法里面多了一个xoSimpleTypeWrapper选项。其实对于后一种方法的复杂类TezMsgHdr, 这个选项是无效的,但对于前一种,就有些不同了(正如其名称所表明的那样,只有真正是SimpleType才有作用):

a. 如果只对HdrUsername加xoSimpleTypeWrapper选项:

y19451Password

可以注意到Username元素不见了,只能见到其值y19451赤裸地出现,而Password一项正常

b.如果只对HdrPassword加xoSimpleTypeWrapper选项:
运行时会出现"Element does not contain a single text node"这样的错误。我估计SOAP Header如下,Password的出现导致了这不是一个合法的XML

y19451Password


c.如果两者都加xoSimpleTypeWrapper选项,结果会是怎样呢?

Password

居然Username都不见了

转: debian 中文系统配置

我对于过于复杂地寻求"美化"之道不是没有兴趣,而是没有精力去琢磨。这篇文章提供的方法比较简单,用来show给新手看,其实我是不喜欢拿 simsun这种有版权的字体来搞的。(另外,初装系统需要中文支持的话,可以先试试从tasksel里面选择Simplified Chinese, 这样比较省事情)

也无非就是这么几步:

1. 安装 simsun.ttf 字体, 美化字体
2. 安装中文locale
3. 安装中文输入法

原文出处: http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=office&Number=511481&page=&view=&sb=&o=

[@more@]


1. 安装 simsun.ttf 字体:
# mkdir /usr/share/fonts/truetype/simsun
# cd /usr/share/fonts/truetype/simsun
# cp /mnt/gentoo/usr/share/fonts/truetype/simsun/SIMSUN.TTF . (将 Simsun 字体拷贝过来)
# mkfontscale (生成 font.scale 文件)
# cp fonts.scale fonts.dir

# vi /etc/X11/XF86Config-4
在相应的地方加入如下行:
FontPath "/usr/share/fonts/truetype/simsun"

2. 安装中文系统

安装 locale:
# apt-get install locales
选择 en_US en_US.ISO-8859-15 en_US.UTF-8 zh_CN zh_CN.GB18030 zh_CN.GBK zh_CN.UTF-8。选择 zh_CN 作为缺省的 locale。

安装中文输入法:
# apt-get install fcitx

安装词典:
# apt-get install stardict
# exit
$ mkdir ~/.stardict
$ cp /mnt/gentoo/usr/share/stardict/dic ~/.stardict -r
(将gentoo的词典拷过来用)

3. 美化字体

# vi /etc/fonts/fonts.conf
1) 在所有的 AR PL KaitiM GB 前插入 SimSun,并将其后面的 SimSun 删掉,让系统先找 SimSun 字体。

2) 为了不让字体模糊,在文件后面(前)加入: (FIXME)

4. 修改 .xsession,形成中文环境

$ vi .xsession
将其内容修改为:
export G_BROKEN_FILENAMES=1
export LANG=zh_CN
export LC_ALL=zh_CN
export XMODIFIERS="@im=fcitx"
fcitx &
gnome-session || exec xterm

然后退出 session 在重新登录就能在漂亮中文环境下生活了。

2005年1月8日星期六

vim-cream的菜单国际化支持

前几天给vim-cream的菜单做了一下国际化(i18n)支持,仿照vim自己的菜单i18n方法写的。
当然同时还做了简体中文的翻译(可到我的主页下载cream-menu-lang.zip)

前日才有机会发给cream的群组,今日收到cream的开发者回信说接受了,并且0.33版本将考虑更多的国际化支持(而不仅仅是菜单)。

以下是菜单国际化的支持补丁,但需要针对自己的语言编写菜单翻译脚本放到cream/lang目录下(参见我的中文翻译范例)

(Here is the patch for i18n of the menu. But you need to write the menu translation script for your own language. Check my translations for Simplified Chinese as an example)

--- cream-menu.vim.orig 2004-02-02 22:23:18.000000000 +0800
+++ cream-menu.vim 2004-12-02 11:52:18.000000000 +0800
@@ -21,6 +21,57 @@
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
" 02111-1307, USA.
"
+function! Load_menu_translation()
+ " copied from vim's own menu.vim, with a little modification
+if exists("v:lang") || &langmenu != ""
+ " Try to find a menu translation file for the current language.
+ if &langmenu != ""
+ if &langmenu =~ "none"
+ let s:lang = ""
+ else
+ let s:lang = &langmenu
+ endif
+ else
+ let s:lang = v:lang
+ endif
+ " A language name must be at least two characters, don't accept "C"
+ if strlen(s:lang) > 1
+ " When the language does not include the charset add 'encoding'
+ if s:lang =~ '^aa|^aa_aa'
+ let s:lang = s:lang . '.' . &enc
+ endif
+
+ " We always use a lowercase name.
+ " Change "iso-8859" to "iso_8859" and "iso8859" to "iso_8859", some
+ " systems appear to use this.
+ " Change spaces to underscores.
+ let s:lang = substitute(tolower(s:lang), '.iso-', ".iso_", "")
+ let s:lang = substitute(s:lang, '.iso8859', ".iso_8859", "")
+ let s:lang = substitute(s:lang, " ", "_", "g")
+
" Remove "@euro", otherwise "LC_ALL=de_DE@euro gvim" will show English menus
+ let s:lang = substitute(s:lang, "@euro", "", "")
+ " Change "iso_8859-1" and "iso_8859-15" to "latin1", we always use the
+ " same menu file for them.
+ let s:lang = substitute(s:lang, 'iso_8859-15=', "latin1", "")
+ menutrans clear
+ exe "runtime! cream/lang/menu_" . s:lang . ".vim"
+
+ if !exists("did_menu_trans")
+ " There is no exact match, try matching with a wildcard added
+ " (e.g. find menu_de_de.iso_8859-1.vim if s:lang == de_DE).
+ let s:lang = substitute(s:lang, '.[^.]*', "", "")
+ exe "runtime! cream/lang/menu_" . s:lang . "*.vim"
+
+ if !exists("did_menu_trans") && strlen(LANG) > 1
+ " On windows locale names are complicated, try using LANG, it might
+ " have been set by set_init_1().
+ exe "runtime! cream/lang/menu_" . tolower(LANG) . "*.vim"
+ endif
+ endif
+ endif
+endif
+endfunction
+

function! Cream_menus()
" Creates each menu loader and calls it
@@ -60,5 +111,7 @@ function! Cream_menus()
let &cpo = cpo_save

endfunction
+source VIMRUNTIME/delmenu.vim
+call Load_menu_translation()
call Cream_menus()



Powered by ScribeFire.

2005年1月1日星期六

Nokia S60上的Python

早上到公司看到python-chinese的邮件列表里说nokia开始为s60系列的提供python包,跟着连接到nokia网站上看了一下附带的 文档,里面有一些截图,还有interactive console,weather和feedreader等几个例子,而且说明是有ui扩展的.

相关网址:
Slashdot上的新闻
http://developers.slashdot.org/article.pl?sid=04/12/22/1533241&from=rss

CSDN上的新闻
http://www.csdn.net/news/newstopic/19/19130.shtml

Python-chinese邮件列表上的讨论(我最开始看见信息的地方)
http://python.cn/pipermail/python-chinese/2004-December/007200.html

Nokia网站
http://www.forum.nokia.com/main/0,,034-821,00.html

Nokia 6600还是Dopod 565?


翻 了移动"存话费, 送手机"活动的宣传材料,nokia的手机有一款6600,查了一下,倒也是s60系列之一,可以支持python。问题是这款手机样 子我不太喜欢,胖胖的样子(同事蒋亮说它绰号"胖六" :-) 。而且nokia网站上的资料显示,它是一年半以前推出的。

但我对 python的喜爱是显然的。所以问题就来了,到底是买dopod 565呢还是nokia 6600呢?dopod采用windows modile, 在上面扩充python是否容易呢?如果现在没有,以后会出现么?毕竟这个windows mobile跟自己熟悉的操作系统windows是比较熟悉 的(相对于那个symbian而言),而词霸什么的我也很喜欢,可能还有那个total commander(也不知道windows ce与 windows mobile是不是一回事或者兼容).

不知道哪些支持java的能不能跑Jython――尽管Java的运行速度和块头总是问题