はじめまして。
現在、Curl Ver4.0 WSDK1.0を使用した、Webシステムに携わっております。
COM.CURL.WSDK.1.0 を使用したSOAP通信にて
レスポンス値が 半角スペース 及び 改行のみのStringである場合
SOAPHTTPRPCPostCaller.call
の戻り値 responses の該当要素では
String の length が 0 になってしまいます。
パケットを監視する http監視上は 正しく受け取れているようですが、
回避策はあるのでしょうか?
まだ4.0使ってるんですか?先日4.0のサポートが切れたと知ってて、あれ、時代の流れが早いなーと感心しました...
確かにXMLの仕様で、スペースと改行が無視されることができるらしく、もうしかして、これはWSDKの仕様かも知れないね、恐らくWSDKの内部実装に依存されている...WSDKのソースコードが公開されているので、ソースコードで調べてみたらどうですか?
ちらっと見ただけですが、soap/SOAPHTTP.scurlの中でSOAPHTTPRPCPostCaller.call が定義されており、
そこからread-message-from-streamというメソッドをコールし、
以下のあたりでresponsesを作っているようです。
let (responses:{Array-of any},
headers:#{Array-of any},
header-roles:#{Array-of #String},
header-must-understands:#{Array-of bool},
root-element-attributes:#{Array-of XMLAttribute}
) =
{self.message-reader.read-rpc-response
xml-input-stream,
.............
}
set responses =
{self.close-response-stream
xml-input-stream,
responses
}
そこらへんにデバッグコードを入れてみたらいかがでしょうか?
XMLにはxmlpace="preserve"が指定されていますか?
heavybugtracker 様
ご返信ありがとうございます。 はい、4.0から今の今までずっと
システム上の要件が追加されても、4.0です。
ついにはサポートがきれましたが...
半角スペース△として △△△△あ△△
といったデータは問題なく受取れますが、△△△△△△といった内容は
trimされてしまうようです。
オープンソースなので、私もある程度(trim-clone などをキーに)追ってみましたが
深くはみれていません。ご指摘のあたりをもう一度追ってみます。
ashimo 様
ご返信ありがとうございます。
なるほど確かにと思い
Contract.scurl の元ネタである wsdl の xml を調べてみると
xml
pace属性 の設定はありませんでした。
オープンソース上でのCurlパーサが
ご指摘の属性を解釈している可能性が高そうですね。
属性を指定して試してみます。ありがとうございました。
xml に xml
pace="preserve" の定義を試してみましたが、うまくいきませんでした。
定義の仕方が間違っているのでしょうか?
それとも、WSDKの仕様でだめなのでしょうか。。。
追記です。
soap/xml-streams.scurl
を追ってみました。
下記のメソッドが、空白のみの場合
要素を空っぽにしてくれちゃってるみたいですが、
要素の中身だけ呼ばれるメソッドではないので、対処方法に苦労中です。
Code:
{method private {check-characters}:void
{if not self.char-buffer.empty? then
{for c in self.char-buffer do
{if not {StreamContentHandler.white-space? c} then
let cs:String = {self.char-buffer.to-String}
{self.events.append
{XMLCharacters
cs,
xml-name-values = {self.string-to-xml-values cs}
}
}
{break}
}
}
{self.char-buffer.clear}
}
}
> 要素の中身だけ呼ばれるメソッドではないので、対処方法に苦労中です。
このメソッドが呼ばれているのはxml-streams.scurl内の4か所だけですね。
$ fgrep -r check-character code/
code/soap/xml-streams.scurl: {method private {check-characters}:void
code/soap/xml-streams.scurl: {self.check-characters}
code/soap/xml-streams.scurl: {self.check-characters}
code/soap/xml-streams.scurl: {self.check-characters}
code/soap/xml-streams.scurl: {self.check-characters}
試してみた限りここの処理では self.char-buffer には内容文字列が入ってきてました。
このソースにもXMLCharactersがありますが、
ヘルプにあるXMLCharactersの以下の記述はこのことを指しているかも?
はずしてたらすみません。
> XML ドキュメント内で XMLStartElement と XMLEndElement の間に空白文字以外のテキストが存在しない場合は、
> XMLInputStream が XMLCharacters を提供できないことがあります。
SAXPaser のイベントからで、
呼ばれる契機は確かに四箇所ですが
要素が値を表すものである場合
{method public {end-element
namespace:String,
local-name:String,
q-name:String}:void
から呼ばれるようです。
そこで、以下のコードで出力を見てみました。
Code:
{method private {check-characters flg:bool = false}:void
{if not self.char-buffer.empty? then
{if flg then
{output "*", self.char-buffer.empty? "*"}
}
{for c in self.char-buffer do
{if not {StreamContentHandler.white-space? c} then
let cs:String = {self.char-buffer.to-String}
{self.events.append
{XMLCharacters
cs,
xml-name-values = {self.string-to-xml-values cs}
}
}
{break}
}
}
{self.char-buffer.clear}
}
}
ContentHandleクラス の end-element は
要素の終了で呼ばれるためそれが値であろうが、単なるxml記述上の改行や空白であろうが
削除してしまいます。
汎用的な改修は難しいかもしれませんが、
項目に特化するならば、local-name、
とあるxmlだけに絞るなら更に namespace を
引数に追加して、強引にスペースを返却させることは可能でした。
Code:
{method private {check-characters flg:bool = false, local-name:#String = null, namespace:#String = null}:void
{if not self.char-buffer.empty? then
{if flg and namespace == "http://temp.openuri.org/Hoge/hogehoge.xsd" then
{switch local-name
case "hoge","hoge_hoge","hoge_desu"
let cs:String = {self.char-buffer.to-String}
{self.events.append
{XMLCharacters
cs,
xml-name-values = {self.string-to-xml-values cs}
}
}
{self.char-buffer.clear}
{return}
}
}
{for c in self.char-buffer do
{if not {StreamContentHandler.white-space? c} then
let cs:String = {self.char-buffer.to-String}
{self.events.append
{XMLCharacters
cs,
xml-name-values = {self.string-to-xml-values cs}
}
}
{break}
}
}
{self.char-buffer.clear}
}
}
もうちょっとうまくやれるかもしれませんね。