ネットワーク経由でXMLメッセージを使用して互いに通信するJavaで記述された2つのアプリケーションがあります。受信側でSAXパーサーを使用して、メッセージからデータを取得しています。要件の1つは、XMLデータにバイナリデータを埋め込むことですが、SAXはこれを好みません。誰でもこれを行う方法を知っていますか?
更新:他の誰かが同様のことを試みている場合に備えて、私はこれをapache commonsコーデックライブラリのBase64クラスで動作させました。
ネットワーク経由でXMLメッセージを使用して互いに通信するJavaで記述された2つのアプリケーションがあります。受信側でSAXパーサーを使用して、メッセージからデータを取得しています。要件の1つは、XMLデータにバイナリデータを埋め込むことですが、SAXはこれを好みません。誰でもこれを行う方法を知っていますか?
更新:他の誰かが同様のことを試みている場合に備えて、私はこれをapache commonsコーデックライブラリのBase64クラスで動作させました。
回答:
base64を使用してバイナリデータをエンコードし、Base64要素に配置できます。以下の記事は、この件に関してはかなり良い記事です。
XMLはとても用途が広い...
<DATA>
<BINARY>
<BIT index="0">0</BIT>
<BIT index="1">0</BIT>
<BIT index="2">1</BIT>
...
<BIT index="n">1</BIT>
</BINARY>
</DATA>
XMLは暴力のようなものです。問題が解決しない場合、XMLは十分に活用されていません。
編集:
ところで、Base64 + CDATAはおそらく最良のソリューションです
(
EDIT2 :私をアップグレードする人は誰でも、本当の答えもアップグレードしてください。SOで最高ランクだったので、貧しい人がここに来て実際に私のメソッドを実装することは望まないでしょう。)
Base64では確かに正しい答えですが、CDATAではない、それは基本的に言っている:「これは何でもかまいません」、しかしそれがなければならないだけで何もすることが、それは、Base64でエンコードされたバイナリデータをする必要があります。XMLスキーマは、Base 64バイナリを、 xsdで使用できるプリミティブデータ型として定義します。
xs:base64Binary
使用するのに適切なデータ型であるデータ型について言及するための追加のポイント。
先週、この問題が発生しました。PDFファイルをシリアル化し、XMLファイル内でサーバーに送信する必要がありました。
.NETを使用している場合は、バイナリファイルを直接base64文字列に変換して、XML要素内に貼り付けることができます。
string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName));
または、XmlWriterオブジェクトに直接組み込まれたメソッドがあります。私の特定のケースでは、Microsoftのデータ型名前空間を含める必要がありました。
StringBuilder sb = new StringBuilder();
System.Xml.XmlWriter xw = XmlWriter.Create(sb);
xw.WriteStartElement("doc");
xw.WriteStartElement("serialized_binary");
xw.WriteAttributeString("types", "dt", "urn:schemas-microsoft-com:datatypes", "bin.base64");
byte[] b = File.ReadAllBytes(fileName);
xw.WriteBase64(b, 0, b.Length);
xw.WriteEndElement();
xw.WriteEndElement();
string abc = sb.ToString();
文字列abcは次のようになります。
<?xml version="1.0" encoding="utf-16"?>
<doc>
<serialized_binary types:dt="bin.base64" xmlns:types="urn:schemas-microsoft-com:datatypes">
JVBERi0xLjMKJaqrrK0KNCAwIG9iago8PCAvVHlwZSAvSW5mbw...(plus lots more)
</serialized_binary>
</doc>
通常、バイナリデータはMIME Base64またはURLエンコーディングでエンコードします。
任意のバイナリからテキストへのエンコーディングでうまくいきます。私はそのようなものを使います
<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
Base64のオーバーヘッドは33%です。
BaseXML for XML1.0のオーバーヘッドはわずか20%です。しかし、これは標準ではなく、まだC実装しかありません。データサイズが気になる場合はチェックしてください。ただし、ブラウザは圧縮を実装する傾向があるため、圧縮は必要ありません。
このスレッドでの議論の後、私はそれを開発しました:XML内のバイナリデータのエンコード:base64の代替。
他の答えはほとんど問題ありませんが、yEncのような、よりスペース効率の良い別のエンコード方法を試すことができます。(yEncウィキペディアリンク)yEncを使用すると、「そのまま」チェックサム機能を利用できます。以下を読んでリンクしてください。もちろん、XMLにはネイティブのyEncタイプがないため、エンコードされたノードを適切に記述するようにXMLスキーマを更新する必要があります。
理由:base64 / 63、uuencodeなどのエンコーディング戦略により。エンコーディングにより、格納および転送する必要があるデータ(オーバーヘッド)の量が約40%(vs. yEncの1〜2%)増加します。エンコードする内容によっては、40%のオーバーヘッドが問題になる可能性があります。
yEnc-ウィキペディアの要約: https : //en.wikipedia.org/wiki/YEnc yEncは、Usenet上のメッセージまたは電子メールを介してメッセージ内のバイナリファイルを転送するためのバイナリからテキストへのエンコードスキームです。... uuencodeやBase64などの以前のエンコーディング方式に対するyEncの追加の利点は、デコードされたファイルがそのまま配信されたことを確認するためのCRCチェックサムが含まれていることです。
オリジナルのバイナリデータをUuencodeすることもできます。この形式は少し古いですが、base63エンコーディングと同じことを行います。
XML形式を制御できる場合は、問題を裏返しにする必要があります。バイナリXMLを添付するのではなく、XMLを含む複数の部分を持つドキュメントを囲む方法について考える必要があります。
これに対する従来の解決策はアーカイブ(たとえばtar)です。ただし、囲んでいるドキュメントをテキストベースの形式で保持する場合、またはファイルアーカイブライブラリにアクセスできない場合は、電子メールとHTTPで頻繁に使用される標準化されたスキームがあり、multipart / * MIMEを使用してContent-Transfer-Encoding:binary。
たとえば、サーバーがHTTPを介して通信し、マルチパートドキュメントを送信する場合、プライマリはバイナリデータを参照するXMLドキュメントであり、HTTP通信は次のようになります。
POST / HTTP/1.1
Content-Type: multipart/related; boundary="qd43hdi34udh34id344"
... other headers elided ...
--qd43hdi34udh34id344
Content-Type: application/xml
<myxml>
<data href="cid:data.bin"/>
</myxml>
--qd43hdi34udh34id344
Content-Id: <data.bin>
Content-type: application/octet-stream
Content-Transfer-Encoding: binary
... binary data ...
--qd43hdi34udh34id344--
上記の例のように、XMLはcid
、Content-Idヘッダーの識別子であるURIスキームを使用して、囲んでいるマルチパートのバイナリデータを参照します。このスキームのオーバーヘッドは、単にMIMEヘッダーになります。同様のスキームは、HTTP応答にも使用できます。もちろん、HTTPプロトコルでは、マルチパートドキュメントを個別のリクエスト/レスポンスに送信することもできます。
データをマルチパートでラップしないようにするには、データURIを使用します。
<myxml>
<data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
</myxml>
ただし、これにはbase64オーバーヘッドがあります。