PEAR の XML_RPC には UTF-8 の文字列の取扱いに不具合があるようで、UTF-8 固有の文字を送信すると文字化けします。例えば、タイトルに挙げた波ダッシュや単位記号(cmやkg)などがこれにあたります(波ダッシュについては、Wikipedia の記事が参考になります)。
解決方法としては、文字列を渡す前にあらかじめ別の文字列に置換しておき、返ってきた結果に対して、逆の置換を行うことが考えられます。例えば、
require_once 'XML/RPC.php';
$str = (XML_RPCに渡す文字列)
// 以下の部分で全角チルダと波ダッシュをいったん naminamimoji に置換
$str = preg_replace('#\xEF\xBD\x9E#i', 'naminamimoji', $str);
$str = preg_replace('#\xE3\x80\x9C#i', 'naminamimoji', $str);
$params = new XML_RPC_Value(
array(
'body' => new XML_RPC_Value($str, 'string'),
'score' => new XML_RPC_Value(50, 'int'),
),
'struct'
);
$msg = new XML_RPC_Message('hatena.setKeywordLink', array($params));
$cli = new XML_RPC_Client('/xmlrpc', 'd.hatena.ne.jp');
$resp = $cli->send($msg);
if (!$resp) {
echo 'Communication error: ' . $cli->errstr;
exit;
}
if (!$resp->faultCode()) {
$val = $resp->value();
$data = XML_RPC_decode($val);
$ret_val = $data;
} else {
/*
* xmlrpc.php スクリプトが遭遇した問題を
* 報告する
*/
echo 'Fault Code: ' . $resp->faultCode() . "\n";
echo 'Fault Reason: ' . $resp->faultString() . "\n";
$ret_val = $data;
}
// 置換していた文字を元に戻す
$ret_val = str_replace('naminamimoji', '〜', $ret_val);
ただ、この方法は例で挙げたはてなキーワード自動リンクAPIのように、入力される一部の文字を無視しても実用上問題がない場合には効果的ですが、入力される文字列自体が重要な場合(検索など)の場合にはうまくいきません。
おそらく内部でエンコードの変換を行っていることが原因だと思うのですが、ちょっと困りものです。
