Apache XML-RPCではまったこと
Apache XML-RPCを使ってみたところ、、、日本語を使用すると以下のようなエラーが。
java.io.IOException: Invalid character data corresponding to XML entity 日 at org.apache.xmlrpc.XmlRpcClient$Worker.execute(XmlRpcClient.java:444) at org.apache.xmlrpc.XmlRpcClient.execute(XmlRpcClient.java:163) at info.fractus.coli.test.XmlRpcTest.main(XmlRpcTest.java:35)
色々調べて「XmlRpc.setEncoding("UTF-8");」だの「XmlRpc.setDriver(org.apache.xerces.parsers.SAXParser.class);」だのやってみるがこのエラーは消えない。 どうもさらにグーグルで彷徨っていると文字列を処理するところでキャラクタの範囲を見ているところがありそれがいけないとの情報を発見。英文字圏の人々が使うキャラクタ以外はすべてExceptionを吐く模様。。
ということでCVSからws-xmlrpcのソースをチェックアウトしいじることに。
ソースをチェックした後、依存ライブラリを解凍してできたディレクトリの下にlibというフォルダを作って保存。
- 依存ライブラリ
- commons-codec
- commons-httpclient
- commons-logging
- servlet.jar
このうちservlet.jarはTomcatのディレクトリから適当にコピーしてきてクラスパスに追加。
チェックアウトしてきたソースの中から「XmlWriter#chardata(String text)」の中のコードを以下のように修正。
protected void chardata(String text) throws XmlRpcClientException, IOException { int l = text.length (); for (int i = 0; i < l; i++) { char c = text.charAt (i); switch (c) { case '\t': case '\r': case '\n': write(c); break; case '<': write(LESS_THAN_ENTITY); break; case '>': write(GREATER_THAN_ENTITY); break; case '&': write(AMPERSAND_ENTITY); break; default: if (c < 0x20) // ←ここ { throw new XmlRpcClientException( "Invalid character data " + "corresponding to XML entity " + String.valueOf((int) c) + ';', null); } else { write(c); } } } }
元のソースだと「if (c < 0x20 || c > 0xff)」になってるんですが、2バイト文字があったらExceptionをthrowってちょっと馬鹿にしてますよね!